Перейти к основному содержимому
Informatik.uz
Бакалавриат · 4-й курсГлава 1. Программная инженерия

Тестирование и контроль качества

Уровни тестирования, пирамида тестов, анализ граничных значений и покрытие кода. Вы узнаете, как обеспечивать качество программ с помощью автоматических тестов, ревью кода и CI.

Тема 2 из 2Чтение: 2 минОбновлено: 27 октября 2026 г.
Список тем (2 из 2)

Тестирование — это процесс поиска дефектов (bug) путём сравнения ожидаемого поведения программы с фактическим результатом. Оно не доказывает отсутствие ошибок: как подчёркивал Эдсгер Дейкстра, тест может показать наличие дефектов, но не их отсутствие. Контроль качества (QC) направлен на поиск дефектов в готовом продукте, а обеспечение качества (QA) — на улучшение процессов, чтобы дефекты не возникали.

Тесты проводят на нескольких уровнях. Модульные (unit) тесты проверяют отдельную функцию или класс изолированно, интеграционные — взаимодействие модулей, системные — приложение целиком, а приёмочные (acceptance) — соответствие продукта требованиям заказчика. Согласно идее пирамиды тестов, больше всего должно быть быстрых и дешёвых модульных тестов, меньше — интеграционных и меньше всего — медленных и сложных тестов интерфейса.

При выборе тест-кейсов используют два основных подхода: чёрный ящик (по входам и выходам, без знания внутреннего кода) и белый ящик (по структуре кода). Для выбора входных значений применяют классы эквивалентности и анализ граничных значений: например, если доступ разрешён с 18 лет, нужно проверить 17, 18 и 19, ведь ошибки чаще всего возникают на границе. На Python модульный тест выглядит так: assert is_adult(18) is True и assert is_adult(17) is False.

Для оценки качества тестов используют покрытие кода (code coverage) — долю кода, которую выполняют тесты. Высокое покрытие не гарантирует качества, потому что даже тест без проверок (assert) увеличивает покрытие. Качество поддерживают и другие практики: ревью кода (code review), статический анализ (линтер), автоматический запуск тестов в CI и регрессионные тесты, которые проверяют, что новое изменение не сломало ранее работавшие функции. Чем раньше найден дефект, тем дешевле его исправить.

Главное

  • Тестирование показывает наличие дефектов, но не может доказать их отсутствие.
  • Уровни: модульные, интеграционные, системные и приёмочные тесты; в пирамиде больше всего модульных.
  • Классы эквивалентности и граничные значения сокращают число тестов и эффективно находят ошибки.
  • Покрытие кода полезно, но не является единственной мерой качества.
  • CI, ревью кода и регрессионные тесты поддерживают стабильное качество.

Практические задания

  1. На Python напишите функцию is_adult(age), возвращающую True для возраста 18 и старше, и составьте с помощью pytest не менее пяти тестов для граничных значений (17, 18, 19) и необычных значений (0, -5).
  2. Командами coverage run -m pytest и coverage report измерьте покрытие кода, найдите непокрытую строку и добавьте тест, который её проверяет.
  3. Протестируйте какую-нибудь веб-форму (например, регистрацию) методом чёрного ящика: с учётом классов эквивалентности и граничных значений составьте таблицу не менее чем из восьми тест-кейсов (входные данные и ожидаемый результат).

Вопросы для закрепления

Проверьте себя: сначала подумайте, потом откройте ответ.

  1. 1Чем отличаются модульные тесты от интеграционных?
    Модульный тест проверяет отдельную функцию или класс изолированно, а интеграционный — что несколько модулей правильно работают вместе.
  2. 2Почему 100% покрытия кода не гарантирует отсутствия ошибок?
    Покрытие показывает, что код выполнялся, а не что результат верен; тесты без проверок или со слабыми проверками тоже увеличивают покрытие.
  3. 3Для чего нужны регрессионные тесты?
    Чтобы проверить, что новое изменение не сломало ранее работавшие функции.

Пройдено тем: 0 из 2

Войти и отметить