Как мы используем автоматическое тестирование
В нашей компании мы используем следующие виды автоматических тестов:
- Acceptance tests - приемочные тесты, написанные с учетом требований заказчика
- Integration tests - интеграционные тесты. С помощью них мы тестируем поведение системы в комплексе с учетом БД и других зависимостей.
- Unit tests - модульные тесты. Предназначены для тестирования поведения отдельных классов, все зависимости на другие классы заменяются Mock или Stub объектами
Как мы понимаем, что нужно писать тесты
- Если проект планируется больше чем на 3-4 месяца. За такой срок команда успевает забыть требования к функционалу, который делался в начале проекта, и тесты помогают не потерять эти требования
- Если есть нетривиальная логика класса/метода, требования к которой сложно уложить в голове - пишем юнит тест
- Если видим требования, которые потенциально могут измениться - пишем интеграционный или приемочный тест
- Если находим баг - пишем тест, что бы он больше не повторился
При выборе того, какой тест писать учитываем то, что самые дешевые и простые в поддержке модульные тесты, но в то же время у них наиболее слабая связь с требованиями заказчика.
Как мы выбираем, какие тесты писать
- Приемочные тесты пишут наши QA специалисты (или программисты, если необходима их помощь)
- Интеграционные тесты пишем в случаях:
- если хотим проверить работу системы в комплексе
- если затраты на создание и поддержку контекста их выполнения (например состояния БД) меньше, чем затраты на создание Mock или Stub для модульных тестов
- Модульные случаи во всех остальных случаях
Что происходит с тестами потом
Во первых - у нас есть система Continius Integration, с помощью которой мы отслеживаем, что все тесты работают после каждого коммита. Во вторых - у нас есть процесс Code Review, в рамках которого проверяются, в том числе, тесты по следующим требованиям:
Требования к тестам
- Должны соблюдаться правила именования тестов:
- Для модульных тестов тестовый класс должен называться относительно класса, который должен быть протестирован с добавлением окончания Test
- Для интеграционных тестов название тестового класса выбирается исходя из названия тестируемой части системы
- Название теста должно отражать его содержание
- Тест должен иметь комментарий, в котором описано что именно тестируется, входные условия и ожидаемый результат
- Тест должен быть построен по ААА шаблону - т.е. должен содержать 3 зоны Arrange-Act-Assert. В зоне Arrange настраивается контекст, в зоне Act выполняется тестируемое действие, в зоне Assert производятся проверки
- Тест должен быть лаконичным. Прячем всю лишнюю обработку в хелперы.
- Тест не должен проверять все возможные ситуации (и тем более позитивные и негативные тесты). Допускается вложение 2-3 ситуаций совпадающих по контексту, который должен следовать из названия теста. Если тест ломается, должно быть однозначно понятно что именно пошло не так.
- В тестах стараемся не использовать ни условия, ни циклы.
- Тесты не должны иметь влияние друг на друга и не зависеть от окружения (если необходим какой-либо контекст, тест сам заботиться о его создании и корректном удалении).
- По возможности тесты пишем максимально быстрыми.
В итоге все разработчики понимают как и когда писать тесты и мы можем быть уверены в качестве нашего кода.
Наверняка можно что-нибудь улучшить в этом процессе, и я был бы очень благодарен читателям за обратную связь.