Здравствуйте, _vovin, Вы писали:
_>Это уже integration testing. А как ты помнишь, TDD включает в себя только unit-testing. Но с другой стороны при обнаружении бага ты можешь написать integration test на него, чтобы он больше не возникал.
Лично я поступаю несколько иначе. У меня как правило одни модули используют другие, одни классы строятся на основании других классов. Если я разрабатываю что-то снизу вверх, то я сначала пишу тесты для отдельных классов, потом для класса, который их использует. Если я разрвбатываю сверху вниз (так бывает чаще всего), то сначала я пишу тест для бОльшего класса, часто при этом применяя вместо составляющих его частей Mock-объекты, а затем уже тесты для каждого из мелких объектов и сами объекты.
Так что, строго говоря, можно и интеграционные тесты писать в рамках этой идеологии.
_>И вообще-то, по большому счету, тестирование в TDD не самое важное. Самое важное это Test-First Design, т.е. дизайн, рождающийся благодаря априорному наличию требований, выраженных в коде.
_>Но так удачно получилось, что требования и unit-testing реализованы в одном лице (в виде unit-тестов). Собственно от тестов с точки зрения именно тестирования требуется лишь хорошее покрытие кода с тем, чтобы без боязни применять refactoring. Который в свою очередь является механизмом поддержки evolutionary design, и если копнуть дальше, то и самого ООП...
Хм... это вообще говоря сомнительный вопрос.
1) В большинстве случаев в коде невозможно выразить ВСЕ требования, так же как и невозможно протестировать ВСЕ.Это утопия. Однако, лучше протестировать хоть что-то, чем ничего. TDD, кстати, вовсе не подразумевает ПОЛНОГО набора тестов, который ТЕСТИРУЕТ ВСЕ. Подразумевается, что тестируется основная функциональность, а при необходимости (например, найден новый баг или например сегодня мне в голову пришла новая идея) набор тестов пополняется.
2) Требования, реализованные в коде трудно читать и изменять, поэтому вряд-ли код можно расценивать как способ выражения требований. А уж если очень хочется — обратитесь к формальным языкам описания требований, таким как RSL
И в заключение, несколько моих чисто личных впечатлений по поводу TDD.
TDD не является серебрянной пулей.
При разработке какой-либо задачи удобно бывает смотреть на нее с разных сторон. Я считаю, что задачу решить тем проще, чем она понятней, а она тем понятней, чем с большего числа сторон рассмотрена. TDD предоставляет нам еще один взгляд на задачу — с чисто функциональной точки зрения.
Когда Вы пишете обычный код, вы, как правило, отвечаете на вопрос КАК что-то должно быть сделано. Когда Вы пишете тесты — вы отвечаете на вопрос ЧТО КОНКРЕТНО должно быть сделано.
Полностью ответить на первый вопрос — означает создать полностью работающий программный продукт.
Полностью ответить на второй вопрос — как не странно, тоже означает создать полностью работающий программный продукт!!! Посмотрите, хотя бы на язык Пролог и парадигму программирования ограничениями. Ведь они именно что и делают — описывают ЧТО ИМЕННО должна делать программа, совершенно не заботясь о том, КАК !
Таким образом, разрабатывая и тестируя, мы приближаемся к решению с двух противоположных сторон, что позволяет нам крутить и вертеть проблему так, как нам удобно.
Чаще всего я разрабатываю программы сверху вниз и тестирую вначале, а потом пишу код. Но иногда я делаю в точности наоборот, если это позволяет мне легче разобраться в том, что я делаю. Однако, в любом случае, тесты я пишу, и не раз оценил уже пользу тестов для поддержания разработки. Некоторые тесты тянутся у меня из версии в версию очень подолгу, когда код давно уже 15 раз переписан и частично выброшен.
Итак, разрабатывайте тесты, отвечая на вопрос, что именно нужно сделать. Пишите программы, отвечая на вопрос КАК именно нужно это сделать. Разрабатывайте куски задачи сверху вниз для того, чтобы четко видеть архитектуру. Разрабатывайте другие куски снизу вверх, если архитектура проблемы чересчур необъятна. Пробуйте, пытайтейсь, главное, не зацикливайтесь на каком-то одном способе в ущерб другим.