Изучение TDD через интенсивную практику. Tdd книги


разработка через тестирование» / Блог компании Издательский дом «Питер» / Хабр

Возвращение знаменитого бестселлера. Изящный, гибкий и понятный код, который легко модифицировать, который корректно работает и который не подкидывает своим создателям неприятных сюрпризов. Неужели подобное возможно? Чтобы достичь цели, попробуйте тестировать программу еще до того, как она написана. Именно такая парадоксальная идея положена в основу методики TDD (Test-Driven-Development — разработка, основанная на тестировании). Бессмыслица? Не спешите делать скороспелые выводы. Рассматривая применение TDD на примере разработки реального программного кода, автор демонстрирует простоту и мощь этой методики. В книге приведены два программных проекта, целиком и полностью реализованных с использованием TDD. За рассмотрением примеров следует обширный каталог приемов работы в стиле TDD, а также паттернов и рефакторингов, имеющих отношение к TDD. Книга будет полезна для любого программиста, желающего повысить производительность своей работы и получить удовольствие от программирования. Чистый код, который работает (clean code that works), — в этой короткой, но содержательной фразе, придуманной Роном Джеффризом (Ron Jeffries), кроется весь смысл методики разработки через тестирование (Test-Driven Development, TDD). Чистый код, который работает, — это цель, к которой стоит стремиться потому, что

• это предсказуемый способ разработки программ. Вы знаете, когда работу можно считать законченной и не беспокоиться о длинной череде ошибок; • дает шанс усвоить уроки, которые преподносит код. Если вы воспользуетесь первой же идеей, которая пришла в голову, у вас не будет шанса реализовать вторую, лучшую идею; • улучшает жизнь пользователей ваших программ; • позволяет вашим коллегам рассчитывать на вас, а вам – рассчитывать на них; • писать такой код приятнее.

Но как получить чистый код, который работает? Многие силы мешают нам получить чистый код, а иногда не удается даже получить код, который просто работает. Чтобы избавиться от множества проблем, мы будем разрабатывать код, опираясь на автоматизированное тестирование. Такой стиль программирования называется разработкой через тестирование. Согласно этой методике

• новый код пишется только после того, как будет написан автоматический тест, завершающийся неудачей; • любое дублирование устраняется.

Два простых правила, не правда ли? Однако они генерируют сложное индивидуальное и групповое поведение со множеством технических последствий:

• в процессе проектирования мы постоянно запускаем код и получаем представление о его работе, это помогает принимать правильные решения; • мы сами пишем тесты, так как не можем ждать, что кто-то другой напишет тесты для нас; • наша среда разработки должна быстро реагировать на небольшие модификации кода; • дизайн программы должен базироваться на использовании множества автономных, слабо связанных компонентов, чтобы упростить тестирование кода.

Два упомянутых правила TDD определяют порядок этапов программирования.

1. Красный — напишите небольшой тест, который не работает, а возможно, даже не компилируется. 2. Зеленый — заставьте тест работать как можно быстрее, при этом не думайте о правильности дизайна и чистоте кода. Напишите ровно столько кода, чтобы тест сработал. 3. Рефакторинг — устраните из написанного кода любое дублирование.

Красный—зеленый—рефакторинг — это мантра TDD.

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

• при достаточно низкой плотности дефектов команда контроля качества (Quality Assurance, QA) сможет перейти от реагирования на ошибки к их предупреждению; • с уменьшением количества неприятных сюрпризов менеджеры проекта смогут точнее оценить трудозатраты и вовлечь заказчиков в процесс разработки; • если темы технических дискуссий будут четко определены, программисты смогут взаимодействовать друг с другом постоянно, а не раз в день или раз в неделю; • и снова при достаточно низкой плотности дефектов мы сможем каждый день получать интегрированный рабочий продукт с добавленной в него новой функциональностью, благодаря чему мы сможем вступить с нашими заказчиками в деловые отношения совершенно нового типа.

Итак, идея проста, но в чем наш интерес? Почему программист должен взять на себя дополнительную обязанность писать автоматизированные тесты? Зачем программисту двигаться вперед малюсенькими шажками, когда его мозг в состоянии продумать гораздо более сложную структуру дизайна? Храбрость.

Храбрость

TDD — это способ управления страхом в процессе программирования. Я не имею в виду страх падения со стула или страх перед начальником. Я имею в виду страх перед задачей, «настолько сложной, что я пока понятия не имею, как ее решить». Боль — это когда природа говорит нам: «Стоп!», а страх — это когда природа говорит нам: «Будь осторожен!» Осторожность — это совсем не плохо, однако помимо пользы страх оказывает на нас некоторое негативное влияние:

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

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

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

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

Тесты в TDD — это зубья на шестеренке храповика. Заставив тест работать, мы знаем, что теперь тест работает, отныне и навеки. Мы стали на шаг ближе к завершению работы, чем были до того, как тест заработал. После этого мы заставляем работать второй тест, затем третий, четвертый и т. д. Чем сложнее проблема, стоящая перед программистом, тем меньше функциональных возможностей должен охватывать каждый тест.

Читатели книги Экстремальное программирование, должно быть, обратили внимание на разницу в тоне между экстремальным программированием (Extreme Programming, XP) и разработкой через тестирование (Test-Driven Development, TDD). В отличие от XP методика TDD не является абсолютной. XP говорит: «чтобы двигаться дальше, вы обязаны освоить это и это». TDD — менее конкретная методика. TDD предполагает наличие интервала между принятием решения и получением результатов, и предлагает инструменты управления продолжительностью этого интервала. «Что, если в течение недели я буду проектировать алгоритм на бумаге, а затем напишу код, использовав подход “сначала тесты”? Будет ли это соответствовать TDD?» Конечно, будет. Вы знаете величину интервала между принятием решения и оценкой результатов и осознанно контролируете этот интервал.

Большинство людей, освоивших TDD, утверждают, что их практика программирования изменилась к лучшему. Инфицированные тестами (test infected) — такое определение придумал Эрих Гамма (Erich Gamma), чтобы описать данное изменение. Освоив TDD, вы обнаруживаете, что пишете значительно больше тестов, чем раньше, и двигаетесь вперед малюсенькими шагами, которые раньше показались бы вам бессмысленными. С другой стороны, некоторые программисты, познакомившись с TDD, решают вернуться к использованию прежних практик, зарезервировав TDD для особых случаев, когда обычное программирование не приводит к желаемому прогрессу.

Определенно, существуют задачи, которые невозможно (по крайней мере, на текущий момент) решить только при помощи тестов. В частности, TDD не позволяет механически продемонстрировать адекватность разработанного кода с точки зрения безопасности данных и надежности выполнения параллельных операций. Безусловно, безопасность основана на коде, в котором не должно быть дефектов, однако она основана также на участии человека в процедурах защиты данных. Тонкие проблемы параллельного выполнения операций невозможно с уверенностью воспроизвести, просто запустив некоторый код.

Прочитав эту книгу, вы сможете:

• начать применять TDD; • писать автоматические тесты; • выполнять рефакторинг, воплощая решения по одному за раз.

Книга разделена на три части.

Часть I. На примере денег. Пример разработки типичного прикладного кода с использованием TDD. Этот пример позаимствован мною у Уорда Каннингэма (Ward Cunningham) много лет назад, и с тех пор я неоднократно использовал его для демонстрации TDD. В нем рассматривается мультивалютная арифметика: выполнение математических операций над денежными величинами, выраженными в различных валютах. Этот пример научит вас писать тесты до тестируемого ими кода и органически развивать проект.

Часть II. На примере xUnit. Пример тестирования более сложной логики, использующей механизм рефлексии и исключения. В примере рассматривается разработка инфраструктуры автоматического тестирования. Этот пример познакомит вас также с архитектурой xUnit, которая лежит в основе множества инструментов тестирования. Во втором примере вы научитесь двигаться вперед еще меньшими шажками, а также разрабатывать систему с использованием механизмов самой этой системы.

Часть III. Шаблоны разработки через тестирование. Здесь рассматриваются шаблоны, которые помогут найти ответы на множество вопросов, в частности: какие тесты писать и как их писать с использованием xUnit. Кроме того, здесь вы найдете описание некоторых избранных шаблонов проектирования и рефакторинга, использовавшихся при создании примеров для данной книги.

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

Касательно примеров хочу отметить следующее. Оба примера, мультивалютные вычисления и инфраструктура тестирования, могут показаться чрезвычайно простыми. Существуют более сложные, дефектные и уродливые решения этих же самых задач (мне лично неоднократно приходилось сталкиваться с подобными решениями). Чтобы сделать книгу более похожей на реальность, я мог бы продемонстрировать одно из таких решений. Однако моя и, я надеюсь, ваша цель — написать чистый код, который работает. Прежде чем пенять на излишнюю простоту примеров, на несколько секунд представьте себе мир программирования, в котором весь код выглядит также чисто и понятно, в котором нет слишком сложных решений, только проблемы, которые кажутся слишком сложными лишь с первого взгляда. Сложные проблемы нуждаются в тщательном обдумывании. TDD поможет добиться этого.

» Более подробно с книгой можно ознакомиться на сайте издательства » Оглавление » Отрывок

Для Хаброжителей скидка 25% по купону — Бек

habr.com

Две книги про тесты | AETHER

Опубликовал Александр Шабуневич — 2 Февраль 2013, 15:11

Две последние книги, которые я прочитал, оказались про тесты: «The Art of Unit Testing with Examples in .NET» и «The RSpec Book: Behaviour-Driven Development with RSpec, Cucumber, and Friends». Последовательность прочтения как раз соответствует историческому развитию методологий.

The Art of Unit Testing

Книга «Искусство юнит-тестирования c примерами на .NET» («The Art of Unit Testing with Examples in .NET») посвящена даже не методологии TDD (Test Driven Development) в целом (про это как раз вторая книга), а теме написания правильных тестов. Это важный вопрос сам по себе, ведь тесты можно использовать и без строгого следования принципам TDD (то есть писать тесты не до кода, а после). При этом, плохо написанные тесты могут даже навредить (например, вселяя необоснованную уверенность в коде при рефакторинге).

Очень важно чтобы тесты были читаемыми (как и код), ведь тесты — это еще и документация. Например, не стоит делать в одном тесте более одного assert-а (чтобы не маскировать их при ошибках) или слишком увлекаться DRY (Don't Repeat Yourself), вынося инициализацию объектов из отдельных тестов в общие методы.

Кроме этого, в книге рассматриваются следующие вопросы:

  • Разные способы внедрения зависимостей: Inversion of Control (для конструкторов), Dependency Injection (для свойств), extract and override — их преимущества и недостатки.
  • Поясняется разница между mock (проверяют вызовы и фейлят тесты, вызывая assert) и stub, которые служат лишь «заглушками».
  • Даются советы, вроде того, что не стоит использовать более одного mock в каждом тесте (stub может быть сколько угодно), так как mock-и являются основным предметом проверки каждого теста.
  • Описаны основые «западни», при написании тестов, например, случаи, когда тесты недостаточно хорошо изолированы и зависят от других тестов.
  • Вопросы правильной организации, наименования тестов и прочие полезные приёмы.

Книга написана не для новичков, а скорее для тех, кто уже знаком с основами написания тестов и теперь хочет узнать рекомендованные способы и практики. Несмотря на то, что книга использует примеры на .NET, они будут понятны всем программистам, знакомым с ООП. Конечно, в книге рассматриваются и специфические .NET-фреймворки, которые мне не интересны, а потому их описания я пропускал, но большая часть книги подходит для любых языков программирования.

Тесты уже прочно прижились в инструментарии программистов. Но как и любая другая область написание тестов требует своей культуры. Даже если не следовать в полной мере TDD, тесты писать скорее всего придётся — сейчас для этого созданы все условия (благодаря библиотекам и другим инструментам). А как их лучше писать расскажет данная книга. Уверен, что даже человек с опытом написания тестов сможет найти в ней что-то полезное. ★★★★☆

The RSpec Book

С этой книгой я решил ознакомиться так как в последнее время всё чаще встречаюсь с понятием BDD (Behavior Driven Development) — своего рода, следующей версией TDD. Почти во всех языках программирования это сейчас является трендом: постоянно появляются новые библиотеки и фреймворки в этом стиле, и все большее количество проектов выбирают BDD для написания тестов. Сначала мне было не слишком понятно, чем вообще отличается BDD от TDD. Данная книга как раз ответила на этот вопрос.

Небольшое отступление про TDD/BDD

TDD, если вкратце, является такой практикой программирования, в которой тесты пишутся до рабочего кода. Это может показаться несколько нелогичным, ведь программистам платят именно за написание кода. Кроме того, писать код — наше самое любимое занятие. Но, думаю, многие знакомы с ситуацией, когда начинаешь писать код без особого предварительного планирования, а потом получается полная каша, которую несколько раз приходится переписывать. Так при чем тут тесты?

Если следовать традиционному подходу — разработке в стиле «водопад», то сначала пишутся технические задания и спецификации, затем составляются умные диаграммы, а потом пишется код и тесты для него. И весь процесс обычно растягивается на месяцы. Более того, если на последних этапах обнаружены какие-то принципиальные ошибки первых этапов, то стоимость их исправления зачастую становится слишком велика, ведь приходится всё повторять заново.

Agile-методология стала альтернативой традиционному подходу в разработке: вместо большого запланированного каскада используются мини-итерации по реализации фич. Одним из решений по оптимизации процесса разработки стала идея о том, что тесты можно (и нужно) писать до кода, добавляя к ним функцию документирования. Иногда тесты даже рекомендуют называть не тестами, а примерами:

A general rule of thumb is that if the code is hard to use in examples, it’s going to be hard to use everywhere else.

То есть вы не пишете тесты, чтобы проверить, правильно ли работает код, а пишете код, чтобы проверить, правильно ли исполняются функциональные требования в виде тестов. И тесты теперь становятся не просто инструментом для проверки ошибок: теперь они являются формальным документом (протоколом), по которому работает программист. Более того, написание тестов по сути является фазой дизайна — именно в этот момент вы проверяете, насколько ваши API будут удобны в использовании.

Данный подход характерен и для TDD, и для BDD, но последний пошел несколько дальше, меняя формат тестов на более «человеческий». Если TDD-тесты пишутся тестерами (или самими программистами) для программистов, то BDD-тесты пишутся еще и для заказчика. Более того, кроме тестирования юнитов (отдельных объектов), большое внимание уделяется тестированию поведения системы в целом (behavior) — в каком-то смысле это замена интеграционному тестированию и ATDP (Acceptance Test–Driven Planning).

Rspec и Cucumber

Книга рассказывает о двух основных продуктах для BDD-тестирования в мире Ruby: RSpec и Cucumber. Первый отвечает за тестирование объектов (аналог TDD), второй — за описание и тестирование поведения системы (аналог ATDP). Одно из главных отличий от более традиционных методов заключается в упрощении восприятия тестов и спецификаций.

Восприятие упрощается даже из-за использования языка, относящегося не к тестам, а к поведению: Given/When/Then. Спецификации Кукумбера вообще пишутся просто на английском (их можно писать даже на русском). При этом в Кукумбере есть несколько очень интересных фич: например, работа с шаблонами и таблицами подставляемых данных. Тесты RSpec очень похожи на TDD, только вместо assert обычно используется should, а вместо названий методов (типа testEmptyStringShouldBeNil) — строки (it "should return nil with empty string").

Но отличие не только в синтаксисе, а скорее в общем подходе. BDD-подход был разработан как ответ на запросы программистов, которые не знали с чего начать в TDD. Предполагается, что разработка должна проходить в виде цикла:

Сначала вы пишете спецификацию в Кукумбере, затем опускаетесь на уровень реализации и пишете тесты RSpec (понятно, что ни те, ни другие тесты сначала не проходят). Затем вы пишете код, подгоняя его под тесты, пока они не начинают исполняться без ошибок. После этого вы возвращаетесь на уровень программы в целом — к Кукумберу — и пишете новые тесты-спецификации.

Плюс подобной схемы в том, что вы связываете сразу два уровня: общий, который можно обсудить с заказчиком, и частный, который отвечает за конкретную реализацию алгоритма. Если делать всё как задумано, получается некий эффект «скольжения»: когда каждый новый шаг логически следует за предыдущим. И хотя может показаться, что работы становится в два раза больше, в более длительной перспективе это даёт свои преимущества при поддержке и рефакторинге программ.

Читая книгу, вы одновременно делаете упражнение по написанию маленькой игры, заключающейся в угадывании случайных цифр. Советую параллельно с чтением действительно писать код, так как «прорабатывание» его в уме не даёт полного эффекта погружения в процесс.

Все примеры в книге даны на Ruby, но это не мешает тем, кто пишет на других языках. На некоторых платформах тот же Кукумбер можно легко применять для тестирования без изменений синтаксиса (например, для разработки iOS/андроид-приложений есть Calabash), а синтаксис RSpec послужил источником вдохновения для многих библиотек. Например, для JavaScript есть Jasmine, которую использует Angular.js.

В общем, я рекомендую книгу к прочтению: в ней есть и обоснование современных подходов к разработке и конкретный пример следования этим подходам. И даже если вы не будете использовать все описанные подходы в разработке, что-то полезное из них наверняка почерпнёте. ★★★★☆

Ссылки по теме:

www.aether.ru

Пара слов о книге «Professional TDD with C#» / Хабр

Хотел бы сказать пару слов о книге Professional Test Driven Development with C#. Выбрать книгу по популярным технологиям и техникам программирования не так сложно. На каждом форуме написано, что если хочешь познать .NET – не обойтись без Рихтера. Сложнее с менее популярными темами. Итак, TDD…

Коротко

Это первая моя книга издания Wrox. Издание прошло проверку. На мой взгляд, весьма достойная книга. Первое что радует – она короткая. 300 страниц. Книга очень компактно написана. Нет воды и нет пережёванных примеров. Всё разложено по полочкам. В таком объёме легко ориентироваться и можно в любой момент найти ту информацию, которую ищешь.

Пройдусь прямо по оглавлению. Лучше книги о книге никто не расскажет.

Part 1.

Глава 1 рассказывает, как разрабатывалось ПО, как эволюционировал стиль разработки и как разработчики пришли к TDD.

Глава 2 – вводная глава в тестирование. Здесь рассказано, что такое тест. Из чего он состоит. Чем отличаются dummy/fake/stub/mock.

Глава 3 повествует про рефакторинг. Принципы ООП. SOLID. Приёмы и примеры рефакторинга.

Глава 4 рассказывает про сам TDD. Что если тест пишется до кода, то это TDD. Если наоборот, то автор не несёт ответственность за сроки сдачи вашего проекта.

Глава 5 содержит информацию про Dependency Injection и Mock’и. Зачем и как используются. Примеры реализации.

Part 2.

Глава 6. От начала до конца разобран процесс создания приложения. Создания структуры проекта в VisualStudio. Правила и советы по написания User Stories. Введение в Agile.

Глава 7. Начинаем реализовывать приложение. Строчка за строчкой, тест за тестом.

Глава 8. Integration Testing. Описываются интеграционные (вроде по-русски) тесты. Пример создания опять же присутствует.

Part 3

Глава 9 описывает техники тестирования веб приложений. В двух словах описано как тестировать ASP.Net Web Forms проекты. Далее довольно подробный разбор тестирования ASP.Net MVC проектов. И под конец ещё пара слов про JavaScript Testing Frameworks.

Глава 10 описывает приёмы тестирования WCF сервисов.

Глава 11 рассказывает про тестирование WPF и SilverLight приложений. Объясняется, как MVVM паттерн облегчит нам эту задачу.

Part 4

Глава 12 содержит общие слова про стратегии работы с новыми требованиями и дефектами в рамках TDD.

Глава 13 подчёркивает непредвзятость автора к разным фреймворкам. Здесь кратко описаны преимущества и недостатки многих Unit Testing Frameworks, Test Runners, Mocking Frameworks, DI Frameworks и нескольких полезных тулзов.

Глава 14 подытоживает всё прочитанное. Тут автор даёт последние наставления, и даже советы, о том, как следует внедрять TDD в своих компаниях более безболезненно.

Заключение.

Хорошая книга. Очень приятно и толково написана. Примеры кода можно скачать на сайте. Стоит отметить, что в переводе её нет, и придётся читать на английском. Сложность написания, с точки зрения языка, чуть выше того же Рихтера, но не на много. Книга собрала в себя колоссальное количество информации, начиная от рефакторинга, заканчивая Agile разработкой и BDD нотацией. Каждый такой пункт описан в 20-30 страницах, чего достаточно, чтобы понять главную идею и докупить уже специализированные книги по вкусу.

Ещё мне понравилась обложка. На ней нарисован хоккеист. Вот.

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

Информация о книге: Professional Test Driven Development with C# Developing Real-World Apllications with TDD Авторы: James Bender, Jeff McWherter Издательство Wrox ISBN 978-0-470-64320-4

habr.com

Экстремальное программирование. Разработка через тестирование

Добавить
  • Читаю
  • Хочу прочитать
  • Прочитал

Жанр: Программирование

ISBN: 978-5-496-02570-6

Год издания: 2003

Серия: Библиотека программиста (Питер)

Издательство: Питер

Оцените книгу

Скачать книгу

304 скачивания

Читать онлайн

О книге "Экстремальное программирование. Разработка через тестирование"

Возвращение знаменитого бестселлера. Изящный, гибкий и понятный код, который легко модифицировать, который корректно работает и который не подкидывает своим создателям неприятных сюрпризов. Неужели подобное возможно? Чтобы достичь цели, попробуйте тестировать программу еще до того, как она написана. Именно такая парадоксальная идея положена в основу методики TDD (Test-Driven-Development – разработка, основанная на тестировании). Бессмыслица? Не спешите делать скороспелые выводы. Рассматривая применение TDD на примере разработки реального программного кода, автор демонстрирует простоту и мощь этой методики. В книге приведены два программных проекта, целиком и полностью реализованных с использованием TDD. За рассмотрением примеров следует обширный каталог приемов работы в стиле TDD, а также паттернов и рефакторингов, имеющих отношение к TDD. Книга будет полезна для любого программиста, желающего повысить производительность своей работы и получить удовольствие от программирования.

Произведение было опубликовано в 2003 году издательством Питер. Книга входит в серию "Библиотека программиста (Питер)". На нашем сайте можно скачать книгу "Экстремальное программирование. Разработка через тестирование" в формате fb2, rtf, epub, pdf, txt или читать онлайн. Здесь так же можно перед прочтением обратиться к отзывам читателей, уже знакомых с книгой, и узнать их мнение. В интернет-магазине нашего партнера вы можете купить и прочитать книгу в бумажном варианте.

Отзывы читателей

Подборки книг

Похожие книги

Другие книги автора

Информация обновлена: 01.07.2017

avidreaders.ru

Изучение TDD через интенсивную практику / Хабр

Примечание от переводчика: мой опыт знакомства с разработкой через тестирование во многом схож с тем, что описывает автор (хотя и начался на несколько лет позже). Я начинал изучать TDD самостоятельно, на работе, исправляя баги и создавая новые модули с нуля. Эффект от применения TDD произвёл на меня настолько мощное впечатление, что породил желание делиться умением применять эту технику с другими. Я также проводил Code Retreat-ы внутри и вне своей компании. И я вижу те же проблемы в своих тренингах — очень сложно взять и «впихнуть» понимание сути TDD в чужие головы.

Поэтому в данной статье я вижу свежий взгляд на проблему, который, возможно, даст новый толчок в изучении TDD мне и моим коллегам. Думаю, она пригодится и прочим интересующимся разработкой через тестирование. Буду рад увидеть Ваши комментарии.

Я использую TDD как инструмент для изучения и преподавания основ модульного дизайна, но должен заметить, что эффективность обучения сильно зависит от дисциплины студентов. Я хочу делать своё дело всё лучше и лучше, и поэтому постоянно ищу новые способы планировать критические шаги1 в преподавании TDD. Думаю, я нашёл микротехнику, которая помогает в этом деле, и хочу немедленно поделиться ей с вами.

TL;DR?
Многие сторонники TDD рекомендуют подход под названием «интенсивная практика», но я догадываюсь, что у Вас не будет возможности тратить много рабочего времени на практику. Я советую людям «применять TDD осознанно», но до сих пор не знал хорошего способа достаточно доступно объяснить смысл этих слов, что снижало ценность моего совета. Вы можете начать применять оба подхода (интенсивный и осознанный) одновременно, если начнёте исправлять баги через тесты. Даже если Вы до сих пор не умеете проектировать софт на экспертном уровне, то, по крайней мере, Вы уже можете учиться как эксперт. И исправление багов через тесты даст Вам естественную и не слишком рискованную возможность делать это. У Вас будет возможность практиковаться в TDD усердно и осознанно. Если у Вас есть возможность исправлять баги на работе в одиночку, то Вы можете использовать эти практики, не привлекая лишнего внимания, которое обычно возникает при разговорах об «интенсивной практике». Просто говорите всем, что Вы исправляете баги. Это всем понравится.

Вам всего лишь надо начать с написания теста, который будет падать до тех пор, пока Вы не исправите баг. Если Вам нужно больше подробностей, прежде чем начать, продолжайте чтение.

Подробности
Во время чтения книги Sources of Power Гэри Кляйна (Gary Klein), в которой описывается, как люди учатся принимать решения, моё внимание привлекла глава об интенсивной практике. (Я прокомментирую несколько цитат со 104-й страницы этой книги.)Поскольку ключом к эффективному принятию решений является построение экспертизы, одним из соблазнов будет создание тренинга, учащего людей думать как эксперты. Мне представляется, что множество людей подвергаются этому искушению и строят свои тренинги так, чтобы максимизировать объём информации экспертного уровня, которой они могут нагрузить участников. Я тоже так делал, но остановился, когда сам побывал на одном из них обычным участником. Если Вы откроете кран и начнёте заливать в меня десятки правил и выводов, я «переполнюсь» всего за пару часов, а затем перестану слушать.В большинстве случаев это будет слишком долгим и дорогим удовольствием. Ага.Однако, если мы не можем научить людей думать как эксперты, возможно, у нас получится научить их учиться как эксперты. Продолжай…Изучив литературу, я выявил несколько способов, как могут обучаться эксперты в различных областях:
  • Они принимают участие в интенсивной практике так, что каждое практическое занятие имеет цель и оценочные критерии.
  • Они нарабатывают обширный пласт опыта.
  • Они получают обратную связь: точную, диагностирующую, и своевременную.
  • Они обогащают свой опыт, проводя «разборы полётов», чтобы извлечь уроки из своих ошибок.
Что-то из этого звучит знакомо, а что-то представляет собой новые возможности извлечь больше из практик по TDD.
Три из четырёх — не так уж и плохо
Ранее я уже упоминал об интенсивной практике. В «Don’t Waste Your Golden Learning Opportunity!» я писал о том, что к новые практики можно рассматривать как этюды. Эта метафора взята из музыки, где этюды широко применяются для отработки техники. Спортсмены, в свою очередь, могут думать о практике как об игровой тренировке. Но, так как большинство программистов вряд ли будут практиковаться вне рамок своей дневной работы, есть смысл рассмотреть такие режимы практики, которые можно применять во время «обычной работы».

Я и сам изучал сперва подход «сначала тесты» (test-first), а потом и «разработку через тесты» (test-driven) в горячке ежедневной работы, когда время ограничено, и от меня ждут реальных результатов. Сейчас, оглядываясь назад, я понимаю, что делал три из четырёх вещей, которые Кляйн перечисляет в качестве источников обучения экспертов.

  • Я нарабатывал обширный пласт опыта, используя TDD для написания почти всего моего рабочего кода в период с начала 2000-го года и до моего ухода из IBM в ноябре 2001-го.
  • Я получал точную, диагностирующую и своевременную обратную связь, задавая тысячи вопросов и участвуя в серьёзных дискуссиях в различных почтовых рассылках. (Тогда ещё не было StackOverflow.) Я также отвечал на множество вопросов других людей, что требовало от меня чтения, написания и улучшения большого количества кода.
  • Отвечая на вопросы в списках рассылки, на конференциях, на встречах пользователей, я часто касался старых тем снова и снова, что позволяло оттачивать мои старые ответы, а также испытывать новые озарения. Весь этот опыт со временем превратился в мою первую книгу: JUnit Recipes: Practical Methods for Programmer Testing.
Но даже тогда, когда я практиковался интенсивно и усердно (и даже осознанно), я не заходил так далеко, чтобы сформулировать явную цель и оценочный критерий для моих практических занятий. Точнее, порой заходил, но чаще нет. Как правило, я не ставил таких целей явным образом, а если ставил, то это происходило случайно. Сейчас же настало время вспомнить мой былой опыт и извлечь из него новый урок.
Интенсивная практика TDD
Если Вы хотите попрактиковаться в TDD как в инструменте качественного проектирования программных систем, попробуйте заняться этим на работе.

Возьмитесь исправить какой-нибудь баг. Скорее всего, Вы уже знаете, как исправлять баги, используя принцип «сперва тесты» (test-first), но на всякий случай я кратко опишу этот процесс:

  1. Напишите интеграционный тест, который падает из-за этого бага. Тест не обязательно должен проходить до конца, но Вы можете продолжить его так далеко, как Вам требуется. Главное, чтобы бы он падал из-за существующего бага.
  2. Начинайте писать всё меньшие и меньшие (более сфокусированные) тесты, которые приближают Вас к месторасположению бага. Можете использовать для этого приём «тиски Саффа» (Saff Squeeze) или любой аналогичный. Можете даже использовать отладчик, если хотите.
  3. Остановитесь тогда, когда у Вас есть минимальный тест (или несколько тестов, если у бага есть несколько причин), который описывает суть ошибки, вызывающей этот баг.
  4. Исправьте ошибку, удостоверьтесь, что все тесты проходят, и затем закомитьте все Ваши изменения.
  5. Налейте себе кружку кофе.
А теперь давайте вернёмся к четырём пунктам Кляйна и посмотрим, как этот метод поможет Вам учиться проектированию софта на экспертном уровне.

Похоже ли это на интенсивную практику? Да. Когда я сажусь исправлять баг этим методом, я отношусь к нему как к возможности потренироваться в написании тестов, возможности учиться меньше полагаться на отладчик и отслеживание кода в голове, возможности учиться лучше выражать и документировать (через тесты) моё знание о коде, который я отлаживаю.

Есть ли у меня ясная цель и оценочные критерии? Я вижу ясную цель: исправить баг, научиться писать тесты, научиться писать более сфокусированные тесты, а также задокументировать приобретённое знание о коде, чтобы это знание не испарилось к тому моменту, когда я буду отправлять свои изменения в общий репозиторий. А в качестве оценочных критериев я могу выбрать что-то из следующего:

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

Поможет ли это мне наработать обширный пласт опыта? Поможет, если я исправлю таким образом 50 багов в течении нескольких следующих месяцев. Как минимум, если я решу исправлять все баги таким образом, я неуклонно наработаю существенный объём опыта. Особенно если я буду исправлять баги во всех частях системы. А уж тем более, если в нескольких системах.

Получу ли я точную, диагностирующую, своевременную обратную связь? Думаю, да. Каждый раз, когда я пишу новый тест, он либо пройдёт, либо упадёт. Поэтому я, по крайней мере, могу понять, что начал приближаться к сломанной части кода. Я не могу быть уверен на 100%, что я нашёл тот кусок кода, который вызывает падение, пока мои тесты не станут достаточно маленькими, чтобы доказать это тем или иным способом, и я постепенно двигаюсь в этом направлении.

Поможет ли это мне пересмотреть мой старый опыт, чтобы получить новые озарения? Да и нет. Нет, потому что (как я надеюсь) мне не придётся исправлять один и тот же баг дважды; но да, потому что я работаю таким образом с каждым новым багом, так что мне придётся сталкиваться с теми же частями системы по многу раз. Чем больше багов я исправляю в какой-либо части системы, тем больше возможности у меня будет вернуться к моим прошлым тестам и сравнить свой новый опыт со старым. Если я потрачу немного времени, сравнивая, что я делаю по-другому по сравнению с прошлыми разами, то это даст мне возможность получить новые озарения.

Так что, мне кажется, что подобный метод исправления багов поможет практикующемуся учиться как эксперт (по крайней мере, в данной интерпретации как метода, так и модели обучения экспертов, описанной Кляйном). Просто попробуйте сами и оцените этот подход.

За пределами работы с багами
Как можно использовать TDD для изучения принципов модульного дизайна на экспертном уровне? Я должен упомянуть одну часто встречающуюся небрежность на этом пути. Это не то чтобы серьёзная небрежность, скорее следствие благих намерений и в то же время недопонимания. Я всегда считал использование «осознанного подхода» особенно важным. Поэтому, когда кто-либо начинает заявлять, что разработка через тесты «не работает» или «причиняет страдание» или «вредит», я включаюсь в дискуссию и раз за разом повторяю одну и ту же идею:Правила ничего не делают сами; всё делают люди. TDD, как и любая другая практика, требует от практикующего включать мозги. Он должен упражняться осознанно. Это было верно, но достаточно бесполезно… до сегодняшнего дня. Я уверен, что Кляйн открыл мне более точный и применимый в деле способ объяснять, что такое «осознанная практика». Я собираюсь использовать его в моих тренингах, начиная с сегодняшнего дня. Похоже, я неявно использовал его в изучении TDD (и модульного дизайна), но до сих пор у меня не было легко запоминающегося способа его сформулировать. Спасибо, Гэри Кляйн.
Как практиковаться в TDD «осознанно»
Возьмите паузу в несколько секунд и подумайте о том, когда и как Вы собираетесь изучать TDD. На каком коде? В какое время? В каких условиях? Не обязательно жёстко ограничивать себя этими правилами, но они помогут упорядочить процесс. Очень важно определить для себя, в каких случаях Вы готовы использовать TDD, а в каких нет. Определите это, пока что, только для себя. Договориться с коллегами можно и позже2.

Как только Вы определили рамки, в которых Вы будете упражняться в TDD, Вы можете задать себе цели и критерии оценки для этих тренировок. Подкину несколько идей.

Цели для тренировок по TDD
  • Создайте через тесты точку интеграции с библиотекой, с которой Вы не работали ранее.
  • Отделите несколько большую часть Вашего кода от интеграции с фреймворком.
  • Напишите поменьше тестов, которые требуют фреймворк-ориентированной библиотеки тестирования (например, Robolectric, NUnitASP, rspec-rails, or JSFUnit), и побольше тестов, которые используют обычные библиотеки тестирования (обычные JUnit, RSpec или pytest).
  • Уменьшите время, которое требуется на создание следующего теста.
Оценочные критерии для тренировок по TDD.
  • Сделал ли я эту часть системы более простой, чем обычно?
  • Являются ли имена в этой части системы более понятными другим, помогают ли они понять, как изменять этот код?
  • Могу ли я расширить эту часть системы, просто добавляя новый код, а не изменяя существующий?
  • Зависит ли код, необходимый для настройки окружения моих тестов, только от тех частей системы, которые я только что создал?
  • Если мой тест содержит несколько проверок, предполагаю ли я, что они сильно связаны друг с другом?
  • Достаточно ли быстро проходят мои тесты? Или они хотя бы стали быстрее, чем раньше?
Если мы посидим вместе хотя бы десять минут, то наверняка придумаем ещё дюжину подобных полезных критериев. Выберите несколько и держите их в голове в течение следующего сеанса программирования, во время которого Вы будете отрабатывать TDD.

А мне позвольте перейти к вопросу получения новых озарений из старого опыта, потому что я часто сталкиваюсь с этим, обучая других и практикуясь с ними. Чтобы перерабатывать свой опыт, не обязательно самому проводить какие-то занятия. Можно, к примеру, просто отвечать на чужие вопросы. Например, я раз за разом отвечаю на одни и те же вопросы, приходящие разными людьми. (Обычно я терпеть не могу повторяться, но сейчас я понял, что эти повторения на самом деле гораздо ценнее.) Чем больше я отвечаю на эти вопросы, тем больше я рефлексирую над моим пониманием. Со временем мои идеи сталкиваются с разнообразными новыми испытытаниями и либо укрепляются, либо дают жизнь новым, более удачным. Я также принимаю участие в Code Retreat-ах специально для того, чтобы работать над одними и теми же небольшими задачками снова и снова с новыми людьми. Каждый год я испытываю новые озарения, работая над игрой «жизнь».

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

Обширный пласт опыта
Я годами описывал TDD как «технику для обучения проектированию», в которой мы можем использовать механизм, схожий с механизмом наработки языковых навыков. Как Вы учились говорить на своём родном языке? Скорее всего, это выглядело как-то так:
  • Сначала, в течение долгого времени. Вы только слушали речь людей вокруг Вас.
  • В какой-то момент Вы начали говорить очень простые фразы.
  • Когда вы начали произносить эти фразы, Вы замечали, как окружающие реагируют на Вашу речь.
  • Иногда Вас поправляли, объясняя, что надо говорить так, а не этак.
  • Из этих объяснений Вы извлекали правила и принципы построения «правильных» фраз.
  • Вы опирались на эти правила и принципы в построении новых предложений.
И этот процесс шёл, не прекращаясь. Язык, на котором Вы разговариваете, превратился в инструмент непрерывного общения с другими людьми, включающий эксперименты, оценку, взаимное влияние, попытки исправлений, извлечение новых правил и принципов… — и так до самой смерти.

На мой взгляд, TDD позволяет изучать дизайн кода аналогичным образом. Он позволяет выйти за пределы обычного программирования, предоставляя программисту возможность оценивать код в критериях высокого уровня, а-ля «я легко могу протестировать это», или «я могу отделить этот код из его контекста, чтобы запускать в изолированном окружении» или «я могу добавить новое поведение через добавление кода, а не через изменение существующего». Вы можете возразить, что такие оценки можно получить, даже просто читая и обсуждая код, но именно TDD мотивирует программиста вести диалог с кодом, обдумывать «как должен вести себя этот кусок?» или «как мне следует спроектировать эту часть?» с разных сторон. Я думаю, что такой диалоговый стиль создания кода позволяет нарабатывать опыт куда эффективнее и быстрее, нежели традиционный подход «пиши много, читай редко». Как минимум, TDD мотивирует программиста видеть код под разными точами зрения.

Главную роль в этом подходе играет рефакторинг. Во время рефакторинга требуется оценить существующий код, понять и выявить его проблемы, предложить способ его улучшения, а затем изменить в соответствии с этим способом. (Не хотелось бы мне проводить крупный рефакторинг без тестов, а если бы я не писал тесты в первую очередь, то вряд ли бы их набралось достаточно много, чтобы я чувствовал себя достаточно уверенно при рефакторинге.) Процесс рефакторинга позволяет программисту видеть разные варианты дизайна одного и того же кода, каждый из которых может либо иметь определённые проблемы, либо не иметь; это позволяет сравнивать различные варианты дизайна и выбирать из них наиболее достойные. У программиста появляется возможность сравнивать состояния «до» и «после» рефакторинга и оценивать, какой эффект дают его улучшения кода.

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

1. Почитайте 3 главу книги Switch, чтобы узнать больше о том, как помогать людям изменять своё поведение. 2. Я обучаю команды технике применения новых практик через безопасные эксперименты, что помогает им улучшать их работу. Я ещё не писал об этом подробно, но обещаю это сделать. Если Вы не можете дождаться новой статьи и хотите узнать об этом как можно скорее, свяжитесь со мной, и мы поработаем так вместе.

habr.com

Книги, которые хорошо бы прочитать разработчику...

 

Описывает test driven development процесс разработки из первых уст.

   

Про юнит тестирование, очень много полезных приемов и решений. Книга-справочник паттернов. 

  

Читать первых 100 страниц, а остальной частью книги пользоваться как справочником. Стоит знать запахи и основные методы борьбы с ними. С этой книги стоит начинать изучать ООП. 

 

Рассказывает как хачить в легаси проектах, чтобы хоть как-то начать рефакторинг/тестирование. Поможет очень в сильно безнадежных проектах. Выход есть! :)

 

 

 

Рассказывает про OOP/SOLID принципы и шаблоны проектирования. Читать 1 раз и навсегда запомнить все те основные шаблоны, которые иначе очень сложно просто заучить.

"Быстрая разработка программ:принципы, примеры, практика"Роберт Мартин  Так же про SOLID, но немного более тяжелым языком.  

Библия программиста. Буквально библия. Стоит иметь на полке и открывать в рендомных местах, читать и просветляться. Пробовать, переживать, снова открывать в любом месте и снова просветляться. 

Немного о том, как работают команды. Что стоит и чего не стоит делать, чтобы увеличить производительность команды. 

Проекты делают не роботы а люди. Люди - существа сложные. Книга о том, как принимать это во внимание.

www.apofig.com

TDD — это как сноубординг / Хабр

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

«Я не использую эту методологию (TDD) из-за того, что главный для меня вопрос остается без ответа. Я знаю, что использование TDD уменьшает количество багов, но что насчет времени, необходимого при работе по этой методологии? Я хотел бы знать как изменяется время на разработку корпоративного приложения с использованием TDD — уменьшается, увеличивается или остается неизменным. Надеюсь, вы сможете ответить, так как TDD и BDD меня очень интересуют.»

Первая и самая важная вещь, на которую я хотел бы обратить внимание, — ошибочное представление о TDD как об инструменте для уменьшения количества багов. Хотя это и является одним из «побочных эффектов» TDD, это не основной мотив для его использования. Главный довод в пользу TDD — последовательная разработка дизайна каждого компонента вашей системы посредством написания теста для него.

Что касается следующего вопроса:

«Я хотел бы знать как изменяется время на разработку корпоративного приложения с использованием TDD — уменьшается, увеличивается или остается неизменным.»

Когда вы впервые решаетесь забраться на гору и рискнуть прокатиться на сноуборде, вы забираетесь туда с мечтой в голове о том как будете рассекать несколько минут и выделывать трюки круче, чем в SSX Tricky. Но после пары падений вы чувствуете увесистый пинок реальности и осознаете, что, похоже, это займет немного больше времени, прежде чем вы научитесь хотя бы просто съезжать с горы без всякого блеска и очарования. Если вы благоразумны, то потратите время на занятия с квалифицированным инструктором, который за день обучит вас основам и поставит технику. На базе занятий с интруктором вы сможете расти как сноубордист следующие пару месяцев, и, скорее всего, не нахватаетесь вредных привычек, которыми могли бы обзавестись, попытайтесь вы научиться самостоятельно.

Как в сноубординге (да и в любом другом новом деле, которое вы решили освоить), в начале нужно потратить время на обучение. Большинство людей, решивших окунуться в TDD, осознают, что в их знаниях много пробелов, которые могут создать проблемы в этом новом мире. Даже если со знаниями у вас все в порядке, вы должны осознавать, что в любом случае первое время вы будете тренировать свой мозг решать программные проблемы непривычным способом. На самом деле, это одно из самых больших препятствий при переходе на TDD — выработка нового стиля программирования, который заставляет вас думать о маленьких шагах и разрабатывать API, как будто он уже написан. Хороший способ начать практиковать TDD — использовать state-based тестирование (от перев. — подход, при котором проверяется состояние объекта после прохождения теста). Как только вы набьете руку на state-based тестировании, вы сможете сочетать его с interaction-based тестированием (от перев. — подход, при котором тестируется взаимодействие объектов, поведение методов, последовательность их вызовов и т.д.).

Начав использовать TDD, вы можете обнаружить, что работаете медленнее, чем обычно, — это в основном из-за того, что вы будете работать вне «зоны комфорта», чувствуя себя неестественно. После того как вы ощутите, что написание тестов стало естественной частью рабочего процесса, что вам больше не нужно думать об использовании TDD при работе над проектом, так как TDD влилось в вашу работу, вы поймаете ваш «АГА!» момент с TDD.

Я был свидетелем работы двух команд (одна из которых была agile) с разработчиками примерно одного уровня, которых попросили реализовать одну функциональность в проекте. Команда, практикующая TDD, подстраивалась под поставленные задачи и меняющиеся требования гораздо лучше, чем та, которая не использовала TDD. Я много раз наблюдал эффект TDD на самых разных проектах — от небольших до огромных проектов уровня предприятия. Я бы не говорил о преимуществах TDD, если бы не чувствовал, что оно действительно заслуживает внимания. Что касается меня, то этот подход полностью изменил мой взгляд на решение проблем в программировании.

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

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

Для тех из вас, кто всерьез рассматривает использование TDD, но еще не начал, — возможно, сейчас хороший сезон, чтобы попробовать взобраться на холм!

habr.com