Какие основные техники и примеры тестирования методом белого ящика?

Ответ

Тестирование белого ящика (структурное тестирование) основано на знании и анализе внутреннего кода приложения. Основные техники:

  • Покрытие операторов (Statement Coverage): Каждая строка кода должна быть выполнена хотя бы раз.
  • Покрытие ветвей (Branch/Decision Coverage): Каждая возможная ветвь (true/false) в условиях должна быть выполнена.
  • Покрытие условий (Condition Coverage): Каждое булево подвыражение в условии должно быть и true, и false.

Пример для анализа покрытия:

def calculate_discount(amount: float, is_member: bool) -> float:
    discount = 0.0
    if amount > 100:               # Ветвь 1 (amount > 100)
        discount = 0.1
    if is_member:                  # Ветвь 2 (is_member)
        discount += 0.05
    return amount * (1 - discount)
Тест-кейс (amount, is_member) Покрытые строки Покрытые ветви (amount>100, is_member)
(50, False) Все, кроме discount = 0.1 и discount += 0.05 (False, False)
(150, False) Все, кроме discount += 0.05 (True, False)
(150, True) Все строки (True, True)
(50, True) Все, кроме discount = 0.1 (False, True)

Другие техники:

  • Тестирование циклов: Проверка нулевых, одинарных, множественных итераций и выхода из цикла.
  • Мутационное тестирование: Внесение мелких изменений в код (мутантов) для оценки эффективности тестового набора. Если тесты не обнаруживают мутант — тесты недостаточны.
  • Статический анализ: Поиск потенциальных дефектов и "запахов кода" с помощью инструментов (SonarQube, Pylint, ESLint) без запуска программы.

Ответ 18+ 🔞

А, так вот ты как, блядь, структурное тестирование, оно же тестирование белого ящика! Это когда ты в код залезаешь, как в холодильник ночью, и смотришь, что там внутри творится, а не просто на кнопочки снаружи тыкаешь. Основано на знании, сука, внутренностей. Не на "ой, а что будет, если сюда плюнуть?", а на "так, щас мы эту строчку ебнем, а потом вот эту ветку проверим".

Основные техники, которые у тебя в арсенале должны быть, а то нихуя не тестер, а так, мартышлюшка с клавиатурой.

Покрытие операторов (Statement Coverage) — это вообще базовое, как "не забыть штаны надеть". Каждую строчку кода, блядь, хоть раз выполнить. Каждую! Даже ту, которая discount = 0.0. А то вдруг там, сука, ошибка в присваивании нуля? Вдруг ноль — не ноль, а какая-нибудь ядрёна вошь? Надо проверить.

Покрытие ветвей (Branch/Decision Coverage) — это уже посерьёзнее. Это когда у тебя в коде if сидит, как хитрая жопа на диване. И ты должен заставить его сработать и как true, и как false. На каждую развилку, блядь, нужно заехать с двух сторон. Иначе как узнаешь, что в ветке else не спрятался какой-нибудь пидарас шерстяной, который всё сломает?

Покрытие условий (Condition Coverage) — это вообще, блядь, тонкая работа. Это когда внутри условия у тебя не просто (amount > 100), а, допустим, (amount > 100 and is_member or day == 'Friday'). И ты должен каждую эту маленькую булеву подпиздушку и в true, и в false загнать. Чтобы ни одна не отсиделась в тени.

Вот смотри, пример для разбора полётов:

def calculate_discount(amount: float, is_member: bool) -> float:
    discount = 0.0
    if amount > 100:               # Ветвь 1 (amount > 100)
        discount = 0.1
    if is_member:                  # Ветвь 2 (is_member)
        discount += 0.05
    return amount * (1 - discount)

И вот мы, блядь, как проктологи, составляем табличку, чтобы всё проверить:

Тест-кейс (amount, is_member) Покрытые строки Покрытые ветви (amount>100, is_member)
(50, False) Все, кроме discount = 0.1 и discount += 0.05 (False, False)
(150, False) Все, кроме discount += 0.05 (True, False)
(150, True) Все строки (True, True)
(50, True) Все, кроме discount = 0.1 (False, True)

Видишь? Чтобы покрыть ВСЕ ветви, нам нужно аж четыре теста, ёпта! Не два, а четыре! Потому что комбинаций хуёво-маё — овердохуища. Если только на (150, True) проверишь, то про случай "не член, но денег дохуя" или "член, но нищеброд" нихуя не узнаешь. А там может скидка ебанётся в минус и начнёт деньги доплачивать!

А есть ещё, блядь, другие техники, чтоб мозг выебать окончательно:

  • Тестирование циклов: Это отдельная песня. Надо проверить: а если цикл ноль раз выполнится? А если один раз? А если сто раз? А если он, сука, вообще никогда не закончится и накроется медным тазом? Все эти варианты нужно впендюрить в тесты.
  • Мутационное тестирование: Вообще пиздец, извращение. Берёшь рабочий код и начинаешь в него мелко, по-тихому, гадить. Меняешь + на -, > на >=, удаляешь строчку. Это создаёт "мутантов". И смотришь: если твои тесты этого мутанта не убили — значит твои тесты говно, они спят. Мутант живёт, а должен быть убит. Эффективность тестового набора оценивается по тому, сколько ублюдков-мутантов он перетрахал.
  • Статический анализ: А это когда ты код даже не запускаешь, а просто даёшь его почитать умной программе (типа SonarQube, Pylint). Она смотрит на него и говорит: "Слушай, а тут у тебя переменная не используется, как мудя в проруби. А тут потенциальное деление на ноль, ебать тебя в сраку. А тут стиль говнаный, читать невозможно". Ищет запахи кода, блядь, не запуская его. Полезная штука, чтобы не выглядеть полным распиздяем перед коммитом.

Вот так вот, сука. Тестирование белого ящика — это не просто "работает? работает!". Это вдумчивый, ебучий анализ каждой строчки, каждой веточки, каждого условия. Чтобы потом на проде не вылезло: "ой, а мы эту ситуацию не проверяли".