← Назад к вопросам

Что такое парадокс пестицида?

1.3 Junior🔥 111 комментариев
#Теория тестирования

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое парадокс пестицида?

Парадокс пестицида — это явление в тестировании, когда повторное использование одних и тех же тест-кейсов перестаёт находить новые баги. Баги остаются, но тесты их не ловят, потому что код был изменён под уже известные проблемы.

Суть проблемы

Представь фермера, который опрыскивает поле одним и тем же пестицидом. Сначала пестицид уничтожает насекомых. Но через время насекомые приспосабливаются. Фермер продолжает опрыскивать, но пестицид уже не работает. Так же и с тестами.

Аналогия:

  • Пестицид = Тесты
  • Насекомые = Баги
  • Сопротивляемость = Код адаптируется к известным тест-кейсам

Как это происходит

Этап 1: Новые тесты, находят баги

Пишу тест для валидации email:

def test_email_validation():
    assert is_valid_email("user@example.com") == True
    assert is_valid_email("invalid-email") == False

Разработчик видит падающий тест, исправляет баг.

Этап 2: Тот же тест, баги уже найдены

Пишу новую фичу, но не добавляю новые тест-кейсы. Запускаю старые тесты — все зелёные.

Но я не тестирую:

  • Email с 40 символами в локальной части
  • Идентификаторы email+tag
  • Кириллицу в домене
  • Новую логику разработчика

Этап 3: Баги остаются незамеченными

Код изменился под старые тест-кейсы, но новые сценарии не покрыты. Баги находят пользователи.

Реальный пример

Старые тесты:

class TestUserCreation:
    def test_create_user_with_valid_name(self):
        user = create_user("John", "john@example.com", 25)
        assert user.name == "John"
    
    def test_create_user_with_short_name(self):
        with pytest.raises(ValidationError):
            create_user("J", "j@example.com", 25)

Новая логика разработчика:

def create_user(name, email, age):
    if len(name) < 2:
        raise ValidationError("Name too short")
    
    # НОВОЕ: Возрастная проверка (баг: нет теста)
    if age < 18:
        raise ValidationError("User must be 18+")
    
    # НОВОЕ: Email подтверждение (баг: не проверяли)
    send_confirmation_email(email)
    
    return User(name=name, email=email, age=age)

Что упустили тесты:

  • Возрастная проверка: create_user("John", "john@example.com", 17) не тестировалось
  • Email подтверждение не проверялось

Симптомы парадокса

  1. Тест-ран всегда зелёный месяцами
  2. Юзеры находят баги в production
  3. Одни и те же тест-кейсы не обновляются
  4. Высокий баг-rate после релиза
  5. Скука в работе с тестами

Как избежать парадокса

Стратегия 1: Расширять тест-кейсы

Плохо:

def test_age_validation():
    assert is_valid_age(25) == True
    assert is_valid_age(-5) == False

Хорошо:

@pytest.mark.parametrize("age,expected", [
    (0, False),
    (17, False),
    (18, True),
    (65, True),
    (120, True),
    (121, False),
    (999, False),
    (-1, False),
])
def test_age_validation(age, expected):
    assert is_valid_age(age) == expected

Стратегия 2: Exploratory Testing

Не только автотесты. Интуитивный поиск багов:

  • Некорректные данные
  • Double-click, rapid clicks
  • Отключённый JavaScript
  • Разные языки системы
  • Разные временные зоны
  • 100 открытых вкладок

Стратегия 3: Mutation Testing

Вноси баги в код и проверяй, падают ли тесты:

# Оригинал
def is_admin(role):
    return role == "admin"

# Мутация
def is_admin(role):
    return role == "admin" or role == "moderator"  # BAG

# Тест должен упасть
def test_only_admin():
    assert is_admin("moderator") == False

Стратегия 4: Property-Based Testing

Используй Hypothesis для генерации случайных входов:

from hypothesis import given, strategies as st

@given(st.integers())
def test_abs_positive(x):
    assert abs(x) >= 0

Стратегия 5: Обновлять при каждом изменении

Новая фича → Новые тесты
Исправление → Тест на баг
Рефакторинг → Проверка старых тестов

Стратегия 6: Разнообразить тестирование

Не только unit-тесты:

  • Unit tests
  • Integration tests
  • E2E tests
  • Performance tests
  • Security tests
  • Exploratory testing

Стратегия 7: Анализировать баги production

Когда юзер находит баг:

  1. Создай тест, воспроизводящий баг
  2. Убедись, что тест падает
  3. Разработчик исправляет
  4. Тест становится зелёным
  5. Тест остаётся в наборе

Мониторинг парадокса

Метрики:

  1. TCE (Test Case Effectiveness) — баги найдено / всего тестов
  2. DER (Defect Escape Rate) — баги в production / всего
  3. Code Coverage Trend — увеличивается ли покрытие
  4. Bug Type Distribution — новые типы багов в production

Пример:

Месяц 1: 50 тестов → 20 багов (40% эффективность)
Месяц 2: 50 тестов → 10 багов (20% эффективность)
Месяц 3: 50 тестов → 5 багов (10% эффективность) ← Парадокс!

Цикл обновления тестов

Неделя 1: 20 новых тест-кейсов
Неделя 2: Расширяю граничные случаи
Неделя 3: Добавляю exploratory результаты
Неделя 4: Анализирую упущенные сценарии
Неделя 5: Mutation testing
Неделя 6: Начинаю заново

Практический совет

Парадокс пестицида — признак застоя. Если месяцами не находишь новые баги и юзеры обнаруживают проблемы:

  1. Добавь граничные случаи
  2. Запусти exploratory testing
  3. Используй mutation testing
  4. Разнообразь методы тестирования
  5. Анализируй баги в production
  6. Требуй новых тест-кейсов при каждой фиче

Помни: тесты, которые не находят баги — это плохие тесты. Их нужно улучшать постоянно.

Что такое парадокс пестицида? | PrepBro