Классификация тестов
Традиционно тесты классифицируют как юнит, интеграционные, функциональные. Логика следующая:
- Юнит - тестирует один модуль или класс с зависимостями компиляции, и по возможности без модулей которые нужны только в рантайме. Другими словами старается тестировать поведение одной штуки в изоляции.
- Интеграционные - тестируют несколько модулей, примерно как они будут связаны в рантайме. Тестирует непосредственное взаимодействие нескольких штук.
- Функциональные - более-менее вся система как она будет работать. Тестирует опосредованное взаимодействие, очень многих штук сразу.
Мне она уже давно кажется абсолютно бесполезной.
Одна проблема с ней - размазанные границы. Многие тесты попадают в пару категорий. Вроде "в основном у нас один модуль, но вот эту зависимость не замокать". Или "вообще тест функциональный, но с настоящей БД сложно запускать в тимсити".
Вторая проблема - плохая связанность с операционными характеристиками теста. Пример: есть интеграционные-тесты на процедуру логина и на драйвер чужого сервиса. Они оба и правда интеграционные - собирают пару модулей вместе, мокают зависимости такой сборки. Первый ходит в заглушку БД и отдаёт фиктивные данные, второй получает фиктивные запросы и ходит в заглушку сервиса. При этом у них сильно отличается время работы, у первого 3±1ms у второго 30±10ms. Гонять сотню аналогов первого можно каждый Ctrl+S, сотню аналогов второго - только в перерывах на чай.
На практике полезнее другая классификация. Не концептуальная, зато однозначная и позволяющая делать практические выводы об операционных свойствах теста.
- Быстрые тесты. Пользуются только памятью и процессором, субквадратичные алгоритмы, входные данные менее 10MB.
- Медленные тесты. Пользуются одним внешним ресурсом (файлы, сети, видяхи :) ), субквадратичные алгоритмы, входные данные менее 100MB.
- Тяжёлые тесты. Пользуются многими внешними ресурсами, произвольные алгоритмы, произвольные объёмы данных.
С некоторыми исключениями про такие категории можно сказать следующее:
Быстрые тесты даже для крупного компонента займут не более минуты с пренебрежительно малым разбросом. Можно использовать агрессивные политики таймаута и ограничения памяти. Для компонента можно выполнять на каждое изменение в десяток строк, повестить на сохранение или фоновый прогон по кругу. Стоит выполнять для всего проекта для каждого коммита.
Медленные тесты займут до 5 минут для компонента, и будут иметь небольшие выбросы. Можно применить сдержанные политики таймаутов и памяти. Стоит выполнять для одного или нескольких компонентов на каждом коммите. Для всего проекта может выполнять CI.
Тяжёлые тесты занимают до 30 минут для компонента, могут иметь большие выбросы. Политики таймаутов и ограничения ресурсов будут работать только мягкие. Запускать их локально уместно только если есть инсайт на высокую вероятность поломки. В основном работают в CI.
Это конечно легко тюнится под конкретную кодовую базу, процессные и операционные реалии. Надеюсь идея понятна.
Кстати JUnit 5 добавил радикально улучшенную поддержку категоризации тестов.