Поэтому мы пишем некоторый тестовый код, затем пропускаем его и перезапускаем. Если у нас еще есть несколько минут в текущем Pomodoro, давайте немного проведем рефакторинг и извлечем некоторые методы. Легко ли?
Ну, у Test-Driven Development есть простое определение, но много последствий и предположений, особенно в части рефакторинга. Вот несколько советов из моего опыта нескольких лет TDD в PHP и Java, в веб-приложениях и приложениях машинного обучения.
Просто хорошее письмо
Наиболее часто игнорируемой техникой рефакторинга является переименование. В некотором стиле BDD попытайтесь сформировать свой тест и имена тестов с шаблоном GivenWhenThen; предпочитайте предметную терминологию техническим терминам, которые сложнее испортить.
public void increasesItsHeightWhenANewRowIsAdded()
более читабельно, чем:
public void processingNewRow()
или даже
public void testAddMethod()
При считывании имен тестовых методов поведение класса должно быть вам понятно:
public void changesItsHeightWhenANewRowIsAdded() public void reducesItsHeightWhenANewRowIsAdded() public void anEmptyRowCantBeAdded()
Подумайте также о порядке, в котором вы размещаете методы. При выполнении теста в подробном режиме вы обычно можете перечислить имена методов и подумать об отсутствующих тестовых случаях, если они организованы с симметрией и согласованностью имен.
Случаи ошибок
Проблема с наивным TDD заключается в тестировании проекта API (имен методов и аргументов), но не в случаях ошибок. Действительно тщательное тестирование основано не только на удачных путях, но и на управлении ошибками; ошибки, которые будут происходить особенно при работе с внешними объектами.
Таким образом, интерфейс, которым вы управляете, также должен формироваться из-за ошибок:
- возвращаемые значения . Нет возвращаемого значения, очевидно, тривиально; в противном случае, это последовательный тип? Вы возвращаете false в некоторых случаях? Можете ли вы вернуть нулевой объект? Может быть интерфейс для определения результата, который воспринимает хорошие и плохие результаты, например тип Maybe.
- побочные эффекты и уведомления . Первый вид предназначен, обязательные эффекты звонков, которые вы делаете. Второе охватывает логирование, события и подписчики (как представления). Попытайтесь уменьшить эфферентную связь (прямо говоря, количество объектов, которые вы имеете как соавторы).
- исключения являются частью API; аннотация @throws и предложения throws моделируют их. Некоторые тесты должны быть выделены, чтобы попытаться вызвать эти исключения и убедиться, что они на самом деле выбрасываются вместо более общего класса Exception или NullPointerException.
Рефакторинг тестов
Извлечение дублирования — хорошая практика и для тестов; целый ряд шаблонов поможет вам организовать тестовый код, если вам не хватает фантазии:
- базовые тесты (которые будут масштабироваться только до 1-2 родительских классов).
- Внешние объекты, такие как шаблон FixtureLoader, для создания поддельного экземпляра базы данных и его заполнения.
- Ограничение объектов для проверки результатов или аргументов, передаваемых в макеты.
- Утверждение библиотеки.
- Строители объектов для настройки сложных объектов или графиков.
Рефакторинг тестового кода также означает, что вы не будете выбрасывать пакет при первом изменении спецификации, из-за большого количества строк кода, которые должны измениться в нем. Если вы не имеете ни малейшего представления о том, каковы элементы этого списка, взгляните на книгу шаблонов xUnit .
Неполные вещи
Используйте неполные тесты для новой функциональности, о которой вы думаете, чтобы избежать многозадачности; Вы должны действительно закончить этот тест, его реализацию и рефакторинг, прежде чем перейти к следующей функции.
В PHP тест может быть передан как неполный с помощью $ this-> markTestIncomplete (), в то время как в Java вы можете просто вызвать исключение, в зависимости от вашей тестовой среды.
Обобщением этого метода для всех задач разработки является запись в блокноте , который я узнал из TDD на Примере и в серии James Shore Let’s TDD. Бумага работает лучше для меня, если я не общаюсь с кем-то, но файл .txt концептуально тот же.
Когда у вас есть готовый блокнот, вы можете записать все, что вам нужно сделать, когда это придет в голову, но это не связано с вашей текущей задачей. Дополнительные тесты и функции могут быть вставлены в качестве методов, но во многих случаях вы можете просто записать заметку, чтобы вам даже не приходилось соответствовать синтаксису или выбирать имя для теста сейчас .
Рефакторинг и идеи для его изучения должны идти в блокноте: по определению вы не можете написать тест на рефакторинг. Я использую некоторые разделы, такие как: следующие сценарии, которые еще не являются тестами, или неполные тесты и возможные варианты сценария (счастливый путь, случаи ошибок, уведомления), рефакторинг для выполнения, задачи инфраструктуры (такие как вставка X в сборку, выполнение всплеск с MongoDB.)
Блокнот гарантирует, что вы делаете хорошую работу, позволяя вам работать над одной задачей за раз, но не забывая ничего, что приходит на ум. Каждая идея может быть принята и оценена в следующем Pomodoro; Может быть, вы будете реализовывать это, может быть, вы бы оценили это как не добавляющую ценность. ?