Практическая работа №27. Тестирование «белым ящиком»
Изучите объяснения, проанализируйте исходный код и выполните задания. Главная цель — подобрать такие тестовые данные, чтобы пройти по разным ветвям программы. Ответы вводите прямо на странице. В конце сохраните работу в PDF.
Что такое тестирование «белым ящиком»
При тестировании «белым ящиком» тестировщик видит внутреннее устройство программы: исходный код, условия, циклы и возможные пути выполнения.
Рассмотрим программу:
age = int(input("Введите возраст: "))
if age >= 18:
print("Доступ разрешён")
else:
print("Доступ запрещён")
В коде есть две ветви. Если проверить только значение 20, выполнится только первая ветвь. Чтобы проверить вторую, нужно использовать значение меньше 18, например 16.
age >= 18 | +---- True ----> "Доступ разрешён" | +---- False ----> "Доступ запрещён"
Для приведённой программы подберите два теста: один должен выполнить ветвь True, второй — ветвь False. Для каждого теста укажите входное значение и ожидаемый результат.
Что искать в исходном коде
При тестировании «белым ящиком» особенно внимательно рассматривают конструкции, которые изменяют путь выполнения программы:
if elif else for while return break continue
Пример:
def check_number(number):
if number > 0:
return "Положительное"
elif number < 0:
return "Отрицательное"
else:
return "Ноль"
У функции три основных результата: положительное число, отрицательное число и ноль. Значит, для проверки всех вариантов одного теста недостаточно.
Подберите минимальный набор значений number, который позволит получить все три результата функции. Для каждого теста запишите ожидаемый результат.
Покрытие операторов и ветвей
Покрытие кода показывает, какая часть программы была выполнена во время тестирования.
Если тесты выполнили 7 из 10 учитываемых элементов, покрытие можно представить так:
7 / 10 × 100% = 70%
Покрытие операторов показывает, какие выполняемые операторы программы были выполнены тестами.
Покрытие ветвей требует проверить разные направления выполнения условий.
if password == "1234":
print("Вход выполнен")
else:
print("Неверный пароль")
Для условия выше необходимо проверить оба результата:
password == "1234" → True password == "1234" → False
В программе есть 8 ветвей. Тестами выполнены 6. Рассчитайте покрытие ветвей в процентах. Затем объясните, что означает полученный результат.
Разбор функции с двумя условиями
Рассмотрим функцию расчёта стоимости доставки:
def shipping_cost(total, vip):
if total >= 5000:
delivery = 0
else:
delivery = 300
if vip:
delivery = max(0, delivery - 100)
return delivery
Первое условие может дать два результата:
total >= 5000 → True total >= 5000 → False
Второе условие тоже имеет два результата:
vip → True vip → False
Например, тест shipping_cost(6000, False) проходит по ветви бесплатной доставки и не применяет VIP-скидку. Тест shipping_cost(3000, True) проходит по платной доставке и применяет VIP-скидку.
Составьте минимальный набор тестов, который позволит увидеть оба результата первого условия и оба результата второго условия. Для каждого теста укажите входные данные, какие результаты условий он проверяет и ожидаемую стоимость доставки.
Практика: простое ветвление
Дана функция:
def check_age(age):
if age >= 18:
return "Совершеннолетний"
else:
return "Несовершеннолетний"
Сначала проанализируйте код, затем подберите тестовые данные. Не начинайте со случайных значений — сначала определите, какие ветви нужно выполнить.
1. Сколько ветвей имеет функция?
2. Подберите минимальный набор тестов для выполнения каждой ветви.
3. Для каждого теста укажите ожидаемый и фактический результат после запуска программы.
Практика: несколько условий
Дана функция определения оценки:
def get_grade(score):
if score < 0:
return "Ошибка"
if score > 100:
return "Ошибка"
if score >= 90:
return "5"
elif score >= 75:
return "4"
elif score >= 60:
return "3"
else:
return "2"
Обратите внимание: два разных условия возвращают строку "Ошибка". Получить один раз результат «Ошибка» недостаточно — нужно проверить обе причины.
Подберите тестовые значения для следующих ситуаций:
| Ситуация | Что нужно проверить |
|---|---|
| 1 | score < 0 |
| 2 | score > 100 |
| 3 | Результат «5» |
| 4 | Результат «4» |
| 5 | Результат «3» |
| 6 | Результат «2» |
После запуска функции запишите ожидаемый и фактический результат каждого теста. Затем объясните, почему значений 50 и 95 недостаточно для проверки всей функции.
Практика: система доступа
Исходный код:
def check_access(age, has_ticket, banned):
if banned:
return "Доступ запрещён"
if age < 18:
return "Только для совершеннолетних"
if has_ticket:
return "Доступ разрешён"
return "Нет билета"
Параметры:
age— возраст;has_ticket— есть ли билет:TrueилиFalse;banned— заблокирован ли пользователь.
Разработайте набор тестов, который позволит выполнить все четыре оператора return. Для каждого теста укажите значения трёх параметров и ожидаемый результат.
Практика: тестирование цикла
Дана функция:
def count_positive(numbers):
count = 0
for number in numbers:
if number > 0:
count += 1
return count
При тестировании циклов полезно проверить разные ситуации:
- цикл не выполняется ни одного раза;
- цикл выполняется один раз;
- цикл выполняется несколько раз;
- условие внутри цикла получает
True; - условие внутри цикла получает
False.
Разработайте минимум четыре теста. Обязательно должны присутствовать: пустой список, список из одного элемента, список из нескольких элементов и список, где встречаются как положительные, так и неположительные числа.
Найдите непроверенные ветви
Дана функция:
def calculate_discount(price, regular_customer):
discount = 0
if price >= 5000:
discount = 10
if regular_customer:
discount += 5
if discount > 15:
discount = 15
return discount
Студент создал только два теста:
print(calculate_discount(1000, False)) print(calculate_discount(6000, False))
Нужно определить, какие результаты условий уже выполняются, а какие ещё не проверены.
1. Какие ветви выполняют два готовых теста?
2. Какие ветви остаются непроверенными?
3. Какие дополнительные тесты нужно добавить?
4. Составьте итоговый набор так, чтобы каждое условие хотя бы один раз получило True и хотя бы один раз False.
Автоматическое измерение покрытия в Python
Покрытие можно оценивать не только вручную. Для Python можно использовать пакет coverage.py.
Установка:
python -m pip install coverage
Запуск файла main.py с измерением ветвей:
coverage run --branch main.py
Текстовый отчёт:
coverage report -m
HTML-отчёт:
coverage html
После этого создаётся каталог htmlcov, внутри которого можно открыть файл index.html.
Выберите одну из функций из заданий 5–9, поместите её в отдельный Python-файл и запустите с измерением покрытия ветвей. Укажите, какой процент покрытия получился до добавления новых тестов и после того, как вы добавили недостающие тесты.
Дополнительное задание: собственная функция
Создайте собственную функцию минимум с тремя условными конструкциями. Тематика может быть любой: стоимость заказа, уровень доступа, оценка, доставка, скидка или игровая логика.
Пример структуры:
def your_function(...):
if ...:
...
if ...:
...
else:
...
if ...:
...
return ...
Напишите свою функцию, затем составьте для неё тесты по принципу «белого ящика». В ответе приведите код функции и не менее четырёх тестов с ожидаемыми результатами. Постарайтесь выполнить все основные ветви.
Контрольные вопросы
- Чем тестирование «белым ящиком» отличается от тестирования «чёрным ящиком»?
- Почему при тестировании «белым ящиком» важно видеть структуру программы?
- Что называется покрытием кода?
- Что показывает покрытие операторов?
- Что показывает покрытие ветвей?
- Почему выполнения каждой строки программы может быть недостаточно для проверки всех вариантов поведения?
- Какие конструкции Python чаще всего создают разные пути выполнения?
- Какие варианты работы цикла желательно проверить?
- Означает ли 100% покрытия, что программа не содержит ошибок?
- Как понять, какого теста не хватает?
Кратко ответьте на контрольные вопросы. Ответы нумеруйте от 1 до 10.
Перед сдачей
После нажатия кнопки откроется окно печати. Выберите «Сохранить как PDF». В PDF попадут все ваши ответы полностью.