Ответ
Тестирование белого ящика (структурное тестирование) основано на знании и анализе внутреннего кода приложения. Основные техники:
- Покрытие операторов (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). Она смотрит на него и говорит: "Слушай, а тут у тебя переменная не используется, как мудя в проруби. А тут потенциальное деление на ноль, ебать тебя в сраку. А тут стиль говнаный, читать невозможно". Ищет запахи кода, блядь, не запуская его. Полезная штука, чтобы не выглядеть полным распиздяем перед коммитом.
Вот так вот, сука. Тестирование белого ящика — это не просто "работает? работает!". Это вдумчивый, ебучий анализ каждой строчки, каждой веточки, каждого условия. Чтобы потом на проде не вылезло: "ой, а мы эту ситуацию не проверяли".