Как стать автором
Обновить

Комментарии 28

Семинары с пиццей — это всегда хорошо :)
Статья интересная, но есть одно замечание — почему книга Kent Beck's Test Driven Development: By Example отнесена к .NET? В ней два примера, один на Java, другой на Python
В книге описывается хорошо сам принцип TDD на примерах, а в качестве тестового фреймворка используют xUnit, что не вызывает сложности в проецировании на NUnit
Согласен что для .net наиболее уместна «The Art of Unit Testing» от Roy Osherove
Кстати, на правах пиара — сейчас развивается подобное русскоязычное сообщество Russian Software Craftsmanship Community. Мы проводим два типа встреч — XP Battle (ежемесячные встречи с целью изучения одной из инженерных практик) и Code&Coffee (утренние встречи с целью покодить в свободной обстановке). Так же зову всех в группу на FaceBook. В планах есть и CodingDojo, и StudyGroup для изучения книг и многое другое.
Кстати, было бы интересно услышать мнение людей, минусующих статья — что их не устроило?
Я не ставил минуса, но близок к этому. Дело в том что не совсем понимаю, а что нового в этой статье? На хабре как минимум 5 статей по поводу TDD. Хаброюзеры чего только не обсудили в комментариях к ним. Каких только статей и книг друг другу не на советовали. Что конкретно еще не знает хабр? Я бы хотел это услышать в первых словах перед статьей, к примеру Вы могли бы предварить словами: «От переводчика: на хабре еще не было ...» или что-то в этом духе.
Спасибо, обновил пост.
Кстати, рекомендую:
experience.openquality.ru/alexey-pakhunov-interview/. Очень грамотный текст про TDD.

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

Плюсы которые получил:
1) Более менее уверен в том что сделал хорошо. Однажды пойманная когда-то бага, сейчас проверена и если тест зеленый, то я ее не повторил
2) Проектируя сперва тест, чаще понимаю что и как должно в конечном итоге выглядеть. Достаточно часто вижу «чтото я лажу напридумывал»
3) Если питон-скрипт показывает мне о том, что все плохо, то юнит-тест указывает достаточно часто функцию где конкретно. Экономлю время на поиске баги.

Нерешенные мною вопросы и которые хотел бы узнать:
1) В виду того что я работаю с файлами и достаточно часто возникает ситуация, когда мне надо подавать разные файлы, то что лучше сделать: 1.1. один файл — один тест или 1.2. setUp должен «кушать» объект конфигурации, которую можно задавать во внешнем ini-файле? Если второе, то это мне кажется нарушает концепцию юнит-тестов
Первый вариант более правильный, имхо, так как если что, неактуальный тест проще удалить и написать заново, чем пытаться что-то разобрать в связке unit-тестов. По поводу второго варианта — есть возможность задавать данные не из внешнего файла, а из кода; наглядный пример — TestFabric в TestNG для Java. Думаю что-то похожее есть, я думаю, и для других фреймворков/языков.

P.S.: мое имхо, если unit-тест, особенно написанный в процессе TDD, работает с файлами, то это уже не unit-тест, а интеграционный. По-крайне мере я это видел в ряде литературы.

P.P.S.: за ссылку спасибо, интересно!
Ппо миинус номер один: время потраченное на тдд возвращается сторицей. Я заметил, что все чаще и чаще код начинает работаьь сразу. Все чаще и чаще рефакторнги в 1000 строк до 300 не наносят вреда информационной системе в целом. Т.о. сейчас, потратив два часа на тесты, на выходе, получаю 5 часов экономии на отладке, и это при том что писатель тестов из меня, скажем, так себе. Это же распространяется на уже готовый код…
Про минус номер два: гораздо больше падает настроение после того как приходит шеф и негодует
При минус номер три: если среда разработки интерпретируема, то тесты могут проходить в режиме (autotest). И, как показывает моя практика, после очередного перекура, или после обеда, или, в тяжелых случаях, к утру, тесты догоняют внесенные изменения в покрытый тестами код. Т.о. мне удалось добиться ситуации, когда я пишу и никого неттрогаю, а оно тестируется помигивая push-уведомлениями.
А я и не говорил, что это минусы. Мною было написано «мой опыт». Написал лишь то, что нужно учитывать при написании тестов, а то очень многие думают что все дается бесплатно или требует только вложения времени при одноразовом написании тестов.
Наверное только дети думают все дается бесплатно.
Нет, даже начинающие юзать юнит-тесты это могут делать. К примеру, когда я только начал использовать эту методику я писал почти на каждый метод любого класса по 1-2 хорошему случаю и по 5 с ошибками. Это было излишне. Потом пришло понимание как улучшить, а потом что нужно, а что нет и какие задавать себе вопросы перед написанием юнит-теста )
Так этот промах не связан с мнимой бесплатностью тестов. Вы говорите в принципе о том, что не нужно производить действие ради действия. Этот лозунг применим почти везде, не считая некоторых буддистских практик :) Почему излишне писать по 7 тестов на «почти каждый метод» тоже не объясняете. Почему же это излишне? У меня к одному методу написано более 40 тестов, но есть причины не считать это излишним. Практика написания тестов сложна, нужно чтобы пришло понимание почему, зачем и как пишутся тесты. Или почему в отдельных случаях тесты не пишутся совсем. и дело здесь вовсе не в стоимости владения тестами. А ваши пространные комментарии даже меня вводят в заблуждение.
>>действие ради действия
Оно может возникать само собой, т.к. разрабатывая класс, метод можно быть уверенным что пишешь правильно и он не поменяется поэтому надо затестировать. Отсюда вывод: «чем больше тестов, тем больше уверенность что не пропустишь багу».

>>Почему же это излишне?
Потому что разработчик обязан соблюдать компромисс между «скоростью разработки» и «качеством результата», т.е. выдать
«достаточно качественный результат в разумный срок».

В задачу разработчика не входит протестировать абсолютно весь свой результат, ведь для этого есть выделенные тестировщики. Однако ему самому же и выгодно создать тесты там, где они подскажут в след.раз «Где же у него ошибка?» или «Где и что сломалось?».
Поэтому основной навык при использовании юнит-тестов это суметь получить достаточно адекватные ответы на вопросы «Что нужно тестировать, а что нет?» и «Согласуется ли с требованием, задачей каждый написанный мною метод при решении задачи?»

Когда начинаешь использовать юнит-тестирования, то культуры и дисциплины их использования почти на нуле. Все приходит с практикой. Сейчас мое видение такое: «Если разработан метод являющийся точкой входа в модуль\библиотеку нужно написать тесты. 1 в случае правильного использования и по одному на каждый вид ошибки о которой он сигнализирует, ведь отрицательный результат тоже результат. Если это внутренний инструмент используемый в методе первого типа, то нужно обязательно поставить assert хотя бы уровня debug-сборки».
Ну, во первых, если вы думаете о том, нужно ли тестировать тот или иной метод, то это уже не тдд. С юнит-тестированием все относительно просто — не нужно тестирвать очевидные вещи.

Разработчику нужно всячески избегать ситуаций с компромисами. Разработчику нужно выкатить качественный результат в разумный срок. Все остальное от лукавого!

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

На мой взглят юнит-тесты выполняют несколько другие функции. Во первых, метод будет производить именно те вещи которые вам необходимы. Во вторых, изменение конкретного метода не нарушит работу всей системы. Но тесты никак не скажут вам, согласуется ли метод с задачей, например потому, что у вас и у заказчика может быть разное видение задачи и соотвественно решения. Но у ваших тестов и вашего кода видение решения будет согласовано с вашим всегда. Иначе — вы шизофреник, и юниты вам не помогут :)
За свою полезность статья заслуживает плюс, но качество перевода и масса опечаток требуют минуса. Так что я лично воздержусь от оценки.
Так ведь подмена понятий!

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

Таким образом, вы доказали преимущества использования юнит-тестирования, но необходимость внедрения обязательного ТДД лично мне, по-прежнему, кажется более чем сомнительной.
Суть данного поста не сводилась к описанию пользы от TDD, я только хотел передать мысль о том, как его внедрять. Сами преимущества описаны по ссылке.
Ключевые из них, на мой взгляд:
  • Когда пишешь тест в начале, думаешь о том, как написать правильный код
  • Детальная документация кода
  • Эволюционный и адаптивный дизайн

Ну, у вас же написано, что преимущества ТДД якобы очевидны и в качестве «доказательства» дана вот эта самая ссылка, описывающая преимущества. Ну, так я и говорю, что из этих преимуществ очевидно только одно — иногда подход «тесты вперёд» позволяют написать правильный код (хотя чаще просто сносно тестируемый). Остальные относятся к использованию тестов вообще, а не практике ТДД в целом.
Подход «тесты вперед» всегда позволяет писать правильный код и при этом только минимальное количество. Эволюционный и адаптивный дизайн тоже возникает только при TDD. Детальная документация кода возникает когда тестов много — это раз, и когда в тестах проверяется только нужное — это два. Это тоже возможно только когда они появляются в ходе TDD.
И да, TDD это не юнит-тестирование, это дизайн кода через тесты.
>Подход «тесты вперед» всегда позволяет писать правильный код

«правильный» только с точки зрения юнит-тестирования

>Эволюционный и адаптивный дизайн тоже возникает только при TDD

Ого! Сильное заявление! Так таки и «только»? А доказать?

>Детальная документация кода возникает когда тестов много — это раз, и когда в тестах проверяется только нужное — это два

«Детальная документация» в виде юнит-тестов — это не документация. Опять подмена понятий.

>Это тоже возможно только

Опять только? А, по-моему, чушь. Как минимум, существует контрактное программирование, которое большинство этих ваших задач (правильный код, Эволюционный и адаптивный дизайн, Детальная документация!) позволяет выполнить куда лучше, нежели TDD. Да, с TDD тоже можно, но это ведь инструмент для другого, а гвозди лучше забивать молотком, чем отвётркой, хотя отвёрткой тоже можно, конечно, но… хм… зачем? :)

>И да, TDD это не юнит-тестирование

Разумеется. Но обсуждаемые преимущества, кроме сомнительного первого, относятся именно к юнит-тестированию вообще, а не к ТДД частности.
Возникает стойкое ощущение, что вы не прочувствовали TDD, потому что оно является следующим этапом программирования по контракту и позволяет писать только тот код, который нужен на данном этапе с точки зрения требований. Именно отсюда и возникает эволюционный дизайн. Опять же, важным этапом TDD является рефакторинг, одной из задач которого и является приведение архитектуры к стройному виду.

Вообще, с TDD такая же история как с Agile вцелом, каждый понимает его по своему с налета, не пробую посмотреть по сторонам и поучиться у других. Жаль(
>потому что оно является следующим этапом программирования по контракту

Хи-хи-хи. «Даже» BDD является следующим этапом TDD (особенно по части документирования кода — не пожелаю даже и врагу «документацию» в виде тестов и если дело действительно настолько катастрофично сначала всё-равно буду читать непосредственно код). Контрактное программирование не имеет непосредственного отношения наследования к обоим, но по многим критериям превосходит многие преимущества и того и другого.

>Именно отсюда и возникает эволюционный дизайн

Угу. А до ТДД при каждом баге или изменении требований всю систему по-вашему, редизайнили и переписывали заново? Вы очень сильно ошибаетесь.

>Опять же, важным этапом TDD является рефакторинг

См. предыдущий пункт. Нет проблем НЕ далать рефакторинг при ТДД — это легко и просто. Равно как нет проблем делать его без ТДД относительно легко (при хорошем покрытии тестами) либо тяжело (без таковых).

>не пробую посмотреть по сторонам и поучиться у других. Жаль(

Адресую это вам. Похоже вы, «внезапно» открыли для себя ТДД и теперь, как новообращённый адепт восторженно приписываете этой практике всё подряд, присущее ей или нет (подменяя, при этом, понятия) и не пробуете даже посмотреть вокруг. Жаль (

Поверьте, мне, в общем-то, всё равно, нравится оно вам или нет. Просьба только не подменять понятия. Нравиться — ну, каждый извращается по-своему. Приемлите для себя «документацию» в виде юнит-тестов (бррррр) — ну, дело ваше. Но, поверьте, есть вещи поудобнее :).
Не привык принимать что-то на веру — реквестирую примеры вещей поудобнее) и чем программирование по контракту лучше и мощнее?

И да, ТДД я открыл достаточно давно, но это так, к слову)
>реквестирую примеры вещей поудобнее)

BDD в части документирования. Остальное — почти то же самое :)

>чем программирование по контракту лучше и мощнее?

Написанием «правильного» кода. Формулирование контрактов куда более мощный способ заставить себя думать, как написать «правильный код». Тесты — лишь [последующая] проверка частных случаев.
Документирование. Во-первых, она находится «по месту», во-вторых куда более внятная, чем лежащие непонятно где тестs, в-третьих, тесты легко отстают от кода при простом манкировании дисциплиной, с контрактами же проделать такой фокус куда сложнее :).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий