Разбиение на классы эквивалентности (equivalence partitioning) - техника тестирования методом чёрного ящика, которая делит данные объекта тестирования на классы, значения внутри которых должны обрабатываться одинаково, и строит тест-кейсы так, чтобы каждый класс был проверен хотя бы один раз. Анализ граничных значений (boundary value analysis) - техника тестирования методом чёрного ящика, которая строит тест-кейсы по минимальным и максимальным значениям упорядоченных классов: именно там обычно находятся дефекты сравнений и ограничений. Техники применяются вместе: разбиение задаёт классы, анализ граничных значений выбирает значения на их краях.
Обе техники описаны в книге Glenford Myers The Art of Software Testing, впервые изданной в 1979 году; по данным рецензии на эту книгу на сайте AgileConnection, они были изложены там вместе с построением графа причин и следствий (cause-effect graphing) и предугадыванием ошибок (error guessing). Сегодня их определяют международный стандарт ISO/IEC/IEEE 29119-4:2021, Software testing, Part 4: Test techniques (разделы 5.2.1 и 5.2.3), и силлабус ISTQB Certified Tester Foundation Level версии 4.0.1 (разделы 4.2.1 и 4.2.2).
История
В таблице - основные вехи в описании техник.
| Дата | Событие |
|---|---|
| 1979 | Книга Glenford Myers The Art of Software Testing описывает разбиение на классы эквивалентности и анализ граничных значений |
| 2015 | Первая редакция ISO/IEC/IEEE 29119-4, техники тестирования |
| Октябрь 2021 | Вторая редакция ISO/IEC/IEEE 29119-4: техники определены через тестовые модели вместо условий тестирования |
| 21 апреля 2023 | Официальный выпуск силлабуса ISTQB CTFL v4.0 |
| 15 сентября 2024 | Силлабус ISTQB CTFL v4.0.1, исправление ошибок; описывает анализ по двум и по трём точкам и покрытие Each Choice |
Какую задачу решают техники
Исчерпывающее тестирование невозможно почти для любых реальных входных данных. У поля количества, которое принимает целые числа, миллиарды возможных значений, а форма объединяет несколько полей. Значения, выбранные наугад, не доказывают, что важные случаи проверены.
Разбиение на классы эквивалентности заменяет множество всех значений небольшим набором классов. Если все значения класса обрабатываются одинаково, тест с одним из них говорит о классе столько же, сколько тест с любым другим.
Само разбиение не говорит, какое значение класса взять. Требование «от 1 до 99» можно реализовать как quantity < 99 вместо quantity <= 99. Все значения из середины класса проходят, не проходит только 99. Силлабус ISTQB называет это типичным дефектом, который находит анализ граничных значений: реализованная граница сдвинута выше или ниже нужного места либо отсутствует.
Классы эквивалентности
Класс эквивалентности (equivalence partition, equivalence class) - подмножество возможных значений элемента данных, для которых объект тестирования должен вести себя одинаково. ISO/IEC/IEEE 29119-4 применяет этот термин и к входным, и к выходным данным.
Допустимые и недопустимые классы
Класс значений, которые объект тестирования должен принять, - допустимый класс (valid partition). Класс значений, которые он должен отклонить, - недопустимый класс (invalid partition). Силлабус ISTQB отмечает, что команды и организации могут по-разному определять допустимые и недопустимые значения. Поэтому определение, принятое в проекте, фиксируется до подсчёта классов.
Правила для классов
Классы можно выделить для любого элемента данных, связанного с объектом тестирования: входных и выходных данных, элементов конфигурации, внутренних значений, значений, связанных со временем, и параметров интерфейсов. К любому набору классов применяются два правила:
- Классы не пересекаются. Значение принадлежит ровно одному классу.
- Пустых классов нет. В каждом классе есть хотя бы одно значение. Класс может состоять из одного значения, например из пустой строки.
Классы выходных данных выделяются так же: у расчёта налога с тремя ставками три класса выходных данных.
Покрытие и тест-кейсы
При разбиении на классы эквивалентности элементы покрытия - это классы, включая недопустимые. Покрытие - число классов, проверенных хотя бы одним тест-кейсом, делённое на общее число выделенных классов, в процентах. Для покрытия 100 процентов достаточно одного тест-кейса на класс.
В The Art of Software Testing есть правило для недопустимых классов: каждый тест-кейс покрывает только один недопустимый класс. Причина - маскирование: если тест-кейс недопустим в двух отношениях, первая проверка, которая его отклоняет, скрывает вторую. Допустимые классы можно объединять в одном тест-кейсе.
Несколько параметров и покрытие Each Choice
У объекта тестирования с несколькими параметрами для каждого параметра свой набор классов. Для этого случая силлабус ISTQB определяет покрытие Each Choice (Each Choice coverage): каждый класс каждого набора проверен хотя бы одним тест-кейсом. Сочетания классов не учитываются.
В примере ниже два параметра: количество товара в заказе с тремя классами и способ оплаты с тремя классами.
| Параметр | Классы |
|---|---|
| Количество | Меньше 1 (недопустимый), от 1 до 99 (допустимый), больше 99 (недопустимый) |
| Способ оплаты | Карта (допустимый), счёт (допустимый), неподдерживаемый способ (недопустимый) |
Для покрытия Each Choice нужно не меньше трёх тест-кейсов - столько, сколько классов в самом большом наборе. Но при трёх тест-кейсах два недопустимых значения попадают в один тест-кейс. По правилу «один недопустимый класс на тест-кейс» набор вырастает до пяти: два тест-кейса объединяют допустимые классы, три содержат по одному недопустимому значению.
Сочетаниями классов занимаются другие техники: таблицы решений, когда результат зависит от сочетания, и попарное тестирование, когда параметров много.
Анализ граничных значений
Граничное значение (boundary value) - минимальное или максимальное значение упорядоченного класса. Анализ граничных значений применим только к упорядоченным классам: числам, длинам, датам и времени. У способа оплаты или страны нет порядка, а значит, нет и границ.
Анализ граничных значений по двум точкам
При анализе граничных значений по двум точкам (2-value boundary value analysis) у каждого граничного значения два элемента покрытия: само граничное значение и ближайшее к нему значение соседнего класса. У допустимого класса целых количеств от 1 до 99 граничные значения 1 и 99, а границы соседних недопустимых классов - 0 и 100. Анализ по двум точкам даёт четыре тестовых значения: 0, 1, 99 и 100.
Анализ граничных значений по трём точкам
При анализе граничных значений по трём точкам (3-value boundary value analysis) у каждого граничного значения три элемента покрытия: граничное значение и оба его соседа. Для границы 1 это 0, 1 и 2; для границы 99 - 98, 99 и 100.
Силлабус ISTQB называет анализ по трём точкам более строгим и показывает это на дефекте. Требование x <= 10 реализовано как x = 10. Значения 10 и 11 из анализа по двум точкам дают одинаковые результаты в обеих версиях: 10 принимается, 11 отклоняется. Значение 9, которое добавляет только анализ по трём точкам, по требованию принимается, а реализацией отклоняется.
Формулы покрытия
В таблице - элементы покрытия и мера покрытия каждой техники в определении силлабуса ISTQB v4.0.1.
| Техника | Элементы покрытия | Покрытие |
|---|---|---|
| Разбиение на классы эквивалентности | Классы, допустимые и недопустимые | Проверенные классы / выделенные классы |
| Анализ по двум точкам | Каждое граничное значение и ближайший сосед в соседнем классе | Проверенные граничные значения / выделенные граничные значения |
| Анализ по трём точкам | Каждое граничное значение и оба его соседа | Проверенные граничные значения и соседи / все выделенные граничные значения и соседи |
Покрытие выражается в процентах от выделенных элементов: класс, который никто не выделил, его не снижает.
Числа
Диапазон целых чисел
Требование: количество товара в заказе - целое число от 1 до 99. В поле ввода попадают и значения, которые не являются целыми числами.
| Класс | Значения | Тип |
|---|---|---|
| P1 | Целые числа меньше 1 | Недопустимый |
| P2 | Целые числа от 1 до 99 | Допустимый |
| P3 | Целые числа больше 99 | Недопустимый |
| P4 | Дробные числа, например 2.5 | Недопустимый |
| P5 | Нечисловой текст, например abc |
Недопустимый |
P1-P3 упорядочены и имеют границы; у P4 и P5 границ нет. В таблице - тестовые значения каждой техники.
| Техника | Тестовые значения |
|---|---|
| Разбиение на классы эквивалентности | -5, 50, 150, 2.5, abc |
| Анализ по двум точкам | 0, 1, 99, 100 |
| Анализ по трём точкам | -1, 0, 1, 2, 98, 99, 100, 101 |
Значения 0 и 100 - границы недопустимых классов P1 и P3. Их соседи -1 и 101 появляются в анализе по трём точкам. В pytest значения становятся списком параметров, и тестовая функция выполняется для каждого из них:
import pytest
from shop.cart import validate_quantity
@pytest.mark.parametrize(
("quantity", "valid"),
[(-1, False), (0, False), (1, True), (2, True),
(98, True), (99, True), (100, False), (101, False)],
)
def test_quantity_boundaries(quantity, valid):
assert validate_quantity(quantity) is validПараметризованные тест-кейсы описаны в статье Тест-кейс.
Денежная сумма
Требование: сумма перевода от 0.01 до 10000.00, не больше двух знаков после запятой. Шаг между соседними значениями - наименьшая единица суммы, 0.01. Без шага у дробного класса нет ближайшего соседа, поэтому шаг берётся из спецификации.
| Класс | Значения | Тип |
|---|---|---|
| P1 | Суммы до 0.00 включительно | Недопустимый |
| P2 | От 0.01 до 10000.00 | Допустимый |
| P3 | Больше 10000.00 | Недопустимый |
Анализ по двум точкам даёт 0.00, 0.01, 10000.00 и 10000.01. Анализ по трём точкам добавляет -0.01, 0.02, 9999.99 и 10000.02. Число знаков после запятой - второй параметр со своими классами: до двух знаков (допустимый) и больше двух знаков, например 10.005 (недопустимый). Это отдельный параметр: по величине 10.005 лежит внутри P2, а классы одного набора не должны пересекаться.
Важен и тип значения. Документация Python отмечает, что числа вроде 1.1 и 2.2 не имеют точного представления в двоичной арифметике с плавающей точкой, в отличие от десятичного типа. Сравнение двоичной суммы с плавающей точкой на границе может дать неожиданный результат.
Строки
Требование: имя пользователя длиной от 3 до 20 символов, состоит из латинских букв, цифр и знаков подчёркивания. У строки два независимых набора классов: по длине и по символам.
| Параметр | Класс | Тип |
|---|---|---|
| Длина | 0, пустая строка | Недопустимый |
| Длина | От 1 до 2 | Недопустимый |
| Длина | От 3 до 20 | Допустимый |
| Длина | 21 и больше | Недопустимый |
| Символы | Только буквы, цифры, подчёркивания | Допустимый |
| Символы | Хотя бы один другой символ, например пробел или - |
Недопустимый |
Пустая строка - отдельный класс, если система обрабатывает её иначе, например сообщением об обязательном поле. Длина упорядочена, поэтому у классов по длине есть границы. Анализ по двум точкам даёт строки длиной 0, 1, 2, 3, 20 и 21. Анализ по трём точкам добавляет длины 4, 19 и 22; длины -1 не существует, поэтому у границы 0 только один сосед. У символов порядка нет, и их классы покрываются только разбиением на классы эквивалентности.
Единица длины - часть границы. Ключевые слова JSON Schema minLength и maxLength считают символы в определении RFC 8259. Свойство JavaScript length и атрибут HTML maxlength считают кодовые единицы UTF-16, поэтому длина эмодзи равна 2. Строка Python str - последовательность кодовых точек Unicode, и len() для того же эмодзи возвращает 1. Имя пользователя из 20 символов с одним эмодзи имеет длину 20 для одного компонента и 21 для другого. Входные схемы инструментов MCP используют те же ключевые слова JSON Schema; они описаны в статье Инструменты в MCP.
Даты
Даты упорядочены. Шаг - один день или меньше, если значение включает время.
Диапазон дат
Требование: доставку можно заказать на дату от завтрашней до 90 дней вперёд. При текущей дате 3 ноября 2026 классы такие:
| Класс | Даты | Тип |
|---|---|---|
| P1 | До 2026-11-03 включительно | Недопустимый |
| P2 | С 2026-11-04 по 2027-02-01 | Допустимый |
| P3 | С 2027-02-02 | Недопустимый |
Анализ по двум точкам даёт 2026-11-03, 2026-11-04, 2027-02-01 и 2027-02-02. Анализ по трём точкам добавляет 2026-11-02, 2026-11-05, 2027-01-31 и 2027-02-03. Границы зависят от текущей даты, а текущая дата - от часового пояса. Тесты такого требования фиксируют часы и часовой пояс объекта тестирования; иначе одни и те же данные в разные дни попадают в разные классы.
Високосные годы и конец месяца
Допустимые дни месяца зависят от месяца, а для февраля - и от года. В григорианском календаре год високосный, если он делится на 4, кроме лет, которые делятся на 100, но не делятся на 400. Поэтому у года четыре класса, по одному на каждую ветвь правила:
| Класс | Пример | Февраль |
|---|---|---|
| Делится на 400 | 2000 | 29 дней |
| Делится на 100, не делится на 400 | 2100 | 28 дней |
| Делится на 4, не делится на 100 | 2028 | 29 дней |
| Не делится на 4 | 2027 | 28 дней |
Для каждого месяца последний допустимый день - граница, а следующий день - её сосед в недопустимом классе. Модуль Python calendar использует пролептический григорианский календарь, а calendar.monthrange() возвращает число дней в месяце. Скрипт печатает пары для анализа по двум точкам:
import calendar
for year, month in [(2027, 2), (2028, 2), (2100, 2), (2026, 4), (2026, 12)]:
last_day = calendar.monthrange(year, month)[1]
print(year, month, "valid:", last_day, "invalid:", last_day + 1)Вывод даёт 28 и 29 для февраля 2027 и 2100 годов, 29 и 30 для февраля 2028 года, 30 и 31 для апреля, 31 и 32 для декабря. Нижняя граница одинакова для всех месяцев: день 1 допустим, день 0 - нет.
Сочетание с таблицами решений
Разбиение на классы эквивалентности и анализ граничных значений рассматривают параметры по одному. Когда результат зависит от сочетания условий, сочетания описывает таблица решений. Её условиями часто служат классы, например «сумма заказа: меньше 100.00, 100.00 и больше». Каждое правило таблицы тогда - сочетание классов, значения его тест-кейса берутся из них, а граничные значения добавляют тест-кейсы на краях каждого условия. Таблицы описаны в статье Таблицы решений.
Где техники не помогают
Техники исходят из того, что все значения класса обрабатываются одинаково. Если это не так, выбранные значения ничего не говорят об остальной части класса. Вне их области несколько случаев:
- Неупорядоченные данные. У способов оплаты, стран и типов файлов есть классы, но нет границ.
- Сочетания. Дефект, который проявляется только при определённой паре значений, не находится изменением одного параметра за раз.
- Поведение, зависящее от истории. Один и тот же ввод допустим в одном состоянии и недопустим в другом: этим занимается тестирование переходов состояний.
- Последовательности действий. Сценариями с альтернативными потоками занимается тестирование по вариантам использования.
- Границы, которых нет в спецификации. Максимум 32-битного знакового целого - 2147483647. Такие ограничения приходят из реализации, и спецификация их не показывает.
Классы верны настолько, насколько верна спецификация, из которой они получены. У пропущенного требования нет класса, и его не проверяет ни один тест.
Разбиение на классы и смежные техники
В таблице техники этой статьи сравниваются с другими техниками чёрного ящика, с которыми их сочетают.
| Техника | Тестовая модель | Что покрывает |
|---|---|---|
| Разбиение на классы эквивалентности | Классы каждого элемента данных | Каждый класс хотя бы один раз |
| Анализ граничных значений | Упорядоченные классы и их края | Границы и их соседей |
| Таблицы решений | Условия, действия и правила | Выполнимые сочетания условий |
| Попарное тестирование | Параметры и их значения | Каждую пару значений любых двух параметров |
Разбиение на классы эквивалентности - основа остальных: анализ граничных значений уточняет его внутри упорядоченных классов, таблицы решений и попарное тестирование используют классы как значения и добавляют сочетания.
ISO/IEC/IEEE 29119-4 также называет метод дерева классификации (classification tree method) среди техник на основе спецификации. Выбор зависит от того, от чего зависит результат: от отдельных значений, от краёв или от сочетаний.
Термины
| Термин | Значение |
|---|---|
| Разбиение на классы эквивалентности (equivalence partitioning) | Техника тестирования методом чёрного ящика, при которой тест-кейсы проверяют каждый класс значений, обрабатываемых одинаково |
| Класс эквивалентности (equivalence partition) | Подмножество значений элемента данных, для которых объект тестирования должен вести себя одинаково |
| Допустимый класс (valid partition) | Класс значений, которые объект тестирования должен принять |
| Недопустимый класс (invalid partition) | Класс значений, которые объект тестирования должен отклонить |
| Покрытие Each Choice (Each Choice coverage) | Покрытие, при котором каждый класс каждого параметра проверен хотя бы один раз, без учёта сочетаний |
| Граничное значение (boundary value) | Минимальное или максимальное значение упорядоченного класса |
| Анализ граничных значений (boundary value analysis) | Техника тестирования методом чёрного ящика, при которой тест-кейсы строятся по граничным значениям упорядоченных классов |
| Анализ граничных значений по двум точкам (2-value boundary value analysis) | Вариант анализа граничных значений с двумя элементами покрытия на границу: граница и ближайший сосед в соседнем классе |
| Анализ граничных значений по трём точкам (3-value boundary value analysis) | Вариант анализа граничных значений с тремя элементами покрытия на границу: граница и оба её соседа |
Источники
- ISTQB Certified Tester Foundation Level Syllabus v4.0.1, разделы 4.2.1 и 4.2.2, ISTQB, 2024(откроется в новой вкладке) (на английском)
- Глоссарий ISTQB(откроется в новой вкладке) (на английском)
- Зеркало глоссария ISTQB: equivalence partitioning, imbus(откроется в новой вкладке) (на английском)
- Зеркало глоссария ISTQB: boundary value, imbus(откроется в новой вкладке) (на английском)
- ISO/IEC/IEEE 29119-4:2021, Software testing, Part 4: Test techniques, ISO(откроется в новой вкладке) (на английском)
- The Art of Software Testing, 3rd Edition, Glenford J. Myers, Tom Badgett, Corey Sandler, Wiley, 2011(откроется в новой вкладке) (на английском)
- Рецензия на The Art of Software Testing, AgileConnection(откроется в новой вкладке) (на английском)
- JSON Schema Validation, draft 2020-12, разделы 6.2 и 6.3(откроется в новой вкладке) (на английском)
- String: length, MDN Web Docs(откроется в новой вкладке) (на английском)
- HTML attribute: maxlength, MDN Web Docs(откроется в новой вкладке) (на английском)
- calendar, документация Python(откроется в новой вкладке) (на английском)
- decimal, документация Python(откроется в новой вкладке) (на английском)
- How to parametrize fixtures and test functions, документация pytest(откроется в новой вкладке) (на английском)