На предыдущем шаге мы начали создавать инфраструктуру автоматизированного тестирования, проверяющую наличие
Предположим, у нас есть команда из десяти разработчиков, и каждый ежедневно записывает изменения кода в системе контроля версий. Один вносит изменение, «ломающее» выполнение ночной сборки и работу по ее тестированию. В этом сценарии мы, придя утром на работу, обнаружим отсутствие «зеленой сборки», и потребуется несколько минут или, что более вероятно, несколько часов, пока команда выяснит, какие именно изменения вызвали проблему, кто их внес и как это исправить.
Рассмотрим наиболее плохой вариант, когда проблема не была вызвана изменением кода, а связана с изменением тестовой среды (например, какой-то параметр конфигурации был установлен неправильно). Команда разработчиков может считать, что они устранили проблему, поскольку все тесты успешно пройдены, но на следующий день обнаружится, что ночью вновь произошел сбой.
Можно еще сильнее усложнить ситуацию, предположив, что в течение дня записано десять изменений в коде. Каждое из них потенциально могло породить ошибки, нарушающие выполнение автоматизированных тестов, что еще увеличивает сложность успешной диагностики и устранения проблем.
Короче говоря, медленная и нечастая обратная связь убивает процесс разработки. Особенно в случае больших команд. Проблема еще осложняется, если десятки, сотни и даже тысячи разработчиков ежедневно записывают изменения кода в системе контроля версий. В результате сборки и автоматические тесты часто сбоят, и разработчики даже приостанавливают на время запись изменений в системе контроля версий («зачем беспокоиться, ведь все равно сборка кода и его проверка сломаны»). Вместо этого для интеграции кода они дожидаются приближения конца проекта, что приводит ко всем нежелательным результатам крупных пакетов работы, интеграции в стиле big bang («большой взрыв») и проблемам с внедрением в производство[79].
Для предотвращения такого сценария нам нужны быстрые автоматические тесты, запускающиеся в средах сборки и тестирования всякий раз, когда в системе управления версиями записывается новое изменение. В этом случае мы можем найти и устранить любые проблемы немедленно, как это показывает пример команды GWS. Действуя так, можно обеспечить выполнение работы небольшими партиями, а также то, что в любой момент код готов к развертыванию.
В целом автоматизированные тесты относятся к одной из следующих категорий (перечислим, начиная от самых быстрых и до самых медленных).
• Модульное тестирование (юнит-тесты). Как правило, эти тесты проверяют один метод, класс или функцию изолированно от других, показывая разработчикам, что их код работает так, как задумано. По многим причинам, в том числе из-за необходимости поддерживать наши тесты быстрыми и не зависящими от состояния системы в целом, в модульных тестах используются заглушки для баз данных и других внешних зависимостей (например, функции изменены, чтобы возвращать статические, предустановленные значения вместо реального обращения к базам данных)[80].
• Приемочное тестирование. Как правило, это тестирование приложения в целом. Оно необходимо, чтобы убедиться, что более верхнеуровневая функциональность работает так, как задумано (например, бизнес-критерии приемки в соответствии с требованиями клиента, правильность API), и что отсутствуют ошибки регрессии (то есть не повреждены функции, ранее работавшие правильно). Хамбл и Фарли так определили разницу между модульным и приемочным тестированием: «Цель модульного тестирования — показать, что отдельная часть приложения делает то, что задумал программист… Цель приемочных тестов — доказать, что наше приложение делает то, что от него ожидает клиент, а не то, что оно должно делать, по мнению программиста». После того как сборка проходит наши модульные тесты, конвейер развертывания запускает приемочное тестирование. Любая сборка, прошедшая приемочное тестирование, обычно становится затем доступной для тестирования вручную (например, исследовательское тестирование, тестирование пользовательского интерфейса и так далее), а также для интеграционного тестирования.