Когда пишешь код, думай о тесте.
Когда пишешь тест, думай о коде.
Когда ты думаешь о коде и тесте как о едином,
тестирование просто, а код красив.
Тестирование является важным этапом основных методологий разработки.
Требования -> Проектирование -> Разработка -> Тестирование -> Запуск
Тестирование предшествует выпуску приложения в production и позволяет обнаружить и исправить большое количество ошибок. Исправить ошибки на этапе тестирования чаще всего дешевле и проще, чем обнаруженные на этапе внедрения.
Этапы тестирования:
Для web-проектов выделяют также следующие типы тестирования:
По типу выполнения тестирование разделяют на:
Модульное тестирование (Unit тестирование) — это проверка работоспособности и правильной работы отдельных частей (модулей) программы. Модуль для тестирования — это не обязательно модуль программы, чаще всего это отдельная "программная единица", поддающая тестированию: функция или метод какого-либо класса/объекта.
Модульный тест — это совокупность данных, подаваемых на вход тестируемой функции и совокупность результатов, ожидаемых от выполнения функции. Если фактические результаты выполнения совпадают с ожидаемыми, то такой тест считается пройденным. Прохождение теста подтверждает поведение, предполагаемое разработчиком. Если результаты не совпадают, то тест считается проваленным и это сигнал для разработчика, что нужно искать и исправлять ошибку.
Модульное тестирование — комплексная задача, в свою очередь состоящая из этапов:
Код тестов вместе с системой из запуска обычно размещают в отдельной папке. Сам процесс запуска тестов и проверки результатов максимально упрощают.
Тесты пишет разработчик, так как он точно понимает, какое поведение ожидается от того или иного модуля. Следует избегать написания разработчиком и кода, и тестов для этого кода, потому что в этом случае возможен вариант, когда тесты "подстраиваются" под написанный код.
Следуя принципу "раньше начали писать тесты — получили меньше багов в production" была разработана техника разработки через тестирование (TDD, test-driven development). При использовании этой техники сначала определяются с необходимым функционалом, затем пишутся тесты, проверяющие соблюдение этого функционала, а затем только код, этот функционал реализующий.
Требования -> Проектирование -> Тестирование -> Разработка -> Запуск
Таким образом, в какой-то момент времени у разработчика есть только тесты, но нет кода, который эти тесты покрывают, а потому все тесты провальные. По мере написания кода все больше и польше тестов становится пройденными. В момент, когда все модульные тесты пройдены, можно считать, что система удовлетворяет поставленным условиям.
Методика тесно связана с принципами «делай проще, дружище» (англ. keep it simple, stupid, KISS) и «вам это не понадобится» (англ. you ain’t gonna need it, YAGNI). Преимуществом данного метода является то, что при написании кода разработчик не задумавается о красоте и элегантности решения, он пишет код только для того, чтобы последний прошел тесты. И только после того, как все тесты пройдены, можно заниматься рефакторингом. Методика обязывает писать тесты на весь функционал системы, ведь для чего не будет написано тестов, для того не будет и написано кода.
Идея того, что новый тест проходит или не проходит, ясно показывает, что тест реально что-то проверяет, а не сделан "для галочки".
Несмотря на то, что кода в итоге пишется значительно больше, время на разработку уменьшается, т.к. большинство багов устраняется прямо на этапе написания кода и время на отладку уменьшается. Внесение изменений в функциональность или в код сразу же отразится на тестах, потому у разработчика будет возможность оперативно отреагировать на эти изменения. Соответсвенно, рефакторинг благодаря тестам покажет свою успешность или неуспешность.
Разработка, основанная на функционировании (behaviour-driven development – BDD) — ответвление от методики TDD, которое говорит о необходимости проверки поведения (функциональности) модулей. Т.е. заказчиком приложения описывается поведение системы, а разработчики задают вопросы касательно их понимания требований к системе и затем пишут код для реализации данного поведения.
Перед внедрением нового функционала разработчик вместе с заказчиком описывают требуемое поведение этого функционала, в результате чего написанные тесты будут указывать не просто на то, что "все работает", а на то, что "все работает как надо".
Например, в систему bug-tracker необходимо добавить напомнинание для тикетов, по которым долго не было активности. Требуемое поведение будет включать: