Tuesday, February 10, 2009

TDD и покрытие кода тестами

Написал развернутый комментарий на тему "Юнит тесты и TDD" в блог bishop-it.ru, после чего он благополучно обрезался и половина пропала - наверное сработало ограничение на размер. Полный комментарий публику здесь.

Я решил завести отдельный ярлычок "Комментарии" для таких постов, думаю их будет больше одного.

--- Cut ---

Что значит 100% покрытие кода тестами? :)

На первой лекции по тестированию нам привели пример программы из 10 строк кода с двумя вложенными циклами и показали, что чтобы полностью проверить работу этого кода нужно выполнить 10^18 операций :) Я думаю тестировщики знают про это.

TDD - это вовсе не о тестировании и не о покрытии кода тестами. Я вообще не понимаю откуда возникла цифра 100% - я много читал/смотрел/использовал TDD, но никогда не слышал о связи TDD и покрытии кода тестами.

Соглашусь с Андреем Валяевым, что TDD - это подход к разработке, который позволяет разработчикам (а не тестировщикам) облегчить жизнь. И именно по этой же причине, если я правильно понимаю, TDD нравится автору поста.

TDD != тестирование.

Тем более тестирование GUI (и все что касается GUI вообще), которое я вообще считаю шаманством и даже не пытаюсь туда лезть :) Единственное, что я могу понять в тестировании GUI и действительно использую - это ручное тестирование (отредактировать, запустить, проверить UI). Я могу это делать сам (и делаю) или могу отдать специально обученному человеку (и отдаю), который проверяет работу системы по заранее написанным сценариям, составленным по ТЗ.

Unit-тесты позволяют сократить цикл "отредактировать, запустить, проверить", если я тестирую логику - потому что для логики есть API и я могу написать Unit-тест. Особенно если речь идет об утилитарных методах/классах типа парсинга текста, вычисления дат и прочих мелочей.

Типичный случай моего использования TDD - если нужно разработать интерфейс сервиса (или бизнес-логики или API, называйте кому как нравится) и проверить его работу.

Unit-тест - это не интеграционный тест (то есть мы уже не можем получить 100% покрытие функциональности; как я говорил выше есть еще тестирование GUI - также вычтите эту часть из 100%), но основные потоки использования сервиса (его интерфейс + usecase) описать и протестировать можно.

TDD очень часто спасал, когда чесались руки спроектировать супер-пупер универсальную иерархию классов - он просто не дает это сделать, позволяя сосредоточиться на требуемом поведении в рамках четко зафиксированных требований. В качестве таких требований я обычно использую основной поток usecase'а.

TDD позволяет придерживаться принципа KISS и он мне нравится уже только поэтому.

Unit-тест TDD - это тестирование логики как черного ящика, что опять же не дает 100% покрытия.

Одно замечание по поводу "кандалов" тестов. Я никогда не пишу тесты, которые бы мне было жалко удалить и переписать. Не нужно проектировать Unit-тесты - достаточно ограничиться рамками метода теста. В этом плане я считаю хорошей практикой написания Unit-тестов TDD подход Copy-Paste.

P.S.

В начальном посте очень много говорится о 100% покрытия кода тестами, а что означает "покрытие кода" автор не приводит. Я думаю и у тестировщиков (что уж там о девелоперах говорить), одного показателя, который измеряется в процентах - нет.

Да, есть инструменты, которые позволяют измерить Code Coverage (например, Cobertura).

Да, они позволяет получить несколько показателей покрытия, но по сути - это такая же размытая оценка о покрытии тестами кода, как и оценка сложности ПО по размеру кода программы в строках.

Такие методики могут быть полезными при оценке проектов, но никак при разработке, и уж точно ничего не говорят о самой методике TDD.

--- Cut ---