JavaOpt: Тестирование
JavaOpt: Тестирование
- Соблюдение TDD (Test-Driven Development) позволяет избегать ошибок и стабилизирует работу кода
- Тесты так же выжны как и продуктивный код. Основной плюс их в применении изменений - чем их больше, тем проще найти ошибку при изменениях
3.Каждый тест должен строиться по процессу:
- Build - подготовка данных/объектов к тесту
- Operate - выполнение действий (позитивных или деструктивных)
- Check - проверка результатов тестирования
- Тест должен легко читаться. Все тесты желательно делать по одному принципу для всего приложения
- Количество
assert
лучше сводить к минимуму - 1 тест проверяет 1 действие
- Тесты рекомендовано FIRST:
F - Fast - тесты должны быть быстрыми
I - Independent - изолированными друг от друга
R - Repeatable - должны отрабатывать одинаково при любых условиях, они не должны зависеть от внешних ресурсов (лучше использовать mock или stub)
S - Self-Validating - недвусмысленны: либо прошли успешно, либо нет
T - Timely - должны писаться перед продуктивным кодом - Следует считать, что в коде всегда будет ошибка пока не будет наложен тест
- Использовать утилиты для проверки покрытия (code coverage). Например, Jacoco
- После обнаружения бага в продуктиве полезным будет наложение на него теста
- Все внешние данные внешних ресурсов должны быть вынесены за код. Сюда входят например: ответы от внешних сервисов в различных форматах, SQL запросы, бинарные документы и т.д.
- В именах тестовых методов следует отображать какие-то свойства, действия, настройки и т.п. - из названия должно быть понятно что будет тестироваться и при каких уникальных условиях
- Для простоты восприятия, для тестовых методов можно добавлять краткое описание. Например, JUnit имеет аннотацию
@DisplayName(“${test_name}”)
и@DisplayNameGenerator(*.class)
- Тестирование не говорит о корректной работе кода (если он успешно выполнен), но если тест выполнен с ошибкой - это должно свидетельством об ошибке
- Желательно чтобы тесты проверяли не какое-то абстрактное наличие значения чего-либо, а четкое значение. Например:
1 | List<Object> x = new ArrayList(); |
Или хотя бы:
1 | assertThat(x.isEmpty, not(true)); |
- При наличии логических или бизнес связей между несколькими тестами рекомендуется объединять их в группы:
1 | class MasterTest { |
- Тестирование разбивается на виды:
- Unit-тесты. Тестирование изолированных методов. Внешние ресурсы заменяются на mock или stub. Основной вид тестов
- Integration-тесты. Тестируют взаимодействие межде компонентами в рамках приложения. Для объектов - вызов методов и работа с другими сервисами; для сервисов - используется когда код будет помещен в контейнеры, тестирует работу с БД (как правило, embedded) и прочими внешними ресурсами (как правило, их stub или mock); для подсистем - тестируется использование внешними системами (вызов внешних сервисов, предоставленных приложением).
- System-software-тесты. Тестируют интеграцию с действующими внешними системами и ресурсами. Могут использовать mock, но желательна интеграция с действительными ресурсами в соответствующей среде
- Условно, тестирование можно разделить на 3 этапа:
- Красный. Пишутся только основные интерфейсы для тестов - основа, по которой можно понять основные функции приложения или его частей. Де-факто. Это просто скелет
- Зеленый. К методам, подготовленным на красном этапе добавляется наполнение чтобы тест выполнялся успешно. Это выполняется для того чтобы можно было контролировать процесс разработки (точнее, поддержка его в постоянно работчем состоянии)
- Постепенно, мелкими шагами дорабатываются тесты и реализуется логика приложения. Поскольку тесты уже наложены, выполняться они будут с ошибками, которые будет легко найти и выявить причину
- Часто бывает полезным добавление fuzz-тестов (fuzzing) - они намеренно создают ошибочные ситуации или условно случайный набор данных. Задача - найти уязвимые места в приложении, которые изначально являются неочевидными. Генерация должна включать cлучаи успешной первичной проверки (т.е. случаи когда визуально данные корректны и проходят валидацию, но де-факто они являются ошибочными). Данные тесты можно писать самостоятельно, либо использовать библиотеки (например, Snodge)
- Желательно заранее продумать какие инструменты и библиотеки будут использоваться для каждого слоя тестирования, например:
- Unit-тесты - JUnit, TestNG
- UI-тесты - Selenium, Cypress
- Производительность - JMeter, Gatling
- Тест контрактов - Spring Cloud Contract, Pact
- тесты изменений - PITest
- Тесты необходимо поддерживать актуальными. Если они отключаются необходимо указать причину
Comments
Comment plugin failed to load
Loading comment plugin