Когда у системы много параметров и значений, полный перебор комбинаций становится слишком дорогим. Pairwise testing помогает сократить их число, оставив покрытие всех пар значений между параметрами. На практике это часто даёт хороший баланс между стоимостью и шансом найти дефекты.
Почему pairwise работает
Многие дефекты проявляются из-за взаимодействия двух факторов, а не из-за редкой комбинации сразу пяти или шести параметров. Поэтому покрытие всех пар значений часто ловит значимую часть проблем при гораздо меньшем количестве тестов.
Где применять
- →Формы с несколькими независимыми полями и значениями.
- →Конфигурации устройств, браузеров, ролей, тарифов, стран, языков.
- →API с множеством параметров и режимов вызова.
- →Матрицы совместимости, где полный перебор слишком дорогой.
О чём важно помнить
- →Pairwise не заменяет тесты на критичные бизнес-риски и известные опасные комбинации.
- →Если есть зависимые параметры, их нельзя слепо смешивать как независимые.
- →Некоторые комбинации логически невозможны и должны быть заранее исключены.
- →Критичные сценарии нужно добавлять поверх generated pairwise-набора, а не вместо них.
Практическая best practice
Используй pairwise как инструмент оптимизации, а не как оправдание для минимального покрытия. Сначала выделяй high-risk cases вручную, потом добавляй pairwise для ширины покрытия, а затем усиливай набор негативными и пограничными сценариями.
Pairwise полезен тогда, когда проблема действительно в комбинациях параметров. Для сложной последовательной логики, состояний или расчётов он не является универсальным решением.
Пример: четыре теста покрывают все двенадцать пар
В учебной модели три фактора: браузер Chrome или Firefox, язык интерфейса ru или en, роль viewer или editor. Допустимы все восемь комбинаций. Версии браузеров, ОС, данные и feature flags в упражнении фиксированы; при реальном запуске запишите точные значения. Это модель выбора входных условий, а не готовое веб-приложение.
Полный перебор содержит 2 × 2 × 2 = 8 строк. Для pairwise нужны все пары значений разных факторов: четыре пары браузер–язык, четыре браузер–роль и четыре язык–роль. Следующие четыре строки покрывают эти двенадцать пар.
ID Browser Locale Role
PW1 Chrome ru viewer
PW2 Chrome en editor
PW3 Firefox ru editor
PW4 Firefox en viewerПроверяем покрытие, а не только число тестов
Фактор A Фактор B Покрывается тестом
Browser=Chrome Locale=ru PW1
Browser=Chrome Locale=en PW2
Browser=Firefox Locale=ru PW3
Browser=Firefox Locale=en PW4
Browser=Chrome Role=viewer PW1
Browser=Chrome Role=editor PW2
Browser=Firefox Role=viewer PW4
Browser=Firefox Role=editor PW3
Locale=ru Role=viewer PW1
Locale=ru Role=editor PW3
Locale=en Role=viewer PW4
Locale=en Role=editor PW2В каждой строке указаны обязательная пара и тест, где она встречается. Все пары покрыты по одному разу. Четыре теста — минимум именно для этой независимой двоичной модели: четыре пары браузер–язык уже требуют хотя бы четырёх строк. Этот вывод нельзя переносить на произвольные pairwise-наборы.
Проверка матрицы на Python 3
Сохраните код как pairwise_coverage.py и запустите python3 pairwise_coverage.py. Нужна только стандартная библиотека; сетевых запросов нет. Ожидаемый вывод: Pairs: 12/12; triples: 4/8.
from itertools import product, combinations
levels = [("Chrome", "Firefox"), ("ru", "en"), ("viewer", "editor")]
rows = [
("Chrome", "ru", "viewer"),
("Chrome", "en", "editor"),
("Firefox", "ru", "editor"),
("Firefox", "en", "viewer"),
]
required = {(i, a, j, b) for i, j in combinations(range(3), 2)
for a, b in product(levels[i], levels[j])}
covered = {(i, row[i], j, row[j]) for row in rows
for i, j in combinations(range(3), 2)}
assert all(row in set(product(*levels)) for row in rows)
assert covered == required
assert ("Chrome", "en", "viewer") not in rows
print(f"Pairs: {len(covered)}/{len(required)}; triples: {len(set(rows))}/8")Для каждой конфигурации нужен ожидаемый результат
Для вымышленного редактора документов заранее задайте правило: viewer читает документ, но попытка редактирования не меняет сохранённый текст; editor сохраняет допустимое изменение ровно один раз. В каждой строке матрицы проверьте язык, результат для роли и сохранённые данные. Покрытие пар само по себе этих результатов не доказывает: без проверок недостаточно просто открыть конфигурацию.
Матрица пропустит дефект, возникающий только при Chrome + en + viewer: такой тройки нет, хотя все её пары встречаются в других строках. Добавьте комбинацию, если это оправдывают риск или прошлый дефект. Последовательности, границы, права и производительность требуют отдельного тест-дизайна. Из «12/12 пар» не следует процент обнаруженных ошибок.
Если комбинация невозможна по правилам продукта, сначала получите допустимые полные комбинации, из них выведите достижимые пары, затем заново постройте и проверьте сокращённый набор. Простое удаление строки может убрать другие допустимые пары. Упражнение: удалите PW4; непокрытыми станут Firefox–en, Firefox–viewer и en–viewer. Восстановите покрытие допустимой строкой, а не уменьшайте знаменатель без объяснения.
Продолжить изучение
Выбор дополнительных тестов по рискам