Тестирование программного обеспечения — это проверка того, как программа ведет себя на заранее выбранном конечном наборе ситуаций, и сравнение фактического результата с ожидаемым. Ожидаемое берется из требований, спецификации или здравого смысла пользователя.
Содержание
- Мини-словарь: что путают чаще всего
- Зачем тестировать и где границы
- Уровни тестирования
- Виды тестирования
- Подходы: черный, белый и серый ящик
- Ручное и автоматизированное тестирование
- Пирамида тестов
- Пример: модульный тест ловит ошибку на границе
- Как организован процесс
- Выводы
- Где применяется / связь с практикой
- FAQ
Тестирование не доказывает, что ошибок нет: оно показывает, что на проверенных сценариях их не нашли. Ниже — уровни и виды тестирования, ручное и автоматизированное, пирамида тестов и пример на Python, где тест ловит ошибку на границе.
Мини-словарь: что путают чаще всего
| Термин | Что это | Пример |
|---|---|---|
| Ошибка (error, mistake) | Действие человека, которое приводит к неверному коду | Разработчик написал > вместо >= |
| Дефект (defect, bug) | Изъян в коде или документации | В функции неверное условие |
| Сбой (failure) | Видимое отклонение поведения при запуске | Клиенту с заказом ровно на 3000 насчитали доставку |
| Отладка | Поиск причины сбоя в коде и ее устранение | Разработчик находит > и правит |
| QA (обеспечение качества) | Процессы, которые предотвращают дефекты | Ревью кода, стандарты, требования к тестам |
Цепочка: ошибка человека -> дефект в коде -> сбой при запуске. Тестирование находит сбой, отладка — дефект, а QA шире и включает процессы, которые не дают дефекту появиться.
Еще одна пара: верификация отвечает на вопрос «сделали ли продукт правильно» (соответствует спецификации), валидация — «сделали ли правильный продукт» (решает задачу пользователя). Продукт может пройти первую и провалить вторую, если ошибка в самих требованиях.
Зачем тестировать и где границы
Тестирование дает информацию для решения, можно ли выпускать релиз и какие риски остаются. Чем раньше найден дефект, тем обычно дешевле исправление.
Три принципа из программы ISTQB, которые стоит держать в голове:
- Исчерпывающее тестирование невозможно, поэтому проверки выбирают по рискам и техникам тест-дизайна.
- Дефекты скапливаются: обычно большая их часть сосредоточена в небольшой части модулей.
- Одни и те же тесты со временем перестают находить новые ошибки, набор нужно пересматривать.
Уровни тестирования
| Уровень | Что проверяет | Кто обычно выполняет | Пример |
|---|---|---|---|
| Модульное (unit) | Функцию или класс в изоляции | Разработчик | Расчет стоимости доставки |
| Интеграционное | Взаимодействие модулей и внешних систем | Разработчик, автотестировщик | Сервис заказов пишет в базу и вызывает платежный шлюз |
| Системное | Систему целиком против требований | Тестировщик | Заказ через интерфейс от начала до конца |
| Приемочное | Готовность с точки зрения заказчика | Заказчик, аналитик, пользователи | Бизнес подтверждает сценарий возврата |
Оговорка: системное тестирование — уровень проверки любой программной системы целиком, а не только операционных систем, как иногда пишут. Границы уровней размыты: тест API с настоящей базой одни команды называют интеграционным, другие — системным.
Виды тестирования
Если уровень — это «что проверяем», то вид — «какое свойство». Функциональное тестирование проверяет, что система делает: при таких входных данных получаем ли ожидаемый результат.
Нефункциональное тестирование проверяет, как система это делает:
| Вид | Типичный вопрос |
|---|---|
| Нагрузочное | Выдержит ли сервис ожидаемое число пользователей с приемлемым временем ответа |
| Стрессовое | Что будет за пределами нормы и восстановится ли сервис |
| Объемное | Не деградирует ли поиск на десятках миллионов записей |
| Безопасности | Можно ли получить чужой заказ, подменив id в запросе |
| Юзабилити | Найдет ли новый пользователь кнопку возврата |
| Совместимость | Корректно ли все работает в разных браузерах и на телефоне |
| Надежность | Не растет ли потребление памяти за сутки работы |
Проверки, связанные с изменениями: дымовое (smoke) — сборка запускается и основные функции живы; ретест — исправленный дефект больше не воспроизводится. Регрессионное тестирование проверяет, что изменения не сломали работавшее, — это отдельная большая тема.
Подходы: черный, белый и серый ящик
Черный ящик — проверка поведения по требованиям без взгляда в код (классы эквивалентности, граничные значения). Белый ящик — тесты по структуре кода: ветвления, покрытие строк и условий. Серый ящик — частичное знание устройства, например схемы базы или API. Отдельно различают статическое тестирование (без запуска: ревью, статический анализ) и динамическое (с запуском).
Ручное и автоматизированное тестирование
| Критерий | Ручное | Автоматизированное |
|---|---|---|
| Где сильнее | Исследование, юзабилити, новые функции | Повторяющиеся проверки, расчеты, API, нагрузка |
| Стоимость старта | Низкая | Выше: код тестов, инфраструктура, поддержка |
| Повторный прогон | Часы и дни | Минуты, можно на каждый коммит |
| Слабое место | Усталость на рутине | Проверяет только запрограммированное; UI-тесты хрупкие |
Это не выбор «или-или»: автоматизация берет стабильные повторяющиеся проверки, человек ищет то, что никто не описал в тест-кейсе.
Пирамида тестов
Пирамида тестов — модель распределения автотестов, которую популяризировал Майк Кон. Внизу много быстрых модульных тестов, посередине меньше интеграционных (API, сервисы), наверху немного медленных сквозных (end-to-end) через интерфейс.
Чем выше уровень, тем тест медленнее, дороже в поддержке и тем сложнее понять причину падения. Это ориентир, а не закон: если логика в основном во внешних интеграциях, команды осознанно делают больше интеграционных тестов (форма «трофей» или «ромб»). Антипаттерн — «рожок мороженого»: много ручных и UI-тестов при пустом нижнем слое.
Пример: модульный тест ловит ошибку на границе
Правило бизнеса: доставка бесплатная, если сумма заказа от 3000 рублей включительно, иначе стоит 300 рублей. Техника граничных значений подсказывает проверить значения по обе стороны границы: 2999, 3000 и 3001. Ниже полный рабочий пример на Python 3 со встроенным модулем unittest.
import unittest
FREE_FROM = 3000
PRICE = 300
def shipping_cost(total: int) -> int:
if total < 0:
raise ValueError("сумма не может быть отрицательной")
return 0 if total >= FREE_FROM else PRICE
class ShippingTest(unittest.TestCase):
def test_below_threshold(self):
self.assertEqual(shipping_cost(2999), 300)
def test_exactly_threshold(self):
self.assertEqual(shipping_cost(3000), 0)
def test_above_threshold(self):
self.assertEqual(shipping_cost(3001), 0)
def test_negative_total(self):
with self.assertRaises(ValueError):
shipping_cost(-1)
result = unittest.main(argv=["x"], exit=False, verbosity=0).result
print("провалено:", len(result.failures), "из", result.testsRun)
Запуск выводит OK и итог провалено: 0 из 4. Каждый тест проверяет одно утверждение, поэтому по имени упавшего теста видно, какое правило нарушено.
Теперь та же функция с типичной ошибкой: разработчик написал строгое сравнение >.
import unittest
def shipping_cost(total: int) -> int:
return 0 if total > 3000 else 300 # ошибка: должно быть >=
class ShippingTest(unittest.TestCase):
def test_exactly_threshold(self):
self.assertEqual(shipping_cost(3000), 0)
def test_above_threshold(self):
self.assertEqual(shipping_cost(3001), 0)
result = unittest.main(argv=["x"], exit=False, verbosity=0).result
print("провалено:", len(result.failures), "из", result.testsRun)
Фактический результат: test_exactly_threshold падает с AssertionError: 300 != 0, итог провалено: 1 из 2. Тест с 3001 проходит: проверяя только «явно больше границы», дефект пропустили бы в релиз. Исправление — вернуть >=, как в первом примере.
Граница примера: модульный тест не скажет, правильно ли корзина передает сумму со скидкой, — это задача интеграционного уровня.
Как организован процесс
Типичный цикл выглядит так (в Agile-проектах шаги идут параллельно с разработкой, а не строго друг за другом):
- Анализ требований — что проверять и какие риски; неоднозначность в требованиях — тоже находка.
- Планирование — объем, среды, критерии окончания.
- Тест-дизайн — тест-кейсы или чек-листы по техникам тест-дизайна.
- Выполнение и баг-репорты — шаги воспроизведения, ожидаемый и фактический результат, окружение.
- Отчет — что проверено, что нет, какие риски остаются.
Выводы
- Тестирование сравнивает фактическое поведение с ожидаемым на конечном наборе сценариев и не доказывает отсутствие ошибок.
- Уровни (unit, интеграционное, системное, приемочное) отвечают на вопрос «что проверяем», виды (функциональное и нефункциональное) — «какое свойство».
- Ручное и автоматизированное тестирование дополняют друг друга: автотесты для повторяющихся проверок, человек для исследования и удобства.
- Пирамида тестов — ориентир держать основную массу быстрых тестов внизу, а не жесткое правило.
- Техника граничных значений на простом примере находит дефект, который пропускают «очевидные» проверки.
Где применяется / связь с практикой
Освойте тему на практике
Все описанное — ежедневная работа QA-инженера: разбирать требования, проектировать проверки, заводить баг-репорты и переносить повторяющиеся сценарии в автотесты. Чтобы пройти этот путь системно, с практикой, посмотри программу курса «QA Engineer».
Освойте тему на практике
Попробовать формат можно на бесплатных открытых уроков Otus.
FAQ
Нужен ли тестировщик, если разработчики пишут unit-тесты?
Модульные тесты проверяют код по замыслу автора. Тестировщик смотрит на систему целиком и со стороны пользователя и находит другие проблемы: разрывы между модулями, неоднозначные требования, неудобные сценарии.
Что такое тест-кейс и чем он отличается от чек-листа?
Тест-кейс описывает шаги, входные данные и ожидаемый результат достаточно подробно, чтобы его выполнил другой человек. Чек-лист — короткий список того, что проверить, без детальных шагов; он быстрее в подготовке, но сильнее зависит от опыта исполнителя.
Можно ли добиться 100% покрытия кода тестами и значит ли это отсутствие ошибок?
Покрытие строк в 100% достижимо, но оно показывает только то, что каждая строка хотя бы раз выполнилась. Неверное требование, пропущенный сценарий или ошибка в данных при этом остаются незамеченными.



