Comments 68
Как Тим Лид настоял, что версия 2.0 одной высоконагруженной распределенной отказоустойчивой системы будем делать в виде TDD. В итоге, сами того не зная, пришли к именованию и грануляции BDD.
Версия 1.0 системы имела всего 300 тестов, исключительно интеграционных.
Теперь же у нас более 3000 юнит тестов и около 50 интеграционных и полная увереность, что система не развалится при малейшем изменении.
TDD/BDD просто единственный путь для систем, малейший сбой которых просто непозволителен.
Версия 1.0 системы имела всего 300 тестов, исключительно интеграционных.
Теперь же у нас более 3000 юнит тестов и около 50 интеграционных и полная увереность, что система не развалится при малейшем изменении.
TDD/BDD просто единственный путь для систем, малейший сбой которых просто непозволителен.
+6
Это высказывание, хоть и абсолютно верное, но вредное, ибо большинство программистов начинает думать, что им TDD/BDD не нужно, так как их система не такая критичная.
На самом деле TDD/BDD позволяет быстрее и комфортнее писать любые системы, а не только отказоустойчивые.
На самом деле TDD/BDD позволяет быстрее и комфортнее писать любые системы, а не только отказоустойчивые.
+2
На чем основано суждение, что «TDD/BDD позволяет быстрее писать любые системы» (про комфорт выкинул, т.к. совсем уж субъективно)? Сколько читал по теме, кто-то из авторов явно, кто-то неявно, но говорят, что исследования по эффективности не проводились?
+1
На моём личном опыте. Мне посчастливилось работать в компании, где все коллеги понимают и используют TDD неукоснительно каждый день — и у нас всё очень хорошо. Быстро и комфортно.
Да, это субъективно. Но мне кажется, если даже вам дадут ссылку на исследование по эффективности TDD, она вас не заставит поверить и начать использовать. А такое вот субъективное мнению — может.
Да, это субъективно. Но мне кажется, если даже вам дадут ссылку на исследование по эффективности TDD, она вас не заставит поверить и начать использовать. А такое вот субъективное мнению — может.
0
Здесь вопрос в области применимости. Исследование покажет когда это эффективно.
То, что у вас вся организация построена под TDD не означает, что вы бы не добились такой же скорости и комфорта без TDD/BDD (есть и другие подходы, которые решают те же проблемы; например, использование аналитиков, архитекторов, тестировщиков). А так же не означает, что любой проект любой команде быстрее писать с использованием TDD/BDD (для упрощения, можно считать, что команда делает не первый, а 3ий проект на TDD).
То, что у вас вся организация построена под TDD не означает, что вы бы не добились такой же скорости и комфорта без TDD/BDD (есть и другие подходы, которые решают те же проблемы; например, использование аналитиков, архитекторов, тестировщиков). А так же не означает, что любой проект любой команде быстрее писать с использованием TDD/BDD (для упрощения, можно считать, что команда делает не первый, а 3ий проект на TDD).
+1
Хочу поспорить по поводу «быстрее» — это абсолютно не так. Когда нужен быстрый time to market следование TDD замедляет в 3 раза. Имеется опыт клиенсткого приложения, который начали делать при помощи TDD и все сильно затянулось, а приложение надо было выпускать очень и очень скоро (специфика рынка) — в итоге пришлось отойти от TDD и делать все по старинке. Потом, конечно, пришлось долго долго дописывать тесты после релиза.
Я бы сказал, что TDD позволяет писать приложения, которые очень просто сопровождать ибо будет 100% увереность, что все работает правильно. Но это нефига не ускоряет разработку.
Я бы сказал, что TDD позволяет писать приложения, которые очень просто сопровождать ибо будет 100% увереность, что все работает правильно. Но это нефига не ускоряет разработку.
+9
Это вопрос навыков. Не надо по оному опыту судить.
На эту темы есть очень простой довод: большая часть времени уходит не на написание (кода), а на продумывание. Это время вы тратите по-любому, ведь продумывать свои действия надо, так? Ну а если вы оформляете промежуточные результаты своего мыслительного процесса в виде тест-кейсов, то идти он должен проще и стабильнее. Это всё равно что каждую следующую мысль записать на бумажку.
На эту темы есть очень простой довод: большая часть времени уходит не на написание (кода), а на продумывание. Это время вы тратите по-любому, ведь продумывать свои действия надо, так? Ну а если вы оформляете промежуточные результаты своего мыслительного процесса в виде тест-кейсов, то идти он должен проще и стабильнее. Это всё равно что каждую следующую мысль записать на бумажку.
0
У меня на одном из проектов, который пробовали делать по TDD, значительная часть времени уходила на изменение тестов. Т.е. фактически старые тесты не поймали ни одной ошибки, а поверх писались уже новые тесты. Никакого особого продумывания для классического mvc-веб-приложения не требуется (время на продумывание относительно времени на написание тестов). Естественно, до этого уже есть некая проектная документация (описание базы, архитектуры, верстка).
+1
Видимо ключевое слово «пробовали». Имхо, ТДД/БДД дает ускорение только когда люди уже привыкли и пишут тесты быстро, а не пробуют.
+2
Не спорю, что при определенных навыках тесты будут писаться быстрее. Но это не снимает необходимость их написания, рефакторинга и обновления под новый функционал. Собственно, интересует когда это оправдано, а когда нет. Ответ «Всегда», который по сути есть в статье представляется несколько оптимистичным.
0
Никакого особого продумывания для классического mvc-веб-приложения не требуется
когда глючит программный код, и архитектура трещит по швам, многие пытаются искать спасения в TDD. проблема в том, что автоматические тесты, это тоже программный код. поэтому его в равной степени можно писать не_правильно, — точно с таким же исходом. :)
у тестов нет задачи «ловить ошибки». ошибки — это лишь следствие — суть, отклонение поведения программы от требуемого (если поведение программного кода отличается от заданного требованием/спецификацией, значит он содержит ошибку). вообще, во главе угла стоят не ошибки, а требования и спецификации.
требования могут быть лишь в вашем воображении, описаны на словах, выражены в схемах и графиках. но лучше, если вы можете сформулировать требование в виде алгоритма: тогда есть возможность выразить его с помощью языка программирования — т.е. написать тест. основное преимущество, которое даёт именно такой способ записи требований — возможность в любой момент и практически *мгновенно* проверить продукт на соответствие (просто «запустив» соответствующий тест). разумеется не каждое требование можно описать в таком виде. существует целый класс нефункциональных требований, которые даны лишь в человеческих ощущениях — и для проверки продукта на соответствие вы будете по-прежнему использовать тестировщиков, пользователей, заказчиков и т.п. медленные и плохо предсказуемые инструменты.
требования могут быть как осмысленными, так и абсолютно бессмысленными (в контексте решаемой задачи). спецификации могут быть недостаточными, избыточными, противоречивыми. а значит всё тоже самое касается и тестов. если нет чёткого представления о том, что вы хотите получить в итоге — нет ни какого смысла писать тест. еще меньше смысла браться что-то «программировать». хотя последнее для «программиста» привычнее.
— эй, вася, что ты такое пишешь?
— еще не знаю, щаз скомпилирую, узнаю.
самое сложное при внедрении TDD это ломка программистского стереотипа: сначала быстро «накодить», ведь и так все ясно, а потом думать зачем, для чего, и исправлять ошибки. :)
как-то так. прошу прощения за дайджест.
+2
Я думаю, неправильно относиться к юнит-тестам как к «тестам».
Смотрите на них как на «спецификации». Ничего, что старые тесты не поймали ни одной ошибки — зато они описывают старые требования к коду. А если появились новые требования к коду, то их тоже надо описать в виде новых тестов. Никакого противоречия тут не вижу.
Если времени на продумывание КОДА особо не требуется, то уж тем более ещё меньше времени потребуется на написание требований к нему.
Смотрите на них как на «спецификации». Ничего, что старые тесты не поймали ни одной ошибки — зато они описывают старые требования к коду. А если появились новые требования к коду, то их тоже надо описать в виде новых тестов. Никакого противоречия тут не вижу.
Если времени на продумывание КОДА особо не требуется, то уж тем более ещё меньше времени потребуется на написание требований к нему.
0
Нет, это не вопрос навыков — а вопрос сроков. Банально надо сроки разработки умножать на 1.5 при использовании TDD ибо объем кода в тестах будет сопоставим, если не больше, с объемом кода самого приложения.
Но это увеличение на 1.5 того стоит, если приложение потом будет иметь долгую жизнь.
А продумывание оформлять в виде тестов — не кажется ли вам, что это только все усложняет? Прототипирование и продумывание я вообще делаю в виде спарков — когда делают хомячковый проект и там обкатываю идею вообще без тестов, а потом переношу ее на проект уже следуя TDD
Но это увеличение на 1.5 того стоит, если приложение потом будет иметь долгую жизнь.
А продумывание оформлять в виде тестов — не кажется ли вам, что это только все усложняет? Прототипирование и продумывание я вообще делаю в виде спарков — когда делают хомячковый проект и там обкатываю идею вообще без тестов, а потом переношу ее на проект уже следуя TDD
0
Кстати, уверенность часто ложная, т.к. шаблоны тяжело действительно хорошо покрыть тестами. Если их много и они достаточно часто меняются, то без носителя знаний проекта (как же оно должно работать и почему пришли к этому) и тестировщика будет сложно.
0
Но ускоряет тестирование? У меня неоднократно бывали случаи, когда тест приходилось прогонять раз по 30 пока не добьешься нужного поведения. Может быть, вы пытались добиться избыточного покрытия тестами?
0
На начальном этапе, когда функциональность невелика, почти все держится в голове TDD действительно может замедлит разработку. Выигрыш будет получен через некоторое время, более-менее долгоживущим системам TDD банально позволяет держаться на плаву, сохраняя устойчивость при рефакторинге и оптимизации самой системы, и, что не менее важно — команды, которая делает систему.
0
ибо будет 100% увереность
<=99% же.
0
Система не развалится. Развалятся ваши 50 интеграционных тестов и некоторые из 3000 юнитов. Не потому что плохо запрограммировано, а наоборот, потому что функционал изменился, и тесты нужно пересматривать.
Чем больше тестов в эволюционирующей системе, тем бОльшая часть времени тратится на их поддержку.
Чем больше тестов в эволюционирующей системе, тем бОльшая часть времени тратится на их поддержку.
+1
Такое случается, если вносить архитектурные изменения где-нибудь через год после начала проекта. В этом случае нужно сходить, сказать ответственному за изменение всё что ты о нём думаешь и садиться рефакторить и код и тесты.
0
Вот и хорошо, что они разваливаются.
Так же это смотря как писать юнит тесты — у нас почти 99% тестов это изолированные тесты, где тестируется класс, а все зависимости ему передаются в виде моков интерфейсов. И если надо поменять поведение этого конкретного класса — мы правим тесты этого конкретного класса.
Взаимодействие тестируется на уровне интеграционного теста, когда приложение запускается как черный ящик и проверяются результаты работы.
Так же это смотря как писать юнит тесты — у нас почти 99% тестов это изолированные тесты, где тестируется класс, а все зависимости ему передаются в виде моков интерфейсов. И если надо поменять поведение этого конкретного класса — мы правим тесты этого конкретного класса.
Взаимодействие тестируется на уровне интеграционного теста, когда приложение запускается как черный ящик и проверяются результаты работы.
+2
Почитал про Behat и увидел «Behat is testing applications outside in. It means, that Behat works only with your application's input/output. If you want to test your models — use unit testing framework instead, Behat created for behavior testing (but can be used for anything +) ).» И несмотря на уточнение в скобках, похоже BDD не является заменой надмножеством TDD, а дополняет его.
P.S. Так до конца TDD и не осилил. Часто пишу тесты, которые, имхо, бессмыслены, но как бы нужны, например проверяю, что new MyClass возвращает экземпляр MyClass. Или часто приходится писать кучу «обвязок», только чтобы проверить записывается ли объект в БД, хотя по коду в 2 строки видно, что не записаться он может только по внешним причинам.
P.S. Так до конца TDD и не осилил. Часто пишу тесты, которые, имхо, бессмыслены, но как бы нужны, например проверяю, что new MyClass возвращает экземпляр MyClass. Или часто приходится писать кучу «обвязок», только чтобы проверить записывается ли объект в БД, хотя по коду в 2 строки видно, что не записаться он может только по внешним причинам.
0
Мне тоже интересно найти ответ на вопрос почему BDD может быть заменой TDD.
Вся идея BDD это использовать слова вроде should и ensure. Всё. В чем эволюция?
Почему нужно было создавать столько новых BDD фреймворков, а не оформить BDD в некоторый набор рекомендаций по написанию TDD и использовать существующие фреймворки?
И по-моему, пример №3 лучше чем пример с BDD %)
Вся идея BDD это использовать слова вроде should и ensure. Всё. В чем эволюция?
Почему нужно было создавать столько новых BDD фреймворков, а не оформить BDD в некоторый набор рекомендаций по написанию TDD и использовать существующие фреймворки?
И по-моему, пример №3 лучше чем пример с BDD %)
+4
Моя изначальная цель была показать, что пример №3 лучше, чем №1 и №2, так что я своей цели добился, видимо. :)
Да есть и набор рекомендаций, есть и целые книжки.
Можно было бы и про JUnit сказать: зачем было городить эту библиотеку вместо того, чтобы просто написать рекомендации, как правильно тестировать код?
Можно было бы и про C++ сказать: зачем было городить целый язык вместо того, чтобы просто написать рекомендации, как правильно программировать на ассемблере?
Эволюция — она такая и есть. Каждая следующая версия обезьяны тоже несильно отличалась от предыдущей, а вот глядишь, в конце концов человечек получился.
Да есть и набор рекомендаций, есть и целые книжки.
Можно было бы и про JUnit сказать: зачем было городить эту библиотеку вместо того, чтобы просто написать рекомендации, как правильно тестировать код?
Можно было бы и про C++ сказать: зачем было городить целый язык вместо того, чтобы просто написать рекомендации, как правильно программировать на ассемблере?
Эволюция — она такая и есть. Каждая следующая версия обезьяны тоже несильно отличалась от предыдущей, а вот глядишь, в конце концов человечек получился.
0
Потому что автор топика показывает не Behavior, а Unit-тесты с синтаксисом Behavior-тестов.
На самом деле, основная идея BDD именно в обратном подходе к разработке, а не в синтаксисе. TDD является моделью разработки inside-out (от частного к общему), когда мы гарантируем работу отдельно взятых атомарных модулей и предполагаем, что система в общем, при этом, будет работать нормально. Через некоторое время, было замечено, что это не так и что верная работа отдельных модулей вовсе не гарантирует верную работу системы в целом.
Появилась потребность в тестировании системы в общем. Такую модель разработки назвали outside-in (от общего к частному) или BDD. Смысл сводится к тому, что мы также сокрываем реализацию в черный ящик и работаем только с выходами/входами, только не отдельных модулей, а всей системы в целом (веб-приложение — Request/Response, консольное приложение — Arguments/Output). Оказалось, что подобную логику легче описывать на специфических терминах типа should/given/when и т.п. Это язык бизнес-логики, на котором разговаривают наши заказчики и UT-фрэймворки оказались к нему неприспособленными. Это как крепить на запорожец обвесы от BMW и считать, что у тебя M3.
https://github.com/sebastianbergmann/phpunit/commit/6aa9183496f9bb2131d17ba08195a93a07937762#commitcomment-164598. Тут Sebastian говорит про то, что он депрекэйтит BDD функциональность в phpUnit 3.5 из-за ее неспособности решать поставленные задачи оптимально и появления на рынке достойного средства для этого — Behat.
Задачи выполняются какбы одинаковые, но цели разные (тестирование атомарных модулей и тестирование всей системы в целом) — отсюда специфичные требования и новый функционал, который не нужен в TDD, но необходим в BDD.
Так что для сравнения BDD с BDD на UT фрэймворке следует приводить вот этот пример: https://gist.github.com/478885.
На самом деле, основная идея BDD именно в обратном подходе к разработке, а не в синтаксисе. TDD является моделью разработки inside-out (от частного к общему), когда мы гарантируем работу отдельно взятых атомарных модулей и предполагаем, что система в общем, при этом, будет работать нормально. Через некоторое время, было замечено, что это не так и что верная работа отдельных модулей вовсе не гарантирует верную работу системы в целом.
Появилась потребность в тестировании системы в общем. Такую модель разработки назвали outside-in (от общего к частному) или BDD. Смысл сводится к тому, что мы также сокрываем реализацию в черный ящик и работаем только с выходами/входами, только не отдельных модулей, а всей системы в целом (веб-приложение — Request/Response, консольное приложение — Arguments/Output). Оказалось, что подобную логику легче описывать на специфических терминах типа should/given/when и т.п. Это язык бизнес-логики, на котором разговаривают наши заказчики и UT-фрэймворки оказались к нему неприспособленными. Это как крепить на запорожец обвесы от BMW и считать, что у тебя M3.
https://github.com/sebastianbergmann/phpunit/commit/6aa9183496f9bb2131d17ba08195a93a07937762#commitcomment-164598. Тут Sebastian говорит про то, что он депрекэйтит BDD функциональность в phpUnit 3.5 из-за ее неспособности решать поставленные задачи оптимально и появления на рынке достойного средства для этого — Behat.
Задачи выполняются какбы одинаковые, но цели разные (тестирование атомарных модулей и тестирование всей системы в целом) — отсюда специфичные требования и новый функционал, который не нужен в TDD, но необходим в BDD.
Так что для сравнения BDD с BDD на UT фрэймворке следует приводить вот этот пример: https://gist.github.com/478885.
+4
Тут ниже дали ссылку на ваш доклад. Посмотрел, несколько вопросов есть по BDD вообще, и Behat в частности:
— использование BDD — это, грубо говоря, переход от разработки основанной на юнит-тестах к разработке, основанной на функциональном/интеграционном тестировании?
— использование юнит-тестов при BDD необходимо, желательно или избыточно?
— а Behat для symfony разработчика — это, грубо говоря, обёртка над функциональными тестами symfony, делающая удобным/стандартизированным то, что и так есть (спеки/user srory можно написать в произвольном виде, и на их основе писать функциональные тесты)?
— использование BDD — это, грубо говоря, переход от разработки основанной на юнит-тестах к разработке, основанной на функциональном/интеграционном тестировании?
— использование юнит-тестов при BDD необходимо, желательно или избыточно?
— а Behat для symfony разработчика — это, грубо говоря, обёртка над функциональными тестами symfony, делающая удобным/стандартизированным то, что и так есть (спеки/user srory можно написать в произвольном виде, и на их основе писать функциональные тесты)?
0
— использование BDD — это не переход, а добавление к юнит-тестам behavior тестов
— верная работа отдельных модулей не гарантирует верную работу системы в целом, но верная работа системы в целом не гарантирует верную работу отдельных модулей ;-)
— sfBehatPlugin — это набор шагов-оберток поверх sfTestFunctional (https://github.com/everzet/sfBehatPlugin/tree/master/features/steps/). EverzetBehatBundle — это набор шагов, использующих стек HTTP компонентов Symfony2 для эмуляции браузинга и тестирования аутпута (http://dl.dropbox.com/u/282797/BehatBundle_results.html). У EverzetBehatBundle более тесная интеграция с фрэймворком за счет того, что Symfony2 как и Behat используют DIC.
— верная работа отдельных модулей не гарантирует верную работу системы в целом, но верная работа системы в целом не гарантирует верную работу отдельных модулей ;-)
— sfBehatPlugin — это набор шагов-оберток поверх sfTestFunctional (https://github.com/everzet/sfBehatPlugin/tree/master/features/steps/). EverzetBehatBundle — это набор шагов, использующих стек HTTP компонентов Symfony2 для эмуляции браузинга и тестирования аутпута (http://dl.dropbox.com/u/282797/BehatBundle_results.html). У EverzetBehatBundle более тесная интеграция с фрэймворком за счет того, что Symfony2 как и Behat используют DIC.
0
> BDD — это, грубо говоря, переход от разработки основанной на юнит-тестах к разработке, основанной на функциональном/интеграционном тестировании?
Однозначно НЕТ!
Юнит-тестирование и функциональное/интеграционное тестирование — это два разных вида тестирования, они оба необходимы и не могут заменить друг друга.
BDD всего лишь пытается улучшить и то, и другое.
Однозначно НЕТ!
Юнит-тестирование и функциональное/интеграционное тестирование — это два разных вида тестирования, они оба необходимы и не могут заменить друг друга.
BDD всего лишь пытается улучшить и то, и другое.
0
у меня TDD ассоциируется с en.wikipedia.org/wiki/Design_by_contract, только «вывернутым наизнанку». в обоих случаях спецификации описываются в виде пред- и пост- условий, с использованием предикатных выражений:
«assert value == false» или «value should be false», — не суть.
но в TDD система описывается «снаружи» (ака черный ящик), а в DbC — «изнутри».
BDD же отражает другой аспект — императив — т.е. требования к поведению — «в динамике». какие действия и в какой последовательности нужно делать. часто это тоже важно:
Given…
When I go google.com
And I see search field
And I type «wtf BDD»
…
Then…
адепты от бизнеса это называют сценариями. а программисты видят отдушку, т.к. находят в нем черты привычного императивного программирования, которым занимаются каждый день. :)
термины юнит/функциональные/интеграционные тесты отражают ортогональный — системный — аспект. те же юнит тесты можно записывать и в стиле bdd и в стиле tdd — всё зависит от типа требований.
«assert value == false» или «value should be false», — не суть.
но в TDD система описывается «снаружи» (ака черный ящик), а в DbC — «изнутри».
BDD же отражает другой аспект — императив — т.е. требования к поведению — «в динамике». какие действия и в какой последовательности нужно делать. часто это тоже важно:
Given…
When I go google.com
And I see search field
And I type «wtf BDD»
…
Then…
адепты от бизнеса это называют сценариями. а программисты видят отдушку, т.к. находят в нем черты привычного императивного программирования, которым занимаются каждый день. :)
термины юнит/функциональные/интеграционные тесты отражают ортогональный — системный — аспект. те же юнит тесты можно записывать и в стиле bdd и в стиле tdd — всё зависит от типа требований.
+1
Я не говорю про тестирование как таковое, я говорю о * driven development. При использовании TDD я должен начинать разработку очередного «юнита» с написания тестов, к нему (ну, плюс «каркас» юнита, чтобы не было fatal/compile/… error), специфицирующих, по сути, его поведение. Рассуждая по аналоги, при использовании BDDя должен начинать разработку с написания behavior приложения в целом.
0
> В BDD нигде не говорится, что он предназначен именно для описания приложения в целом. Ну, и нигде не говорится, что спецификации BDD надо писать ДО приложения. Так что правильного ответа на ваш вопрос не знаю.
В нашем фирме мы пишем функциональные тесты всё-таки ПОСЛЕ того, как приложение написано.
В нашем фирме мы пишем функциональные тесты всё-таки ПОСЛЕ того, как приложение написано.
0
> Через некоторое время, было замечено…
Да что вы, необходимость интеграционного тестирования была очевидна задолго до того, как слово «юнит-тесты» появилось на свет.
> TDD является моделью… предполагаем, что система в общем, при этом, будет работать нормально.
Да что вы, никто не предполагает, что благодаря одному только TDD система будет работать нормально. В любом описании TDD всегда говорится, что одних юнит-тестов недостаточно, и другие виды тестирования тоже необходимы.
> основная идея BDD именно в обратном подходе к разработке, а не в синтаксисе.
Да что вы, откуда вы это взяли?
Вот цитата с википедии:
«BDD is… technique that encourages collaboration between developers, QA and non-technical or business participants in a software project. <...> It extends TDD by writing test cases in a natural language that non-programmers can read.»
То есть: «BDD — это техника… которая улучшает взаимодействие между программистами, тестеровщиками и не-техническими людьми в проекте. <...> BDD расширяет TDD путём написания тест-кейсов на естественном языке, который могут читать и не-программисты.»
en.wikipedia.org/wiki/Behavior_Driven_Development
Да что вы, необходимость интеграционного тестирования была очевидна задолго до того, как слово «юнит-тесты» появилось на свет.
> TDD является моделью… предполагаем, что система в общем, при этом, будет работать нормально.
Да что вы, никто не предполагает, что благодаря одному только TDD система будет работать нормально. В любом описании TDD всегда говорится, что одних юнит-тестов недостаточно, и другие виды тестирования тоже необходимы.
> основная идея BDD именно в обратном подходе к разработке, а не в синтаксисе.
Да что вы, откуда вы это взяли?
Вот цитата с википедии:
«BDD is… technique that encourages collaboration between developers, QA and non-technical or business participants in a software project. <...> It extends TDD by writing test cases in a natural language that non-programmers can read.»
То есть: «BDD — это техника… которая улучшает взаимодействие между программистами, тестеровщиками и не-техническими людьми в проекте. <...> BDD расширяет TDD путём написания тест-кейсов на естественном языке, который могут читать и не-программисты.»
en.wikipedia.org/wiki/Behavior_Driven_Development
0
По-моему не хватает в статье нормального введения. Потому что щас в качестве введения «разницу между TDD и BDD», а какая может быть разница если одно лежит в основе другого?
Изучив историю появления BDD, можно сделать следующие выводы:
1. Многие разработчики не знали как и не умели писать хорошие тесты используя TDD
2. Придумывают заменить слово test на should / ensure that, называют это BDD
3. BDD можно использовать с любым unit test framework-ом
4. Идея развивается, придумываются спецификации, ориентированость на user cases, а не на техническую сторону
5. Появляются BDD framework-и, которые больше подходят для написания функциональных тестов.
5. TDD не исчез и его нужно применять (стараясь использовать стиль BDD)
6. BDD — acceptance tests
Так?
Изучив историю появления BDD, можно сделать следующие выводы:
1. Многие разработчики не знали как и не умели писать хорошие тесты используя TDD
2. Придумывают заменить слово test на should / ensure that, называют это BDD
3. BDD можно использовать с любым unit test framework-ом
4. Идея развивается, придумываются спецификации, ориентированость на user cases, а не на техническую сторону
5. Появляются BDD framework-и, которые больше подходят для написания функциональных тестов.
5. TDD не исчез и его нужно применять (стараясь использовать стиль BDD)
6. BDD — acceptance tests
Так?
+1
>> Через некоторое время, было замечено…
>Да что вы, необходимость интеграционного тестирования была очевидна задолго до того, как слово «юнит-тесты» появилось на свет.
Я говорил не про интеграционное тестирование вообщем, а про интеграционное тестирование на основе behavior тестов. И оно уж никак не могло появиться раньше TDD ;-)
> То есть: «BDD — это техника… которая улучшает взаимодействие между программистами, тестеровщиками и не-техническими людьми в проекте. <...> BDD расширяет TDD путём написания тест-кейсов на естественном языке, который могут читать и не-программисты.»
Да, тут Вы правы. Я смешал понятия Outside-In Development с BDD, т.к. BDD сейчас чаще всего применяется именно при OIN разработке и я до сих пор не увидел смысла применять синтаксис BDD для написания юнит-тестов. В TDD практически не возникает коммуникативных проблем, которые существуют в Outside-IN ориентированной разработке, которые и породили необходимость в новом DSL.
Вообщем, извините за укол в Вашу сторону, виноват я.
>Да что вы, необходимость интеграционного тестирования была очевидна задолго до того, как слово «юнит-тесты» появилось на свет.
Я говорил не про интеграционное тестирование вообщем, а про интеграционное тестирование на основе behavior тестов. И оно уж никак не могло появиться раньше TDD ;-)
> То есть: «BDD — это техника… которая улучшает взаимодействие между программистами, тестеровщиками и не-техническими людьми в проекте. <...> BDD расширяет TDD путём написания тест-кейсов на естественном языке, который могут читать и не-программисты.»
Да, тут Вы правы. Я смешал понятия Outside-In Development с BDD, т.к. BDD сейчас чаще всего применяется именно при OIN разработке и я до сих пор не увидел смысла применять синтаксис BDD для написания юнит-тестов. В TDD практически не возникает коммуникативных проблем, которые существуют в Outside-IN ориентированной разработке, которые и породили необходимость в новом DSL.
Вообщем, извините за укол в Вашу сторону, виноват я.
0
И спасибо, что поправили. А то укоренился бы еще больше в заблуждении. ;-)
0
UFO just landed and posted this here
для .Net используют specflow.org/
+3
так же хорошая BDD библиотека для .Net github.com/robconery/shouldly
+1
Спустя какое-то время приходит ещё один разработчик и замечает, что даже этот хороший юнит-тест на является вполне читабельным
на -> не.
0
Что-то я так и не понял в чем слоь. TDD — это методология, она управляет разработкой, я не могу добавлять функциональность не придумав как ее можно протестировать т.е. не придумав ограничения (спецификации). Различия в «попытке №3» и примере с BDD только в синтаксисе (который, надо признать, намного удобнее читать) и названии тестов? Ну так все гуру тестирования говорят что у тестов должны быть осмысленные имена, и что тесты — лучшая документация для программы.
Ну а вообще, спасибо за статью, обязательно поковыряюсь в библиотеках для .NET.
Ну а вообще, спасибо за статью, обязательно поковыряюсь в библиотеках для .NET.
+1
вот и я тоже не понял при чем тут TDD равно как и BDD. Возможно пример #2 относится как-то к TDD, но это осталось за пределами заметки. А вообще, из текста возникает (во всяком случае у мена) ложное впечатление, что вся разница между «типичными юнит тестами», TDD и BDD в наименовании методов и степени грануляции тестов. Также, я не смог понять обещанной «покажу разницу между TDD и BDD». Вот если бы не знал то подумал, что там вся соль в именовании тестов и их размере, что на самом деле является просто характеристикой осмысленных и читабельных тестов.
+1
Почему же ложное? Вот вам определение с википедии: en.wikipedia.org/wiki/Behavior_Driven_Development
«It extends TDD by writing test cases in a natural language that non-programmers can read.»
Просто я не весь language показал, ну так это и не было моей целью.
«It extends TDD by writing test cases in a natural language that non-programmers can read.»
Просто я не весь language показал, ну так это и не было моей целью.
0
Для России это все-таки означает русский язык, иначе представителю заказчика это вряд ли можно будет показать. Так же ему не интересна реализация тестов. Такое есть в rspec и cucumber для ruby. Пример фичи( github.com/aslakhellesoy/cucumber/blob/master/examples/i18n/ru/features/division.feature ):
# language: ru
Фича: Деление чисел
Поскольку деление сложный процесс и люди часто допускают ошибки
Нужно дать им возможность делить на калькуляторе
Структура сценария: Целочисленное деление
Допустим я ввожу число <делимое>
И затем ввожу число <делитель>
Если я нажимаю "/"
То результатом должно быть число <частное>
Значения:
| делимое | делитель | частное |
| 100 | 2 | 50 |
| 28 | 7 | 4 |
| 0 | 5 | 0 |
0
А для Питона есть что нибудь похожее?
0
https://github.com/aslakhellesoy/cucumber/wiki/Python и lettuce.it/
0
Прочитал статью по ссылке. Получается, что это попытка скрестить «пользовательские сценарии» c unit-тестами?
Сценарии пишутся обычным языком и в большинстве случаев на высоком уровне абстракции, что подразумевает интеграционное тестирование как минимум.
Unit-тесты, с другой стороны, пишутся на языке программирования и могут заботиться о таких деталях о которых бизнес-пользователь ни сном, ни духом… Например, транзакции.
PS: А пример приведённый в данном хабратопике кодируется с помощью регулярного выражения. И зачем его так усиленно тестировать, ума не приложу.
Сценарии пишутся обычным языком и в большинстве случаев на высоком уровне абстракции, что подразумевает интеграционное тестирование как минимум.
Unit-тесты, с другой стороны, пишутся на языке программирования и могут заботиться о таких деталях о которых бизнес-пользователь ни сном, ни духом… Например, транзакции.
PS: А пример приведённый в данном хабратопике кодируется с помощью регулярного выражения. И зачем его так усиленно тестировать, ума не приложу.
0
Я тут ответил и на Ваш вопрос habrahabr.ru/blogs/tdd/107262/#comment_3390155 ;-)
0
для .NET есть NUnut, и метод Assert.That, позволяющий писать тест, который сам объясняет что он делает. Как пример, можно взять след.:
string[] s = new string[] { «30520», «30530», «C0430», «C0441», «C0440», «C0421», «70511», «70521» };
Assert.That(this.helper.GetNodesAtVoltage(2f, 5f), Is.EquivalentTo(s));
или вот еще один пример
Assert.That(mpsh.List_Nodes, Has.Some.Property(«uz»).EqualTo(«1»));
В первом случае говорится, что все содержимое полученного списка должно быть эквивалентно массиву s
Во втором, что в списке есть один элемент, у которого свойство 'uz' равно '1'
string[] s = new string[] { «30520», «30530», «C0430», «C0441», «C0440», «C0421», «70511», «70521» };
Assert.That(this.helper.GetNodesAtVoltage(2f, 5f), Is.EquivalentTo(s));
или вот еще один пример
Assert.That(mpsh.List_Nodes, Has.Some.Property(«uz»).EqualTo(«1»));
В первом случае говорится, что все содержимое полученного списка должно быть эквивалентно массиву s
Во втором, что в списке есть один элемент, у которого свойство 'uz' равно '1'
+1
Это совсем не BDD. Оычное, красиво оформленное TDD. Тут тестируется не поведение объекта, а сравнение результатов с эталоном и не более. А вот тестирование поведения выглядит, например, так:
@article.should.receive(:save).and_return(true)
put /article/1
Вот тут, во время выполнения экшена на пут запрос, проверяется вызов метода save и результат этого вызова.
@article.should.receive(:save).and_return(true)
put /article/1
Вот тут, во время выполнения экшена на пут запрос, проверяется вызов метода save и результат этого вызова.
+7
Если хорошенькое вдуматься, то это то же самое, только чуть по-другому названное.
так ведь я как раз об этом и говорю.
так ведь я как раз об этом и говорю.
0
Совсем не то же самое. Но это нужно осознать, вдумавшись.
+1
Точек между словами больше… они что-то значат и вызывают? Т.е. можно просто article.should написать? Или это чисто для группировки тестов используется… мол выбрать все тесты с article, и все с receive..?
Странный синтаксис. Напишите статью тогда уж — тема же интересная
Странный синтаксис. Напишите статью тогда уж — тема же интересная
0
Это синтаксис Rspec. Статью писать не буду — их в интернете итак полно )
@article.should.receive(:save).and_return(true)
Я даже не знаю, как объяснить в терминах дотнета. Синтаксис как раз очень хорош. Он примерно значит следующее:
во время выполнения экшена у статьи должен вызываться метод save, который возвращает true.
Это буквальный перевод.
Мы проверяем не результат работы, а поведение экшена или любого метода вообще то есть у нас во время выполнения экшена статья должна сохраняться.
@article.should.receive(:save).and_return(true)
Я даже не знаю, как объяснить в терминах дотнета. Синтаксис как раз очень хорош. Он примерно значит следующее:
во время выполнения экшена у статьи должен вызываться метод save, который возвращает true.
Это буквальный перевод.
Мы проверяем не результат работы, а поведение экшена или любого метода вообще то есть у нас во время выполнения экшена статья должна сохраняться.
0
Ну так и в юнит-тесте то же самое можно проверять, используя моки.
Примерно так это выглядит на Java:
article = mock(Article.class);
put(article, 1);
verify(article).save().shouldBeEqual(1);
Примерно так это выглядит на Java:
article = mock(Article.class);
put(article, 1);
verify(article).save().shouldBeEqual(1);
0
verify(article).save().shouldBeEqual(1);
В это сточке происходит вызов метода save и его сверка с 1? Или save произошёл раньше, внутри метода put?
В это сточке происходит вызов метода save и его сверка с 1? Или save произошёл раньше, внутри метода put?
0
save должен был произойти раньше, внутри метода put.
А verify(article).save() убеждается, что он действительно произошёл.
Здесь есть больше примеров:
mockito.org/
habrahabr.ru/blogs/java/72617/
В RSpec просто есть встроенная аналогичная функциональность, которая, похоже, выглядит получше и покороче благодаря тому, что язык Ruby сам по себе лаконичнее.
А verify(article).save() убеждается, что он действительно произошёл.
Здесь есть больше примеров:
mockito.org/
habrahabr.ru/blogs/java/72617/
В RSpec просто есть встроенная аналогичная функциональность, которая, похоже, выглядит получше и покороче благодаря тому, что язык Ruby сам по себе лаконичнее.
0
UFO just landed and posted this here
ScalaTest не только для Scala, можно и для проектов на Java юзать.
+1
Sign up to leave a comment.
Эволюция юнит-теста