Проектирование системы с учетом юнит-тестирования
От: Аноним  
Дата: 05.12.12 03:00
Оценка:
Почитав некоторое время про юнит-тестирование систем, сложилось впечатление что что-бы покрыть ее тестами придется во-первых для всех классов выделять интерфейсы что-бы имелась возможность заменять моками, во-вторых практически обязательно использование фреймворков для реализации IoC и моков т.к. иначе будет куча ручной работы.
Насколько это вообще соответствует действительности?
Re: Проектирование системы с учетом юнит-тестирования
От: landerhigh Пират http://www.blinnov.com
Дата: 05.12.12 05:05
Оценка: 2 (2)
Здравствуйте, Аноним, Вы писали:

А>Почитав некоторое время про юнит-тестирование систем, сложилось впечатление что что-бы покрыть ее тестами придется во-первых для всех классов выделять интерфейсы что-бы имелась возможность заменять моками, во-вторых практически обязательно использование фреймворков для реализации IoC и моков т.к. иначе будет куча ручной работы.




А>Насколько это вообще соответствует действительности?


Не соответствует чуть более, чем полностью. Все поставлено с ног на голову в некотором роде.
Чтобы код был тестируем, он должен удовлетворять некоторым критериям тестируемости. Каждый юнит должен быть достаточно изолирован и самостоятелен и не требовать атомной электростанции для запуска. При этом внешние зависимости удобно заменять заглушками или воображалами (для чего, собственно, и выделяются интерфейсы).
В результате получается модульный код, разбитый на изолированные юниты с четко разграниченной ответственностью. Почти священный грааль программирования. Только разница в том, что получается он таким вовсе не в результате кропотливого планирования, а в результате итеративной разработки с применением юнит-тестов.
www.blinnov.com
Re: Проектирование системы с учетом юнит-тестирования
От: samius Россия http://sams-tricks.blogspot.com
Дата: 05.12.12 06:12
Оценка: 8 (1) +3
Здравствуйте, Аноним, Вы писали:

А>Почитав некоторое время про юнит-тестирование систем, сложилось впечатление что что-бы покрыть ее тестами

Акцент все-таки на том, что нельзя в общем случае взять непокрытую систему и покрыть ее юнит тестами, что бы потом сказать "вот юнит тесты для той системы". Система должна была быть специальным образом разработана, либо адаптирована к юнит тестированию.

A>придется во-первых для всех классов выделять интерфейсы что-бы имелась возможность заменять моками

Для всех классов — это, пожалуй, слишком сильное утверждение. Зависит от связанности модулей (юнитов).

A>во-вторых практически обязательно использование фреймворков для реализации IoC и моков т.к. иначе будет куча ручной работы.

Не вдаваясь в тонкости терминологии — нет, не обязательно. Но бывает удобно.

А>Насколько это вообще соответствует действительности?

Более-менее соответствует. Степень соответствия специфична для конкретных систем и их создателей.

Видал систему, написанную без единого теста, но так, будто бы ее писали TDD и после завершения выкинули все тесты. Не скажу что там была толпа интерфейсов. IoC применялся, но без фреймворков.
Re[2]: Проектирование системы с учетом юнит-тестирования
От: Brutalix  
Дата: 05.12.12 07:20
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Чтобы код был тестируем, он ....


А не посоветуешь умную книжку, желательно по-проще, с карнтинками и с упором на выгоды юнит-тестов? (для агитации местного населения)
Re[3]: Проектирование системы с учетом юнит-тестирования
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 05.12.12 12:30
Оценка: 63 (9)
Здравствуйте, Brutalix, Вы писали:

B>Здравствуйте, landerhigh, Вы писали:


L>>Чтобы код был тестируем, он ....


B>А не посоветуешь умную книжку, желательно по-проще, с карнтинками и с упором на выгоды юнит-тестов? (для агитации местного населения)


Книжки нет, но я довольно много писал об этом (и как раз занимался агитацией в своей команде. Успешно).

1. Что значат для вас юнит-тесты?
Как раз о том, что это такое и, главное, какой в них смысл.

2. The Art of Unit Testing
Если собираешься пробивать эту тему, то лучше всего с ней подробнее разобраться. Там много чего полезного описано, включая "продавливание" юнит-тестов в командах.

3. Параметризованные юнит-тесты
Как сделать так, чтобы кода тестов было меньше, а смысла от них (и покрытия в том числе) — больше.

4. Управление зависимостями
Не совсем про юнит-тесты, а про дизайн, но поскольку юнит-тесты — это прежде всего хороший дизайн, то управление зависимостями играет тут ключевую роль.

5. Идеальная архитектура
Опять таки, одним из важных характеристик "хорошести" архитектуры явялется ее независимость, а значит тестируемость. Может тоже чего хорошего найдете.
Re[3]: Проектирование системы с учетом юнит-тестирования
От: landerhigh Пират http://www.blinnov.com
Дата: 05.12.12 12:35
Оценка:
Здравствуйте, Brutalix, Вы писали:

L>>Чтобы код был тестируем, он ....


B>А не посоветуешь умную книжку, желательно по-проще, с карнтинками и с упором на выгоды юнит-тестов? (для агитации местного населения)


Честно говоря, сам хочу найти. Не уверен, что такая существует. Это же сугубо практическая вещь, теорию на юнит-тестирование натягивать ИМХО бесполезно.
По опыту, агитация действует не очень. Лучше всего работает быстрый проект, которым рулит евангелист TDD или просто юнит-тестирования (в завсимости от публики ему может быть очень желательно быть еще и фашистом или просто диктатором)
www.blinnov.com
Re[3]: Проектирование системы с учетом юнит-тестирования
От: pik Италия  
Дата: 05.12.12 13:03
Оценка:
Здравствуйте, Brutalix, Вы писали:


B>А не посоветуешь умную книжку, желательно по-проще, с карнтинками и с упором на выгоды юнит-тестов? (для агитации местного населения)


с картинками

http://msdn.microsoft.com/en-us/library/jj159345.aspx
Re[4]: Проектирование системы с учетом юнит-тестирования
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 05.12.12 13:14
Оценка: 19 (4)
Здравствуйте, landerhigh, Вы писали:

B>>А не посоветуешь умную книжку, желательно по-проще, с карнтинками и с упором на выгоды юнит-тестов? (для агитации местного населения)


L>Честно говоря, сам хочу найти. Не уверен, что такая существует. Это же сугубо практическая вещь, теорию на юнит-тестирование натягивать ИМХО бесполезно.

L>По опыту, агитация действует не очень. Лучше всего работает быстрый проект, которым рулит евангелист TDD или просто юнит-тестирования (в завсимости от публики ему может быть очень желательно быть еще и фашистом или просто диктатором)

В упомянутой выше The Art of Unit Testing есть целый раздел по поводу продвижения (как я уже сказал выше).
А продвигать приходится как всегда: примером, причем желательно собственным и позитивным (т.е. они для вас должны приносить пользу).

Как-то недавно пробегал твит от кого-то из TDD-гуру: что если бы каждый раз, когда юнит-тест находил баг, человек бы подпрыгивал и кричал "Ура! Тест сработал!", то все значительно лучше бы осознавали их ценность

Если серьезно, то очень здорово покрыть тестами (юнит или интеграционными) наиболее хрупкие части системы, и показывать их преимущества изо дня в день.

Помимо этого может сработать ненавязчивое проталкивание этой техники во время код- или дизайн-ревью с помощью вопросов:

Ты: — Вот смотри, как бы ты писал юнит тест для своего класса/модуля?
Он: — Ну, не знаю, а зачем мне это нужно, да и вообще, сложно это...

Ты: — Ну раз ты не можешь написать юнит-тест, значит ты не можешь думать о своем классе/модуле в изоляции. А значит у него нет четких входов/выходов (или их слишком много), что говорит о проблемах с дизайном. Если модуль тяжело протестировать, то его будет тяжело (или невозможно) использовать в другом контексте, что ставит полный крест на повторном использовании.

Он: — Ну ладно, но все равно, как-то не хочется из-за таких "мелочей" тратить время.

Ты: — А ты посмотри с другой стороны: ты не просто тратишь время один раз, ты бережешь его для себя и своей команды в будущем. Ведь тесты можно использовать, как еще один клиент твоего класса/модуля. Нормальный тест будет является своего рода источником спецификации системы и мы можем использовать эту информацию повторно. Да и вообще, ведь тебе, чтобы доделать задачу, все равно придется потратить время на запуск всей этой сложной системы, причем делать это придется каждый раз и не только тебе, но и твоим коллегам. Юнит-тест может просто сберечь твое время, поскольку ты сможешь потратить времени в 10 раз меньше на проверку этой маленькой функции.
Он: — Ну, не убедил окончательно... А какие есть у этого дела еще выгоды?

Ты: — Ну, если этого мало Давай подумаем об интеграции. Ведь у нас постоянная проблема с параллельной разработкой упирается в интеграцию. Вспомни, как ты с Васей долелали куски одной задачи и начали их интегрировать. На задачу ушло неделю, а потом вы бились головами еще три недели, чтобы объединить эти два куска и заставить их работать вместе. Тест дают некоторый формализм и значительно упрощают интеграцию. Ты вспомни того же Буча: любая сложная система строится на основе проверененных маленьких строительных блоков. А как нам получить проверенные строительные былоки, если мы не будем тестировать их вначале в изоляции? Вот и получается, что у нас есть огромная плоская система, на которой мы постоянно проверяем эффект бабочки: изменяем одну часть системы, а в продакшне летит совершенно другая ее часть.
Ну и не забывай о рефакторинге: без тестов (юнит и интеграционных) мы не можем зафиксировать текущее поведение, чтобы изменить ее внутреннюю реализацию. Тесты выступают в роли таких себе "тисков", в которые мы зажимаем систему, чтобы она не дергалась. Без этого процесс рефакторинга становится совершенно неуправляемым, а ведь мы-то с тобой знаем, что придет время, когда мы с тобой скажем: "А давай-ка тут немного переделаем!", так давай заложимся на это с самого начала.
Он: — Ну ладно, так давай подытожим, чего же мы получим в результате.

Ты: — Ну, ладно, вот небольшой список пользы юнит-тестов:
1. Юнит-тесты — лакмусовая бумажка плохого дизайна. Если у нас нет мыслей, как это дело потестить, то с дизайном явно что-то не то.
2. Юнит-тесты — дополнительный источник спецификации системы. Код сам по себе не может быть правильным или не правильным. Все зависит от того, что мы от него ожидаем (а тесты как раз и показывают "ожидаемое" поведение системы).
3. Юнит-тесты помогают использовать повторно наши усилия: подумать раз и заперсистентить наши мысли в форме тестов.
4. Юнит-тесты могут даже ускорить разработку. Если для проверки фичи нужно 5 минут, то 20 минут на написание теста с последующей секундной проверкой будет более эфективным использованием времени даже в краткосрочной перспективе.
5. Юнит-тесты упрощают интеграцию. Хорошо продуманные кусочки легко объединять и, что самое главное, легко "перемещать" из одного места системы в другое.
6. Юнит-тесты — это — это необходимый background для рефакторинга. Без них рефакторинг превращается в серьезную авантюру.

Но есть и явный вред от них:
1. Плохие юнит-тесты — хуже чем их отсутствие. Они должны тестировать абстракцию, и не вдаваться в подробности реализации. Тест, который постоянно падает будет удален. Тест, в котором невозможно разобраться, будет удален. Тест, который падает через раз — будет удален. Тест, который работает полдня — будет удален. Тест, который постоянно ломается при несущественных изменениях реализации — будет удален.
2. Тесты — не самоцель. Не гонитесь за покрытием, будьте прагматиками. Тестируйте важные части системы и не тестируйте глупости.

А еще рекомендую послушать следующие два подкаста Кента Бека (они очень круто меняют взгляд на юнит тесты):

1. Software Engineering Radio Episode 167 – The History of Junit and the Future of Testing with Kent Beck
2. Development Testing with Kent Beck
Re[4]: Проектирование системы с учетом юнит-тестирования
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 05.12.12 13:16
Оценка: +2
Здравствуйте, landerhigh, Вы писали:


L>Честно говоря, сам хочу найти. Не уверен, что такая существует. Это же сугубо практическая вещь, теорию на юнит-тестирование натягивать ИМХО бесполезно.

L>По опыту, агитация действует не очень. Лучше всего работает быстрый проект, которым рулит евангелист TDD или просто юнит-тестирования (в завсимости от публики ему может быть очень желательно быть еще и фашистом или просто диктатором)

Ни фашист, ни диктатор работать не будет. Чтобы тесты заработали нужно, чтобы люди загорелись. В противном случае, народ накалбасит вам два ведра говно-тестов, стоимость поддержки которых будет выше, чем стоимость поддержки самой системы. Хрупкие тесты — страшная вещь, так что силой здесь ничего не сделать.
Re[5]: Проектирование системы с учетом юнит-тестирования
От: landerhigh Пират http://www.blinnov.com
Дата: 05.12.12 13:27
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Здравствуйте, landerhigh, Вы писали:



L>>Честно говоря, сам хочу найти. Не уверен, что такая существует. Это же сугубо практическая вещь, теорию на юнит-тестирование натягивать ИМХО бесполезно.

L>>По опыту, агитация действует не очень. Лучше всего работает быстрый проект, которым рулит евангелист TDD или просто юнит-тестирования (в завсимости от публики ему может быть очень желательно быть еще и фашистом или просто диктатором)

ST>Ни фашист, ни диктатор работать не будет. Чтобы тесты заработали нужно, чтобы люди загорелись. В противном случае, народ накалбасит вам два ведра говно-тестов, стоимость поддержки которых будет выше, чем стоимость поддержки самой системы. Хрупкие тесты — страшная вещь, так что силой здесь ничего не сделать.


Вот для этого и нужен диктатор-фашист. Люди, прежде чем загореться, будут саботажничать. Намеренно или невольно, но это неважно. Вот этот саботаж и нужно давить в зародыше, и в то же время попытки написания тестов просто на "получи и отвали" должны пресекаться самым жестким образом.
Обычно для всего этого достаточно простого менторинга — люди и правда загораются и сами начинают колбасить тесты, и остается лишь стоять в сторонке да поглядывать. Только достоачно одного дятла, чтобы все испортить. Вот для этих дятлов и нужны ежовые рукавицы.
www.blinnov.com
Re[5]: Проектирование системы с учетом юнит-тестирования
От: artelk  
Дата: 05.12.12 15:22
Оценка:
Здравствуйте, SergeyT., Вы писали:

ST>Ну и не забывай о рефакторинге: без тестов (юнит и интеграционных) мы не можем зафиксировать текущее поведение, чтобы изменить ее внутреннюю реализацию.

ST>6. Юнит-тесты — это — это необходимый background для рефакторинга. Без них рефакторинг превращается в серьезную авантюру.
Тут не без нюансов. Если в рамках рефакторинга меняется дизайн приложения (что чаще всего и бывает), то это требует изменений в юнит-тестах. И обещанных гарантий фиксации поведения уже нет.
На одном из проектов нам в наследство досталась куча сильносвязного кода с багами и без тестов. Было решено сделать глубокий рефакторинг. Из соображений "зафиксировать текущее поведение" заказчик решил покрыть все тестами. Более бессмысленного занятия я не припомню...
Re[6]: Проектирование системы с учетом юнит-тестирования
От: Yoriсk  
Дата: 05.12.12 15:57
Оценка: +2
Здравствуйте, artelk, Вы писали:

A>Тут не без нюансов. Если в рамках рефакторинга меняется дизайн приложения (что чаще всего и бывает), то это требует изменений в юнит-тестах. И обещанных гарантий фиксации поведения уже нет.

A>На одном из проектов нам в наследство досталась куча сильносвязного кода с багами и без тестов. Было решено сделать глубокий рефакторинг. Из соображений "зафиксировать текущее поведение" заказчик решил покрыть все тестами. Более бессмысленного занятия я не припомню...

Потому что не надо юнит-тесты пихать в все щели.
В вашем случае помог бы behaviour(или как он правильно называется?)-подход: на "верхние" интерфейсы пишутся тестовые сценарии, прогоняющие типичные use-cases, юнит-тесты выкидываются и дальше все потроха рефакторятся с единственной оглядкой на проходжение сценариев.
Re[4]: Проектирование системы с учетом юнит-тестирования
От: Jericho113 Украина  
Дата: 06.12.12 09:00
Оценка:
Здравствуйте, pik, Вы писали:

B>>А не посоветуешь умную книжку, желательно по-проще, с карнтинками и с упором на выгоды юнит-тестов? (для агитации местного населения)

pik>с картинками
pik>http://msdn.microsoft.com/en-us/library/jj159345.aspx

Кстати об этой книжке- стоит на нее время тратить???
Кто нибудь хотябы частично реализовал предложенное в ней на реальных проектах?

Поясню свой интерес — у меня тут появился проект уже запущеный в продакшен (MVC3 + DAO самописный (Postgree/MySQL — plain sql /stored procedures) без ORM )
я на пректе не работал но сейчас буду единственным его мейнтейнером.
Т.к. новые фичи + исправление старых косяков ляжет на меня то как говорится "не навреди" т.е. не хочется при исправлении багов и добавлении фич
поломать уже работающий функционал и поэтому имхо стоит обложить проект хотя бы высокоуровневыми интеграционными тестами что бы на ранней стадии
увидеть что что то пошло не так.
Может кто уже ходил по тем граблям по которым мне предстоит так что подскажите в какую сторону двигаться?
NetDigitally yours ....
Re[5]: Проектирование системы с учетом юнит-тестирования
От: pik Италия  
Дата: 06.12.12 10:00
Оценка: +1
Здравствуйте, Jericho113, Вы писали:

J>Кстати об этой книжке- стоит на нее время тратить???

J>Кто нибудь хотябы частично реализовал предложенное в ней на реальных проектах?

я то сам толъко пробежался по ней и рекомендации датъ не могу.
был на МС-конференции там нам это расписывали как чудо инновации МСа
собственно что имеем? а то что те юнит-тесты котрые ранъше вручную писали и код для этого "нагибали" затем или выкидывали или отделъно от проекта надолго кудато запихивали — теперъ
имеют автоматический механизм и целую кучу инструментария, всё хранится с проектом и всегда готово к запуску. преимущества конечно существенные. но это не интергарционны тесты и то что вы описали — это не то. вы не хотите ломатъ старые структуры и созданный код рефакторизироватъ а толъко пару тестов для скорре успокоения души так сказатъ написатъ. такой подход с точки зреноя МС и коекаких существующих авторов книг — не правилен. старый код(legacy code) нелъзя еффектифно без рефакторинга юнит тестами покрытъ. естъ мнение что именно юнит-тесты помогают даже старый код как положено рефакторироватъ(или как там по русски?)
короче: если речъ идёт о юниттестировании — то вам придётся весъ код перелопатитъ и много времени инвестироватъ в это но тогда будет и еффект. код не трогатъ а пару интеграционных тестов завести — по моему смысла совсем не имеет или оченъ мало ибо это и так всегда разработчиком делается и вполеслдствии тестерами, всё осталъниое в более-менее сложных пректах — нереалъно
Re[7]: Проектирование системы с учетом юнит-тестирования
От: artelk  
Дата: 06.12.12 11:50
Оценка:
Здравствуйте, Yoriсk, Вы писали:

Y>Потому что не надо юнит-тесты пихать в все щели.

Надо, если их делать с самого начала проекта.
Y>В вашем случае помог бы behaviour(или как он правильно называется?)-подход: на "верхние" интерфейсы пишутся тестовые сценарии, прогоняющие типичные use-cases, юнит-тесты выкидываются и дальше все потроха рефакторятся с единственной оглядкой на проходжение сценариев.
Ну да, все закончилось функциональными и самыми "общими" интеграционными тестами.
Я это к тому, что при глубоком рефакторинге юнит-тесты нифига не помогают что-то там зафиксировать.
При рефакторинге они помогают главным образом в другом — проверить насколько удачный дизайн получился после рефакторинга, т.е.
1. Слабосвязный (и, как следствие, гибкий), благодаря чему юнит-тесты легко писать
2. Простой, благодаря чему юнит-тесты легко читать
Re[7]: Проектирование системы с учетом юнит-тестирования
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 09.12.12 13:04
Оценка:
Здравствуйте, Yoriсk, Вы писали:

Y>Потому что не надо юнит-тесты пихать в все щели.


Проблема в том, что апологеты юнит-тестирования как раз таки именно это и предлагают.

Y>В вашем случае помог бы behaviour(или как он правильно называется?)-подход: на "верхние" интерфейсы пишутся тестовые сценарии, прогоняющие типичные use-cases


Это называется функциональное тестирование.
... << RSDN@Home 1.2.0 alpha 5 rev. 66 on Windows 8 6.2.9200.0>>
AVK Blog
Re[5]: Проектирование системы с учетом юнит-тестирования
От: AndrewVK Россия http://blogs.rsdn.org/avk
Дата: 09.12.12 13:04
Оценка: 2 (1)
Здравствуйте, Jericho113, Вы писали:

J>Кстати об этой книжке- стоит на нее время тратить???


Конкретно эту книжку не смотрел, но вообще MS P&P весьма вменяемые вещи обычно делает.

J>Кто нибудь хотябы частично реализовал предложенное в ней на реальных проектах?


Так это, оно ведь как раз на основе реально реализованных проектов пишется. Постфактум.
... << RSDN@Home 1.2.0 alpha 5 rev. 66 on Windows 8 6.2.9200.0>>
AVK Blog
Re[8]: Проектирование системы с учетом юнит-тестирования
От: Yoriсk  
Дата: 10.12.12 14:41
Оценка:
Здравствуйте, artelk, Вы писали:

Y>>Потому что не надо юнит-тесты пихать в все щели.

A>Надо, если их делать с самого начала проекта.

Угу. А если система есть а их нет, то надо начать с самого начала, написать никому не нужные юнит тесты потому что как же мы без священной коровы.

A>При рефакторинге они помогают главным образом в другом — проверить насколько удачный дизайн получился после рефакторинга, т.е.


Это, мягко говоря, спорно.
На практике я почему-то вижу, что эта пресловутая "слабосвязанность" достигается именно тем, что описал топик стартер: какой-то горой никому(кроме тестов) не нужных итерфейсов один в один повторяющих методы класса, абстракций, прокси, прокси на прокси и т.д.
Еще очень хорошая практика для тестируемости делать приватные приватные переменные не совсем приватными(иначе как же тест их замокает?). Апофеозом адхитектуры для тестирования может стать вообще отказ от ООП: есть отдельно какие-то данные, есть отдельно набор методов-функций разной степени чистоты. Всё отлично изолировано, всё хорошо тестируется, всё непойми как работает(и не работает).

Вобщем может быть так а может и иначе, лёгкость тестирования вам ничего не гарантирует.

A>2. Простой, благодаря чему юнит-тесты легко читать


Никогда не видели, как юниттесты легко читать, всё ими обложено, всё зелёное, а "в целом" всё падает чуть более чем постоянно?
Re[9]: Проектирование системы с учетом юнит-тестирования
От: landerhigh Пират http://www.blinnov.com
Дата: 10.12.12 23:57
Оценка: :)
Здравствуйте, Yoriсk, Вы писали:

Y>Здравствуйте, artelk, Вы писали:


Y>>>Потому что не надо юнит-тесты пихать в все щели.

A>>Надо, если их делать с самого начала проекта.

Y>Угу. А если система есть а их нет, то надо начать с самого начала, написать никому не нужные юнит тесты потому что как же мы без священной коровы.



Все же этому форуму очень не хватает смайлика "рука лицо".
www.blinnov.com
Re[10]: Проектирование системы с учетом юнит-тестирования
От: Yoriсk  
Дата: 11.12.12 14:19
Оценка:
Здравствуйте, landerhigh, Вы писали:

L>Все же этому форуму очень не хватает смайлика "рука лицо".


Абсолютно согласен. Вот вы, например, пишите, что заявление топикстартера "не соответствует <действительности> чуть более, чем полностью" и тут-же парой строчек ниже сообщаете, что да, прийдётся на каждый пук писать прокси и интерфейсы выделять и, следовательно, как-то мапить их на классы, а там уже и IOC фреймворк для этого а значит, и т.с. вроде как и прав и всё соответствует действительности чуть более чем полностью...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.