Принципы и терминология: верификация, валидация, дефект, качество
Есть соблазн пролистать статью про термины: «ну баг и баг, все понимают». Проблема в том, что не понимают — и расхождение стоит денег. Типичный диалог на ретро:
— Мы всё протестировали, качество высокое. — А почему клиент вернул релиз? — Так это не баг, это требование такое было. — Требование было неправильное. — Ну это не к нам.
Здесь в четырёх репликах перепутаны верификация и валидация, дефект и несоответствие требованию, качество продукта и качество в использовании. Пока команда не различает эти вещи словами, она не различает их и действиями: не проверяет требования, не заводит дефекты на спецификацию, меряет качество числом закрытых тикетов.
Эта статья — фундамент курса. Дальше будут техники (https://courses.digitable.life/post/testing/02-test-design/), документация (https://courses.digitable.life/post/testing/03-documentation/), инструменты. Здесь — понятийная сетка, на которую всё это ложится, плюс честный разбор, где красивые определения из учебников ломаются о практику.
Ошибка, дефект, сбой: три разные вещи
Самая полезная различающая триада. Она зафиксирована в IEEE 1044 и в глоссарии ISTQB, но важна не как формальность, а как способ думать.
- Error / Mistake (ошибка) — действие человека, породившее неправильный результат. Разработчик неверно понял требование, перепутал
<и<=, забыл про часовой пояс. Ошибка живёт в голове и в моменте. - Defect / Fault / Bug (дефект) — материальный след ошибки в артефакте: в коде, в конфиге, в требовании, в схеме БД, в тексте на кнопке. Дефект существует в репозитории, даже если его никто не наблюдал.
- Failure (сбой, отказ) — наблюдаемое отклонение поведения системы от ожидаемого при исполнении. Сбой существует во времени выполнения.
Важнейший вывод: дефект не обязан приводить к сбою, и один дефект может порождать десятки разных сбоев. Мы находим дефекты через сбои — но между ними стоит цепочка условий.
Эту цепочку в академической литературе называют моделью RIP (Reachability, Infection, Propagation) — она подробно разобрана в Ammann & Offutt, Introduction to Software Testing. Чтобы тест нашёл дефект, должны выполниться три условия:
- Reachability — тест должен дойти до дефектного кода;
- Infection — состояние программы после исполнения должно стать неверным;
- Propagation — искажение должно дойти до наблюдаемого выхода, и проверка должна его заметить.
Разберём на коде — это самый быстрый способ понять, почему «100% покрытия» ничего не гарантирует.
def apply_discount(price: float, percent: int) -> float:
"""Возвращает цену со скидкой. Дефект: нет верхней границы процента."""
if percent < 0: # проверяем только нижнюю границу
percent = 0
return price * (100 - percent) / 100
# Тест 1: строка с дефектом выполняется (Reachability есть),
# но состояние корректно — Infection нет. Тест зелёный.
def test_normal_discount():
assert apply_discount(100.0, 10) == 90.0
# Тест 2: Reachability + Infection (percent=150 даёт -50.0),
# но мы проверяем только тип — Propagation до проверки не доходит. Тест зелёный.
def test_returns_float():
assert isinstance(apply_discount(100.0, 150), float)
# Тест 3: все три условия выполнены — сбой наблюдаем.
def test_discount_above_100_is_clamped():
assert apply_discount(100.0, 150) == 0.0 # падает: получаем -50.0
Покрытие строк во всех трёх случаях одинаковое — 100%. Дефект находит только третий тест. Отсюда правило, к которому мы вернёмся в https://courses.digitable.life/post/testing/13-tests-in-ci/: покрытие измеряет Reachability и ничего больше. Это метрика достижимости, а не метрика качества проверок. Мутационное тестирование, наоборот, бьёт прямо в Infection + Propagation — потому и честнее.
Разработчику: триада объясняет, почему «у меня локально работает» — не аргумент. Отсутствие сбоя не означает отсутствия дефекта, оно означает, что вы не подобрали данные, вызывающие Infection.
Тестировщику: триада объясняет, почему баг-репорт «иногда падает» бесполезен. Ваша работа — не только зафиксировать Failure, но и сузить условия до воспроизводимого набора данных, приближающего разработчика к Fault.
Верификация и валидация: два разных вопроса
Классическая формулировка принадлежит Барри Боэму:
- Верификация — Are we building the product right? Соответствует ли то, что мы сделали, тому, что мы записали: спецификации, требованиям, дизайну, стандарту, контракту API.
- Валидация — Are we building the right product? Решает ли то, что мы сделали, реальную задачу реального пользователя.
Разница не академическая. Верификация всегда идёт относительно документа, валидация — относительно потребности. Система может пройти верификацию на 100% и провалить валидацию полностью: идеально реализованная неправильная идея.
пользователя"] --> B["Требования
к системе"] B --> C["Архитектура
и дизайн"] C --> D["Код"] end subgraph V2["Правая ветвь: проверка"] E["Модульные
тесты"] --> F["Интеграционные
тесты"] F --> G["Системные
тесты"] G --> H["Приёмочные
тесты"] end D --> E C -. "верификация дизайна" .-> F B -. "верификация требований" .-> G A -. "ВАЛИДАЦИЯ" .-> H
Это V-модель — не как процесс разработки (в таком виде она давно мертва), а как карта соответствий: каждый уровень проверки отвечает своему уровню спецификации. Ценность идеи сохраняется и в Agile: приёмочный тест всё равно проверяет потребность, а модульный — реализацию.
Практические следствия:
| Приём | Что это | Верификация или валидация |
|---|---|---|
| Код-ревью | Сверка кода со стандартом и дизайном | Верификация |
| Статический анализ, линтеры | Сверка кода с правилами | Верификация |
| Модульные и интеграционные тесты | Сверка поведения с ожидаемым по спеке | Верификация |
| Контрактные тесты | Сверка API с контрактом | Верификация |
| Ревью требований с аналитиком | Сверка требований между собой | Верификация требований |
| Демо заказчику, UAT | Проверка, решена ли задача | Валидация |
| A/B-тест, пользовательские интервью | Проверка гипотезы о ценности | Валидация |
| Бета-тест, канареечный релиз | Проверка на реальном трафике | Валидация |
Обратите внимание: большая часть того, что команды называют «тестированием», — это верификация. Валидация делается редко, поздно и часто вообще не тестировщиками, а продактами. Отсюда системный перекос: команда уверена, что «протестировала», а продукт не нужен.
Где расходятся взгляды. Разработчик обычно считает валидацию не своей зоной («мне дали задачу — я сделал»). Тестировщик, наоборот, часто оказывается единственным человеком, который читает требование целиком и замечает, что оно противоречит другому требованию или здравому смыслу. Это и есть главная недооценённая ценность QA: тестирование требований до написания кода дешевле тестирования кода. Обнаруженное на ревью требований противоречие стоит часа обсуждения; то же противоречие, найденное в проде, стоит инцидента.
Что такое качество (и почему определение важнее, чем кажется)
Три классических определения, между которыми стоит выбирать сознательно:
- Филип Кросби: качество — соответствие требованиям (conformance to requirements). Удобно измерять, но делает бессмысленным вопрос «а требования хорошие?».
- Джозеф Джуран: качество — пригодность к использованию (fitness for use). Ближе к реальности, но измерять сложно.
- Джеральд Вайнберг: «Quality is value to some person» — качество есть ценность для кого-то конкретного. Самое честное: оно требует назвать этого человека. Джеймс Бах позже добавил уточнение: «…at some time who matters» — ценность для того, чьё мнение влияет на судьбу продукта.
Определение Вайнберга — рабочий инструмент, а не философия. Когда на груминге спорят «это баг или не баг», правильный вопрос: для кого это потеря ценности и насколько эта потеря значима? Ответ обычно закрывает спор за минуту.
Индустриальный стандарт раскладывает качество на измеримые характеристики — ISO/IEC 25010 (редакция 2023 года, часть серии SQuaRE).
Три вещи, ради которых эту модель стоит держать в голове:
- Качество — вектор, а не число. «Качественный продукт» — бессмысленная фраза, пока не сказано, по каким осям. Банковский бэкенд оптимизирует надёжность и безопасность; прототип для инвестора — функциональную полноту и скорость выхода; встроенное ПО кардиостимулятора — safety, ценой всего остального.
- Тестируемость — часть сопровождаемости. То есть свойство продукта, а не тестировщика. Если систему невозможно проверить, это дефект архитектуры. Требовать тестируемости — законное инженерное требование, а не каприз QA.
- Качество в использовании — отдельная модель. Продукт может быть безупречен по всем девяти характеристикам и всё равно не решать задачу. Это ровно граница между верификацией и валидацией, только выраженная в терминах стандарта.
Ссылки на первоисточники: ISO/IEC 25010, ISTQB Glossary (бесплатный, поддерживает русский), IEEE 1044-2009.
QA, QC, тестирование, отладка — четыре разных занятия
Слова часто используют как синонимы, а это разные виды работ с разными владельцами.
обеспечение качества"] QC["Quality Control
контроль качества"] T["Testing
тестирование"] D["Debugging
отладка"] QA -->|"процесс: как не производить дефекты"| QC QC -->|"продукт: проверить, что произвели"| T T -->|"нашли сбой"| D D -->|"нашли и починили дефект"| T QA -.->|"стандарты кодирования, DoD,
ревью, обучение, ретро"| QA QC -.->|"тесты, инспекции,
аудит артефактов"| QC
- QA (обеспечение качества) — работа с процессом: как организовать разработку, чтобы дефектов возникало меньше. Definition of Done, обязательное ревью, стандарты, шаблоны, разбор инцидентов. Превентивно.
- QC (контроль качества) — работа с продуктом: проверить готовый артефакт и найти в нём дефекты. Реактивно.
- Тестирование — конкретная техника QC: исполнение системы (динамическое) или анализ артефакта (статическое) с целью обнаружить несоответствие.
- Отладка — поиск и устранение причины сбоя. Это работа разработчика, а не тестировщика: тестировщик находит Failure, разработчик — Fault.
Практический смысл различения: должность «QA-инженер», занимающаяся исключительно прогоном тест-кейсов, на самом деле QC. Это не унизительно, но объясняет, почему в таких командах количество дефектов не падает год за годом — никто не работает с процессом.
Семь принципов тестирования — и что с ними не так
Канонический список из ISTQB Foundation Level. Он полезен, но каждый пункт стоит читать вместе с оговоркой.
1. Тестирование показывает наличие дефектов, а не их отсутствие. Дейкстра: «Program testing can be used to show the presence of bugs, but never to show their absence». Тестирование — эмпирическая, а не доказательная деятельность. Оговорка: формальная верификация и типы всё-таки доказывают отсутствие целых классов дефектов. Строгая типизация, Option вместо null, тотальные функции — это способ сделать дефект невыразимым, а не ловить его тестом. См. https://courses.digitable.life/post/principles/06-testing-principles/.
2. Исчерпывающее тестирование невозможно. Функция от двух 32-битных чисел имеет порядка 1.8×10^19 комбинаций входов. Даже тривиальная форма из 10 полей даёт комбинаторный взрыв. Отсюда вся дисциплина тест-дизайна — выбирать разумное подмножество. Оговорка: «невозможно» относится к перебору; фаззинг и property-based тестирование покрывают гигантские пространства входов автоматически и находят то, что человек не придумает.
3. Раннее тестирование экономит время и деньги (shift left). Дефект, найденный на этапе требований, дешевле дефекта в проде на порядки. Оговорка: знаменитая «кривая Боэма» с ростом стоимости в 100 раз происходит из данных 1970-х по waterfall-проектам и многократно критиковалась (см. разбор Лорана Боссавита, The Leprechauns of Software Engineering). Направление верное, конкретные множители — фольклор. Не цитируйте «×100» как факт.
4. Кластеризация дефектов. Небольшое число модулей содержит большинство дефектов — принцип Парето в действии. Практический вывод: история багов — лучший источник для приоритизации тестов. Модуль, в котором за квартал нашли 12 дефектов, почти наверняка даст тринадцатый.
5. Парадокс пестицида. Одни и те же тесты со временем перестают находить новое — как насекомые вырабатывают устойчивость к пестициду. Регрессионный набор нужно обновлять, добавлять новые техники, менять данные. Оговорка: это не значит, что старые тесты бесполезны — они переходят из режима «поиск дефектов» в режим «защита от регрессий». Две разные функции с разной ценностью.
6. Тестирование зависит от контекста. Медицинский софт, банковский процессинг, игра и внутренний дашборд тестируются принципиально по-разному. Нет универсально правильной стратегии — есть подходящая под риски.
7. Заблуждение об отсутствии ошибок. Система без известных дефектов может быть непригодной. Это принцип 1 плюс принцип «валидация ≠ верификация», сформулированный для менеджмента.
К этим семи стоит добавить два принципа, которых в ISTQB нет, но которые определяют реальную работу:
8. У тестирования есть цена, и она конкурирует с ценностью. Каждый тест стоит: написать, прогонять, поддерживать при рефакторинге, чинить когда флакует. Тест, который за год ни разу не поймал дефект и трижды упал ложно, — отрицательная ценность. Решение «что тестировать» — экономическое, а не моральное. Подробно в https://courses.digitable.life/post/testing/12-automation-strategy/.
9. Тесты — тоже код, и в них тоже есть дефекты. Зелёный тест может быть зелёным потому, что ничего не проверяет (см. пример с isinstance выше). Тестовый код требует ревью наравне с продакшн-кодом.
Проблема оракула: как вы вообще знаете, что результат верный
Самое недооценённое понятие в тестировании. Тестовый оракул — механизм, определяющий, корректен ли наблюдаемый результат. Без оракула нет теста: есть запуск.
Проблема в том, что точный оракул часто недоступен. Как проверить корректность результата поисковой выдачи? Отрендеренного PDF? Рекомендательной модели? Расчёта страховой премии по 200-страничной методике?
Виды оракулов, от самого дорогого к самому дешёвому:
оракулы)) Точный Захардкоженное ожидание Эталонный файл Формула из спецификации Эвристический Свойства инварианты Метаморфические отношения Проверка правдоподобия Сравнительный Старая версия системы Альтернативная реализация Другой язык или библиотека Человек Исследовательское тестирование Приёмка заказчиком Отсутствует Только на падения и таймауты Санитайзеры и ассерты рантайма
Пример свойственного (property-based) оракула: мы не знаем правильный ответ для конкретного входа, но знаем инвариант, который должен выполняться для всех входов.
from hypothesis import given, strategies as st
from billing import apply_discount
@given(
price=st.floats(min_value=0, max_value=1_000_000, allow_nan=False),
percent=st.integers(min_value=-1000, max_value=1000),
)
def test_discount_invariants(price: float, percent: int) -> None:
result = apply_discount(price, percent)
# Инвариант 1: цена со скидкой не может быть отрицательной.
assert result >= 0
# Инвариант 2: скидка не может увеличить цену.
assert result <= price
# Инвариант 3: монотонность — больший процент даёт не большую цену.
if percent < 1000:
assert apply_discount(price, percent + 1) <= result + 1e-9
Мы нигде не написали «для 100 и 10 должно быть 90», но эти три инварианта поймают дефект с percent > 100 немедленно — hypothesis подберёт контрпример и сократит его до минимального.
Пример метаморфического оракула на TypeScript — проверяем не значение, а отношение между двумя запусками:
import { describe, expect, it } from "vitest";
import { search } from "./search";
describe("метаморфические отношения поиска", () => {
it("уточнение запроса не расширяет выдачу", async () => {
const broad = await search("ноутбук");
const narrow = await search("ноутбук 16 гб");
// Не знаем «правильную» выдачу, но знаем: уточнение сужает.
expect(narrow.total).toBeLessThanOrEqual(broad.total);
});
it("порядок слов не должен менять множество результатов", async () => {
const a = await search("красный шарф");
const b = await search("шарф красный");
expect(new Set(b.ids)).toEqual(new Set(a.ids));
});
});
Метаморфическое тестирование — рабочая техника для систем без точного оракула: ML-моделей, поиска, компиляторов, графики. Основополагающая работа: Chen et al., «Metamorphic Testing: A Review of Challenges and Opportunities».
Практический совет. Когда вы не можете сформулировать оракул для проверки — это сигнал. Либо требование сформулировано слишком размыто (тогда идите к аналитику: вы только что нашли дефект в требованиях), либо задача действительно требует эвристики. Фраза «работает корректно» в тест-кейсе означает, что оракула нет.
Рабочий словарь: уровни, типы, техники
Три ортогональные оси, которые постоянно путают. Уровень отвечает на вопрос «что за объект тестируем», тип — «какое свойство проверяем», техника — «как выбираем тесты».
Уровни тестирования (детализация — статьи 05–07 курса):
| Уровень | Объект | Кто обычно делает | Кто владеет окружением |
|---|---|---|---|
| Модульный (unit) | Функция, класс, модуль в изоляции | Разработчик | Никакого — всё в памяти |
| Интеграционный | Взаимодействие модулей, модуль + БД/брокер | Разработчик, реже QA | Testcontainers, docker-compose |
| Системный | Собранная система целиком | QA | Тестовый стенд |
| Приёмочный (UAT) | Система с точки зрения бизнеса | Заказчик, аналитик, QA | Пре-прод |
Типы тестирования — соответствуют характеристикам ISO 25010:
- функциональные — что система делает;
- нефункциональные — как она это делает: производительность (https://courses.digitable.life/post/testing/09-performance-testing/), безопасность (https://courses.digitable.life/post/testing/10-security-testing/), совместимость и доступность (https://courses.digitable.life/post/testing/11-mobile-and-compatibility/), удобство;
- структурные — проверка внутренней структуры, покрытие путей и ветвей;
- связанные с изменениями — подтверждающее (confirmation, он же re-test: проверяем, что конкретный баг починен) и регрессионное (проверяем, что починка ничего не сломала). Это разные вещи; в баг-трекере это разные переходы состояний.
Техники — по уровню доступа к внутренностям:
- Чёрный ящик — тесты выводятся из спецификации, без знания кода. Плюс: находят пропущенную функциональность, не наследуют заблуждения разработчика. Минус: не видят ветвей, о которых спека молчит.
- Белый ящик — тесты выводятся из структуры кода. Плюс: систематическое покрытие ветвей. Минус: не находят отсутствующий код — если фича не реализована, покрывать нечего.
- Серый ящик — знаем архитектуру и схему БД, но тестируем через внешний интерфейс. Реальный режим большинства сильных тестировщиков.
И ещё одна пара, которую путают почти все:
- Статическое тестирование — анализ артефакта без исполнения: ревью, инспекции по Фагану, линтеры, статический анализ, проверка типов. Дешевле динамического и находит другие классы дефектов — прежде всего дефекты требований и дизайна.
- Динамическое тестирование — исполнение системы.
Позитивное тестирование проверяет, что система делает то, что должна, на валидных данных. Негативное — что она корректно отказывает на невалидных. Соотношение в зрелом наборе обычно в пользу негативного: правильных сценариев мало, способов сломать — много.
Жизненный цикл дефекта
Термины про баг-трекер стоит знать точно — это язык ежедневной коммуникации.
Два состояния заслуживают внимания. Reopened — метрика здоровья процесса: высокая доля переоткрытых дефектов означает, что разработчик чинит симптом, а не причину, либо не воспроизводит баг перед фиксом. Deferred — самое опасное: это официальное решение жить с дефектом. Оно должно приниматься осознанно и человеком с полномочиями, а не молча.
Severity и Priority — не одно и то же
Классическая путаница на собеседованиях и в реальных спорах.
- Severity (серьёзность) — объективная характеристика технического воздействия: насколько сильно сломано. Определяет тестировщик.
- Priority (приоритет) — решение бизнеса о порядке починки. Определяет продакт или лид.
Все четыре комбинации реальны:
| Высокий приоритет | Низкий приоритет | |
|---|---|---|
| Высокая severity | Падает оплата в чекауте. Чиним немедленно. | Полный краш в модуле, которым пользуется один клиент раз в год через месяц. |
| Низкая severity | Опечатка в названии компании на главной странице перед пресс-конференцией. | Съехавший на 2px отступ в футере админки. |
Правый верхний угол — самая недооценённая клетка: косметический по технике дефект с огромной бизнес-ценой. Если тестировщик выставляет приоритет по severity, он теряет доверие бизнеса, а если ставит severity по приоритету — теряет технический смысл поля.
Минимальный полезный баг-репорт
Формат подробно разбирается в https://courses.digitable.life/post/testing/03-documentation/, но базовый скелет — часть терминологического минимума:
Заголовок: Скидка > 100% даёт отрицательную сумму заказа в корзине
Окружение: stage, build 2026.7.14-rc3, Chrome 138, аккаунт b2b_test_01
Шаги воспроизведения:
1. Войти под b2b_test_01.
2. Добавить в корзину товар «Кресло Nord» (12 000 ₽).
3. Применить промокод SUPER150 (номинал 150%).
4. Открыть страницу корзины.
Фактический результат: итого = −6 000 ₽; кнопка «Оплатить» активна.
Ожидаемый результат: итого = 0 ₽ (по разделу 4.2 спецификации биллинга),
либо промокод отклоняется с ошибкой.
Severity: Critical (возможна отрицательная транзакция)
Приоритет: предлагаю Highest — воспроизводится на всех промокодах > 100%
Воспроизводимость: 5/5
Приложения: har-файл, скриншот, лог billing-service (trace_id 9f2c...)
Ключевое здесь — разделение фактического и ожидаемого результата с указанием источника ожидания. Ссылка на пункт спецификации превращает спор «баг или фича» в проверяемое утверждение. Если источника ожидания нет — вы нашли дефект требований, и репорт нужно заводить именно так.
Стоимость и риск: как решать, что тестировать
Полноценный риск-ориентированный подход — тема статьи https://courses.digitable.life/post/testing/12-automation-strategy/, но базовая рамка относится к терминологии.
Риск в тестировании — сочетание двух независимых оценок: вероятности того, что дефект есть и проявится, и ущерба, если он проявится. Тестирование не устраняет риск, оно снижает неопределённость относительно него. Это важная переформулировка: тест не делает продукт лучше, он делает наше знание о продукте точнее. Улучшает продукт исправление дефекта, а не его обнаружение.
Оценка вероятности не берётся с потолка. Хорошие сигналы: частота изменений модуля (git log по файлу), сложность кода, история дефектов, число разработчиков, трогавших модуль, свежесть кода, наличие внешних интеграций.
# Быстрая эвристика: топ-15 самых изменяемых файлов за год.
# Пересечение с историей багов даёт кандидатов на глубокое тестирование.
git log --since="1 year ago" --name-only --pretty=format: \
| grep -E '\.(py|ts|go)$' \
| sort | uniq -c | sort -rn | head -15
Где расходятся взгляды. Разработчик оценивает риск через сложность кода: «здесь запутанная логика, надо покрыть». Тестировщик — через ущерб для пользователя: «здесь простой код, но если он сломается, мы потеряем деньги клиентов». Обе оценки нужны, и они не совпадают. Простейший модуль перевода денег может быть тривиальным по коду и катастрофическим по последствиям.
Мини-словарь: что часто путают
| Часто говорят | На самом деле | Почему это важно |
|---|---|---|
| «Баг» про всё подряд | Failure — то, что наблюдали; Defect — причина в коде | Иначе баг-репорт описывает симптом без данных для локализации |
| «Тест упал — значит баг» | Мог упасть тест: устаревшее ожидание, флак, проблема стенда | Ложные баги подрывают доверие к автотестам |
| «Покрытие 85% — качество высокое» | Покрытие = Reachability, не Infection и не Propagation | Метрика превращается в самообман |
| «Регресс» = «прогнать все тесты» | Регресс — проверка, что изменение не сломало работавшее | Иначе регресс раздувается и перестаёт помещаться в релизный цикл |
| «Смоук» = «быстрые тесты» | Смоук — проверка, что сборку вообще имеет смысл тестировать | Критерий отбора — не скорость, а «сломано ли принципиально» |
| «QA» = «человек, который кликает» | QA — работа с процессом; клики — QC | Иначе процесс никто не улучшает |
| «Автотест заменит ручное» | Автотест повторяет известную проверку; исследовательское находит неизвестное | Разные функции, друг друга не заменяют |
| «Приёмочные критерии» = «тест-кейсы» | Критерии — условия принятия истории; кейсы — как их проверить | Смешение приводит к историям, которые невозможно закрыть |
| «Верификация» ≈ «валидация» | Разные вопросы: соответствие спеке vs решение задачи | Продукт проходит одно и проваливает другое |
| «Severity» ≈ «Priority» | Техническое воздействие vs бизнес-очерёдность | Потеря доверия бизнеса или потеря технического смысла |
Отдельно про entry/exit criteria и Definition of Done — их путают постоянно:
- Entry criteria — условия, при которых имеет смысл начинать тестирование: сборка задеплоена, смоук зелёный, тестовые данные готовы, известны изменения. Без них команда тратит день на тестирование сломанной сборки.
- Exit criteria — условия завершения: все запланированные кейсы выполнены, нет открытых блокеров, известные дефекты приняты явным решением. Формулировка «багов нет» в качестве exit criteria недостижима — см. принцип 1.
- Definition of Done — командное соглашение о готовности любой задачи (код влит, тесты написаны, документация обновлена, ревью пройдено). DoD — инструмент QA (процесс), exit criteria — инструмент управления тестированием (конкретный цикл).
Типичные ошибки на старте
- Заводить дефект без ожидаемого результата. «Кнопка работает неправильно» — это не репорт. Ожидание должно ссылаться на источник: спека, аналог, здравый смысл (последнее нужно явно помечать).
- Путать «не воспроизводится» с «не дефект». Невоспроизводимый баг — это дефект с недостаточно исследованными условиями. Часто он самый опасный: race condition, зависимость от таймзоны, состояние кэша.
- Считать метрики целью. Число написанных кейсов, процент покрытия, количество найденных багов — все они моментально ломаются при попытке оптимизировать (закон Гудхарта). Тестировщик, которого меряют числом багов, начинает заводить косметику.
- Тестировать только позитивные сценарии. Самая частая слепота новичков и разработчиков: пишем тест на happy path и считаем функцию покрытой.
- Верить зелёному прогону без проверки самих тестов. Простой способ проверить: сломайте код намеренно и убедитесь, что тест краснеет. Это ручное мутационное тестирование за 30 секунд.
- Игнорировать статическое тестирование. Ревью требований — самая дешёвая проверка в арсенале, и её почти никто не делает системно.
Мини-итог
- Ошибка → дефект → сбой — три разные сущности. Мы наблюдаем сбои, ищем дефекты, предотвращаем ошибки.
- Чтобы тест нашёл дефект, нужны все три условия RIP. Покрытие кода отвечает только за первое — отсюда его репутация метрики-самообмана.
- Верификация сверяет продукт со спецификацией, валидация — с потребностью. Большая часть «тестирования» в командах — верификация; из-за этого продукт бывает правильно сделан и не нужен.
- Качество — вектор (ISO/IEC 25010) и всегда чья-то ценность (Вайнберг). Спор «баг или не баг» решается вопросом «для кого потеря и насколько значимая».
- Оракул — то, что отличает тест от запуска. Нет оракула — нет теста; невозможность сформулировать оракул есть дефект требований.
- Семь принципов ISTQB полезны, но два из них (стоимость раннего дефекта, невозможность исчерпывающего тестирования) требуют оговорок, а к списку стоит добавить стоимость тестирования и тот факт, что тесты — тоже код с дефектами.
- Severity ≠ Priority, QA ≠ QC, регресс ≠ прогон всего. Точность языка — не педантизм, а способ не терять деньги на недопонимании.
Источники
- Ammann P., Offutt J. Introduction to Software Testing, 2nd ed. — модель RIP, критерии покрытия, формальная база. cs.gmu.edu/~offutt/softwaretest/
- Kaner C., Bach J., Pettichord B. Lessons Learned in Software Testing — контекстно-ориентированная школа, разбор мифов. kaner.com
- Weinberg G. Quality Software Management, Vol. 1: Systems Thinking — определение качества как ценности.
- Bossavit L. The Leprechauns of Software Engineering — критический разбор «кривой стоимости дефекта». leanpub.com/leprechauns
- ISTQB Certified Tester Foundation Level Syllabus — источник семи принципов и канонической терминологии.
- ISTQB Glossary — нормативные определения, доступен на русском.
- ISO/IEC 25010:2023 — модель качества продукта.
- Hypothesis documentation — property-based тестирование на Python.
- Chen T. Y. et al. Metamorphic Testing: A Review of Challenges and Opportunities — ACM Computing Surveys.
- Martin Fowler. Test Coverage — martinfowler.com/bliki/TestCoverage.html.
Что дальше
Мы разобрали, чем оперирует тестировщик. Следующий шаг — как из бесконечного пространства возможных проверок выбрать те несколько десятков, которые действительно найдут дефекты: классы эквивалентности, граничные значения, попарные комбинации и таблицы решений.
Тест-дизайн: классы эквивалентности, границы, попарное тестирование, таблицы решений