Комбинаторная генерация наборов тестов
Updated Jul 2026
Проблема комбинаторного взрыва
Когда у вас есть несколько входных параметров, исчерпывающее тестирование непрактично. Форма регистрации пользователя с 5 параметрами, каждый из которых имеет 3-5 значений, порождает сотни или тысячи комбинаций. Тестирование всех из них дорого, и большинство комбинаций не выявляют уникальных ошибок.
Комбинаторное проектирование тестов решает эту проблему, выбирая подмножество комбинаций, которое гарантирует, что каждая пара (или n-кортеж) значений параметров появляется хотя бы в одном тестовом сценарии. Это радикально сокращает количество тестов при сохранении высокого уровня обнаружения дефектов.
Попарное (2-Way) тестирование
Попарное тестирование гарантирует, что каждая комбинация любых двух параметров появляется хотя бы в одном тестовом сценарии. Исследования последовательно показывают, что большинство программных дефектов вызывается взаимодействием не более чем двух параметров (приблизительно 70-90% дефектов, по данным исследований NIST).
Промпт для попарной генерации
Generate a pairwise combinatorial test suite for a user registration form with
these parameters:
- Browser: Chrome, Firefox, Safari, Edge
- OS: Windows, macOS, Linux
- Language: English, Spanish, Japanese
- Account type: Free, Pro, Enterprise
- Auth method: Email/password, Google SSO, SAML
Requirements:
- Every pair of parameter values must appear in at least one test case
- Minimize total number of test cases
- Output as a numbered table
Пример вывода
Сильная LLM создаёт близкий к оптимальному попарный набор из приблизительно 16-20 тестовых конфигураций вместо полных 4 x 3 x 3 x 3 x 3 = 324 комбинаций:
| # | Browser | OS | Language | Account | Auth |
|---|---|---|---|---|---|
| 1 | Chrome | Windows | English | Free | Email/password |
| 2 | Chrome | macOS | Spanish | Pro | Google SSO |
| 3 | Chrome | Linux | Japanese | Enterprise | SAML |
| 4 | Firefox | Windows | Spanish | Enterprise | SAML |
| 5 | Firefox | macOS | Japanese | Free | Email/password |
| 6 | Firefox | Linux | English | Pro | Google SSO |
| 7 | Safari | Windows | Japanese | Pro | Email/password |
| 8 | Safari | macOS | English | Enterprise | SAML |
| 9 | Safari | Linux | Spanish | Free | Google SSO |
| 10 | Edge | Windows | English | Free | Google SSO |
| 11 | Edge | macOS | Spanish | Enterprise | Email/password |
| 12 | Edge | Linux | Japanese | Pro | SAML |
| 13 | Chrome | Windows | Japanese | Pro | SAML |
| 14 | Firefox | macOS | English | Enterprise | Google SSO |
| 15 | Safari | Linux | English | Free | SAML |
| 16 | Edge | Windows | Spanish | Free | Email/password |
Это 16 тестов, покрывающих все пары, вместо 324 исчерпывающих комбинаций -- сокращение на 95% количества тестов.
Валидация попарного покрытия
После генерации проверьте, что каждая пара действительно присутствует:
from itertools import combinations
def verify_pairwise_coverage(test_suite: list[dict], parameters: dict) -> list[str]:
"""Check that every pair of parameter values appears in at least one test."""
missing_pairs = []
param_names = list(parameters.keys())
for p1, p2 in combinations(param_names, 2):
for v1 in parameters[p1]:
for v2 in parameters[p2]:
found = any(
test[p1] == v1 and test[p2] == v2
for test in test_suite
)
if not found:
missing_pairs.append(f"({p1}={v1}, {p2}={v2})")
return missing_pairs
# Usage
parameters = {
"browser": ["Chrome", "Firefox", "Safari", "Edge"],
"os": ["Windows", "macOS", "Linux"],
"language": ["English", "Spanish", "Japanese"],
"account": ["Free", "Pro", "Enterprise"],
"auth": ["Email/password", "Google SSO", "SAML"],
}
missing = verify_pairwise_coverage(test_suite, parameters)
if missing:
print(f"INCOMPLETE: {len(missing)} pairs not covered:")
for pair in missing:
print(f" - {pair}")
else:
print("All pairs covered!")
Комбинаторное тестирование высшего порядка (3-Way, N-Way)
Когда дефекты вызываются взаимодействием трёх или более параметров, вам нужно покрытие более высокого порядка.
Когда необходимо 3-Way тестирование
- Критичные для безопасности системы (аутентификация, авторизация, шифрование)
- Финансовые вычисления (валюта + округление + налоговая юрисдикция)
- Тестирование аппаратного/встроенного ПО (комбинации сигналов)
- Поведение, зависящее от конфигурации (feature flags + окружения + роли пользователей)
Промпт для 3-Way генерации
Generate a 3-way combinatorial test suite for the payment processing module:
Parameters:
- Payment method: credit_card, debit_card, bank_transfer, paypal
- Currency: USD, EUR, GBP, JPY
- Amount range: small (< $10), medium ($10-$1000), large (> $1000)
- Customer type: new, returning, VIP
- Region: domestic, international
Requirements:
- Every combination of any 3 parameter values must appear in at least one test
- Minimize total number of test cases
- Output as a numbered table with all parameters
Количество тестов для 3-way значительно больше, чем для попарного (обычно 40-60 тестов для данного набора параметров), но всё ещё намного меньше исчерпывающих 4 x 4 x 3 x 3 x 2 = 288 комбинаций.
ИИ vs специализированные комбинаторные инструменты
| Подход | Лучше всего подходит для | Ограничение |
|---|---|---|
| Попарное, сгенерированное ИИ | Быстрое исследование, малые пространства параметров (5-7 параметров) | Не математически оптимально для больших пространств |
| PICT (Microsoft) | Большие пространства параметров (10+ параметров), доказуемое покрытие | Требует установки и настройки |
| ACTS (NIST) | N-way покрытие исследовательского уровня с ограничениями | Зависимость от Java, более крутая кривая обучения |
| Гибрид ИИ + PICT | ИИ определяет параметры и ограничения, PICT генерирует комбинации | Дополнительная настройка, но наиболее строгий подход |
Гибридный рабочий процесс ИИ + PICT
Это наиболее строгий подход, и его стоит упомянуть на собеседованиях:
Step 1: Ask AI to identify all relevant parameters and their values
from the specification or requirements document.
Step 2: Ask AI to identify constraints (invalid combinations that
should be excluded, e.g., "SAML auth is only available for
Enterprise accounts").
Step 3: Generate PICT model file from AI output:
# registration.pict (generated by AI, verified by human)
Browser: Chrome, Firefox, Safari, Edge
OS: Windows, macOS, Linux
Language: English, Spanish, Japanese
Account: Free, Pro, Enterprise
Auth: EmailPassword, GoogleSSO, SAML
# Constraints (AI-identified)
IF [Auth] = "SAML" THEN [Account] = "Enterprise";
IF [OS] = "macOS" THEN [Browser] <> "Edge";
Step 4: Run PICT to generate the optimal test suite:
$ pict registration.pict > test_combinations.tsv
Step 5: Ask AI to convert the TSV into executable test code
matching your framework and style.
Преобразование комбинаторных таблиц в тестовый код
import pytest
import csv
def load_pairwise_tests(filepath: str) -> list[dict]:
"""Load pairwise test cases from a TSV file."""
with open(filepath) as f:
reader = csv.DictReader(f, delimiter='\t')
return list(reader)
PAIRWISE_TESTS = load_pairwise_tests("test_combinations.tsv")
class TestRegistrationCombinatorial:
"""Pairwise combinatorial tests for user registration."""
@pytest.mark.parametrize("combo", PAIRWISE_TESTS,
ids=[f"combo-{i}" for i in range(len(PAIRWISE_TESTS))])
def test_registration_combination(self, browser_driver, combo):
"""Each pairwise combination should either succeed or fail gracefully."""
driver = browser_driver(
browser=combo["Browser"],
os=combo["OS"],
language=combo["Language"]
)
# Navigate to registration
driver.navigate("/register")
# Fill form based on combination
driver.select_account_type(combo["Account"])
driver.select_auth_method(combo["Auth"])
# Assert: registration either succeeds or shows a clear error
# (no crashes, no blank pages, no 500 errors)
assert driver.current_url in ["/dashboard", "/register"]
if driver.current_url == "/register":
assert driver.find_element(".error-message").is_displayed()
Практические рекомендации
Сколько параметров оправдывают комбинаторное тестирование?
- 2-3 параметра: Тестируйте все комбинации вручную. Комбинаторные инструменты избыточны.
- 4-7 параметров: Попарное тестирование -- оптимальный вариант. ИИ-генерация быстра и достаточна.
- 8-15 параметров: Используйте PICT или ACTS. Попарное, сгенерированное ИИ, может пропустить пары.
- 15+ параметров: Вам, вероятно, нужно сначала сократить пространство параметров. Обсудите с командой, какие взаимодействия действительно имеют значение.
Как представить это на собеседовании
"For features with multiple interacting parameters, I use pairwise
combinatorial testing to reduce the test space. For a 5-parameter form
with 3-5 values each, this cuts 300+ combinations to about 16-20 tests
while covering all parameter pair interactions. I generate the initial
matrix using AI from the spec, verify coverage programmatically, then
convert it to parametrized tests. For larger parameter spaces or
safety-critical features, I use Microsoft PICT with AI-identified
constraints to get mathematically optimal coverage."
Частые подводные камни
Забывание об ограничениях. Не все комбинации валидны. Аутентификация через SAML может работать только с аккаунтами Enterprise. Если вы не моделируете ограничения, вы получаете тестовые сценарии, которых не должно существовать.
Путаница попарного с случайным. Случайная выборка не гарантирует попарного покрытия. Случайная выборка 20 тестов из 324 комбинаций обычно пропускает 30-40% пар.
Игнорирование негативных комбинаций. Попарное покрытие охватывает валидные взаимодействия, но вам также нужны тесты для невалидных комбинаций (например, отрицательное количество + просроченный купон + отсутствующая аутентификация).
Чрезмерное доверие к оптимальности ИИ. Попарные наборы, сгенерированные ИИ, хороши, но не всегда математически минимальны. Для критических систем проверяйте с помощью специализированного инструмента.
Ключевой вывод
Комбинаторное тестирование -- это мост между «тестировать всё» (непрактично) и «тестировать немного» (недостаточно). ИИ делает его доступным, генерируя попарные наборы из описаний параметров на естественном языке. Для максимальной строгости комбинируйте идентификацию параметров с помощью ИИ со специализированными инструментами типа PICT для генерации.