Тесты для школьных задач Python: как проверять решение
Автор: Казачкин Даниил Михайлович · Обновлено
Тест — это конкретный ввод вместе с заранее известным ожидаемым результатом. Один удобный пример подтверждает мало: нужны обычный случай, минимальная граница, значение на пороге…
Тест — это конкретный ввод вместе с заранее известным ожидаемым результатом. Один удобный пример подтверждает мало: нужны обычный случай, минимальная граница, значение на пороге и случай, где вероятна ошибка. Сначала вычислите ответ независимо от программы.
Проверяем функцию автоматически
def is_positive_even(number):
return number > 0 and number % 2 == 0
assert is_positive_even(4) is True
assert is_positive_even(3) is False
assert is_positive_even(0) is False
assert is_positive_even(-2) is False
print('Все проверки пройдены')Если функция верна, появится одна строка. При нарушении assert программа остановится на конкретном примере с AssertionError.
Тест должен различать версии
Значение 4 не обнаружит ошибку number >= 0 вместо number > 0, а тест 0 обнаружит. Хороший набор выбирается из структуры условия. Для диапазона проверяйте обе границы и соседние значения; для списка — пустой, один элемент и повторы; для деления — нулевой делитель.
Не вычисляйте ожидаемое тем же ошибочным кодом. Запись assert result == function_again(input) ничего не доказывает. Имена тестов или комментарии должны объяснять, какое правило защищает пример.
Собственный набор регрессии
Напишите функцию count_digits(number) для неотрицательного целого и не менее пяти assert: 0, однозначное, число с нулями внутри, круглая степень десяти и обычный случай. Намеренно внесите ошибку и убедитесь, что хотя бы один тест падает. После исправления сохраните набор: он защищает поведение при следующих изменениях.
Набор регрессии по классам случаев
Для функции normalise_score(value) определите контракт: значения ниже нуля становятся нулём, выше ста — ста, остальные сохраняются. Подберите тесты не случайным списком, а классами: ниже нижней границы, ровно на ней, внутри, на верхней и выше. Добавьте числовой тип с дробной частью, если контракт его допускает. Дайте каждому assert короткий комментарий о защищаемом правиле. Затем сломайте один оператор сравнения и убедитесь, что падает тест соответствующей границы. Набор считается полезным, если объясняет требование и различает правдоподобные ошибочные реализации.
Практикум: набор тестов по классам входа
Для функции ограничения балла диапазоном 0–100 составьте тесты: ниже нуля, ровно 0, внутри, ровно 100 и выше 100. Дайте каждому тесту название защищаемого правила. Затем измените <= на < и убедитесь, что падает конкретная граница. Добавьте неверный тип только если контракт определяет его обработку. Не заменяйте набор десятками случайных чисел: классы эквивалентности и границы должны различать правдоподобные ошибки. После исправления повторите весь набор.
Контрольная точка
Почему тест значения 50 не проверяет поведение на 0 и 100? Внутренний пример проходит у многих реализаций, а граница отличает включение от исключения.
Частые вопросы
Сколько тестов достаточно для школьной задачи?
Число зависит от ветвей и контракта. Нужны обычные случаи, каждая граница, пустой или минимальный ввод и варианты, активирующие разные ветви. Тест должен иметь причину, а не быть случайным числом.
Связанные исследования
- AlphaDev: как обучение с подкреплением нашло более быстрые алгоритмы сортировки — Разбираем AlphaDev без громких обобщений: поиск ассемблерных программ, проверка корректности, benchmark и интеграция малых сортировок в LLVM libc++.
- Алгоритм Гровера: квантовый поиск, оракул и небольшой пример на Qiskit — Объясняем алгоритм Гровера: O(√N) запросов, фазовый оракул, амплитудное усиление, пример Qiskit и ограничения реального ускорения.
- CRDT: как реплики сходятся без центрального разрешения конфликтов — Объясняем CRDT через strong eventual consistency, state- и operation-based модели, G-Counter, семантику удаления и ограничения бизнес-инвариантов.