Условная логика в тесте (Conditional Test Logic)

Тест содержит операторы if, switch или циклы for/while. В зависимости от условий тест проверяет разное поведение — или не проверяет ничего вовсе.

Симптомы

  • if, else if, switch внутри @Test-метода
  • for (Item item : list) { assertTrue(...) } — если список пустой, ни один assert не выполнится
  • Тест проверяет одно поведение при одних данных и другое при других
  • Тест всегда зелёный, даже когда список пуст или коллекция не содержит нужных элементов

Причины возникновения

  • Попытка охватить несколько сценариев одним тестом через ветвление
  • Копирование стиля продакшн-кода в тесты — «здесь тоже нужен if»
  • Незнание параметризованных тестов (@ParameterizedTest) как альтернативы
  • Стремление написать «универсальный» тест, работающий при разных данных

Почему это проблема

  • Непредсказуемость: тест может не выполнить ни одного assert и при этом быть зелёным
  • Разная логика при разных данных: сложно понять, что именно проверяется и в каком сценарии
  • Скрытые ошибки: условие никогда не выполняется в CI — тест зелёный, дефект не обнаружен
  • Трудно читать и поддерживать: нужно прослеживать все ветки в уме

Решение

Конкретные сценарии без ветвлений, при необходимости — @ParameterizedTest:

// ❌ for + if — может не выполнить ни один assert
for (Product p : catalog.getDiscounted()) {
    if (p.getCategory().equals("ELECTRONICS")) assertTrue(p.getDiscount() >= 10);
    else assertTrue(p.getDiscount() >= 5);
}

// ✅ явный сценарий + проверка непустоты перед итерацией
@Test
void electronicsDiscountIsAtLeast10Percent() {
    assertThat(catalog.getDiscounted())
        .filteredOn(p -> p.getCategory().equals("ELECTRONICS"))
        .isNotEmpty()
        .allMatch(p -> p.getDiscount() >= 10);
}