Тестирование ПО Принципы и терминология: верификация, валидация, дефект, качество
0%

Принципы и терминология: верификация, валидация, дефект, качество

Принципы и терминология: верификация, валидация, дефект, качество

Есть соблазн пролистать статью про термины: «ну баг и баг, все понимают». Проблема в том, что не понимают — и расхождение стоит денег. Типичный диалог на ретро:

— Мы всё протестировали, качество высокое. — А почему клиент вернул релиз? — Так это не баг, это требование такое было. — Требование было неправильное. — Ну это не к нам.

Здесь в четырёх репликах перепутаны верификация и валидация, дефект и несоответствие требованию, качество продукта и качество в использовании. Пока команда не различает эти вещи словами, она не различает их и действиями: не проверяет требования, не заводит дефекты на спецификацию, меряет качество числом закрытых тикетов.

Эта статья — фундамент курса. Дальше будут техники (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

Эту цепочку в академической литературе называют моделью RIP (Reachability, Infection, Propagation) — она подробно разобрана в Ammann & Offutt, Introduction to Software Testing. Чтобы тест нашёл дефект, должны выполниться три условия:

  1. Reachability — тест должен дойти до дефектного кода;
  2. Infection — состояние программы после исполнения должно стать неверным;
  3. 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% и провалить валидацию полностью: идеально реализованная неправильная идея.

Это 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).

Модель качества продукта ISO/IEC 25010

Три вещи, ради которых эту модель стоит держать в голове:

  1. Качество — вектор, а не число. «Качественный продукт» — бессмысленная фраза, пока не сказано, по каким осям. Банковский бэкенд оптимизирует надёжность и безопасность; прототип для инвестора — функциональную полноту и скорость выхода; встроенное ПО кардиостимулятора — safety, ценой всего остального.
  2. Тестируемость — часть сопровождаемости. То есть свойство продукта, а не тестировщика. Если систему невозможно проверить, это дефект архитектуры. Требовать тестируемости — законное инженерное требование, а не каприз QA.
  3. Качество в использовании — отдельная модель. Продукт может быть безупречен по всем девяти характеристикам и всё равно не решать задачу. Это ровно граница между верификацией и валидацией, только выраженная в терминах стандарта.

Ссылки на первоисточники: ISO/IEC 25010, ISTQB Glossary (бесплатный, поддерживает русский), IEEE 1044-2009.

QA, 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 — инструмент управления тестированием (конкретный цикл).

Типичные ошибки на старте

  1. Заводить дефект без ожидаемого результата. «Кнопка работает неправильно» — это не репорт. Ожидание должно ссылаться на источник: спека, аналог, здравый смысл (последнее нужно явно помечать).
  2. Путать «не воспроизводится» с «не дефект». Невоспроизводимый баг — это дефект с недостаточно исследованными условиями. Часто он самый опасный: race condition, зависимость от таймзоны, состояние кэша.
  3. Считать метрики целью. Число написанных кейсов, процент покрытия, количество найденных багов — все они моментально ломаются при попытке оптимизировать (закон Гудхарта). Тестировщик, которого меряют числом багов, начинает заводить косметику.
  4. Тестировать только позитивные сценарии. Самая частая слепота новичков и разработчиков: пишем тест на happy path и считаем функцию покрытой.
  5. Верить зелёному прогону без проверки самих тестов. Простой способ проверить: сломайте код намеренно и убедитесь, что тест краснеет. Это ручное мутационное тестирование за 30 секунд.
  6. Игнорировать статическое тестирование. Ревью требований — самая дешёвая проверка в арсенале, и её почти никто не делает системно.

Мини-итог

  • Ошибка → дефект → сбой — три разные сущности. Мы наблюдаем сбои, ищем дефекты, предотвращаем ошибки.
  • Чтобы тест нашёл дефект, нужны все три условия 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 OpportunitiesACM Computing Surveys.
  • Martin Fowler. Test Coveragemartinfowler.com/bliki/TestCoverage.html.

Что дальше

Мы разобрали, чем оперирует тестировщик. Следующий шаг — как из бесконечного пространства возможных проверок выбрать те несколько десятков, которые действительно найдут дефекты: классы эквивалентности, граничные значения, попарные комбинации и таблицы решений.

Тест-дизайн: классы эквивалентности, границы, попарное тестирование, таблицы решений

Нашли неточность? Выделите фрагмент текста — рядом появится жучок.

Нужен разбор именно вашей ситуации?

Статья описывает общий случай. Если у вас частный — можно разобрать его отдельно, платно. А если не хватает целого материала, предложите тему: её оплачивают вскладчину, и она выходит открытой для всех.

Доска запросов