Тестирование переходов состояний (state transition testing) - техника тестирования методом чёрного ящика, при которой тест-кейсы строятся так, чтобы задействовать элементы модели переходов состояний. Модель описывает состояния объекта тестирования, события, на которые он реагирует, и переходы между состояниями, которые эти события вызывают. Техника нужна, когда реакция системы на ввод зависит не только от самого ввода, но и от того, что происходило раньше.
Модели состояний пришли из теории автоматов. В 1978 году Т. С. Чоу (T. S. Chow) опубликовал в журнале IEEE Transactions on Software Engineering метод тестирования проектов программ, описанных конечными автоматами, и глоссарий ISTQB называет Чоу источником термина «покрытие N-переключений» (N-switch coverage). Сегодня техника - одна из четырёх техник чёрного ящика в силлабусе ISTQB Foundation Level (версия 4.0.1, раздел 4.2.4). Силлабус Advanced Level Test Analyst (версия 4.0, 2025 год, раздел 3.2.2) добавляет покрытие N-переключений и покрытие круговых путей. Стандарт ISO/IEC/IEEE 29119-4:2021 описывает технику в разделе 5.2.8, а измерение её покрытия - в разделе 6.2.8.
Какую задачу решает тестирование переходов состояний
Многие объекты по-разному реагируют на один и тот же ввод. Кнопка «Отменить» отменяет заказ, который ждёт оплаты, возвращает деньги за оплаченный заказ и ничего не делает с уже отправленным. Верный пароль открывает учётную запись после одной неудачной попытки и не открывает после трёх, потому что к этому моменту учётная запись заблокирована. Ввод один и тот же, результат зависит от состояния.
Техники, которые смотрят только на входные значения, этой зависимости не видят. Классы эквивалентности и таблицы решений описывают одну реакцию на одно сочетание входных данных. Они не описывают последовательности: что будет, если заказ оплатить, затем отменить, а затем событие оплаты придёт ещё раз. Дефекты такого рода проявляются в порядке событий, а не в значениях.
Модель состояний делает зависимость явной. Она перечисляет состояния, указывает, какие события допустимы в каждом из них и куда ведёт каждое событие. Тест-кейсы затем строятся как пути по модели, а покрытие показывает, какие состояния и переходы тесты задействовали.
Элементы модели состояний
Модель состояний состоит из нескольких элементов. В таблице они перечислены с примерами из жизненного цикла заказа, который используется дальше.
| Элемент | Значение | Пример |
|---|---|---|
| Состояние | Положение, в котором объект ждёт событий | Paid |
| Событие | Происшествие, которое может вызвать переход | ship |
| Переход | Смена исходного состояния на целевое | Из Paid в Shipped |
| Сторожевое условие | Условие, которое должно быть истинным, чтобы переход сработал | payment approved |
| Действие | Поведение, которое выполняется при переходе | send tracking number |
| Начальное состояние | Состояние, в котором объект начинает работу | Pending payment |
| Конечное состояние | Состояние, после которого объект не принимает событий | Delivered, Cancelled |
Силлабус ISTQB записывает метку перехода как event [guard condition] / action. Сторожевое условие (guard condition) и действие (action) опускаются, если их нет или если для тестировщика они не важны. Переходы считаются мгновенными. Переход может вести обратно в то же состояние: отклонённая оплата оставляет заказ в ожидании оплаты и показывает ошибку.
Сторожевые условия делят одно событие на несколько переходов. Событие pay из состояния Pending payment ведёт в Paid, если оплата одобрена, и оставляет заказ в Pending payment, если она отклонена. Для тестировщика это два разных перехода, и каждому нужен свой тест.
Диаграмма состояний
Диаграмма состояний (state diagram) показывает состояния как узлы, а допустимые переходы - как стрелки с подписями событий. Жизненный цикл заказа в интернет-магазине содержит пять состояний и шесть допустимых переходов:
start
|
v
+-----------------+ pay [declined] / show error
| Pending payment |--------------------------+
| |<-------------------------+
+-----------------+
| |
| cancel | pay [approved] / send receipt
| v
| +------+
| | Paid |----------------------+
| +------+ |
| | | cancel / refund
| | ship / send tracking |
| v |
| +---------+ |
| | Shipped | |
| +---------+ |
| | |
| | deliver |
| v |
| +-----------+ |
| | Delivered | |
| +-----------+ |
v |
+-----------+ |
| Cancelled |<-------------------------+
+-----------+Переходы пронумерованы, чтобы ссылаться на них дальше в статье:
| № | Исходное состояние | Событие [условие] / действие | Целевое состояние |
|---|---|---|---|
| T1 | Pending payment | pay [approved] / send receipt | Paid |
| T2 | Pending payment | pay [declined] / show error | Pending payment |
| T3 | Pending payment | cancel | Cancelled |
| T4 | Paid | cancel / refund | Cancelled |
| T5 | Paid | ship / send tracking | Shipped |
| T6 | Shipped | deliver | Delivered |
Диаграмма показывает только то, что разрешено. Она не показывает, что происходит, когда событие приходит в состояние, где для него нет стрелки, например cancel для отправленного заказа.
Таблица состояний
Таблица состояний (state table) - модель, равносильная диаграмме состояний. Её строки - состояния, столбцы - события вместе со сторожевыми условиями, а в каждой ячейке записаны целевое состояние и действие. В отличие от диаграммы, таблица состояний явно показывает недопустимые переходы. Силлабус ISTQB оставляет такие ячейки пустыми; в таблице ниже они отмечены дефисом:
| Состояние | pay [approved] | pay [declined] | cancel | ship | deliver |
|---|---|---|---|---|---|
| Pending payment | Paid / send receipt | Pending payment / show error | Cancelled | - | - |
| Paid | - | - | Cancelled / refund | Shipped / send tracking | - |
| Shipped | - | - | - | - | Delivered |
| Delivered | - | - | - | - | - |
| Cancelled | - | - | - | - | - |
В таблице 25 ячеек: 6 допустимых переходов и 19 недопустимых. Построение таблицы заставляет принять решение по каждой ячейке. Ячейка, которую никто не может заполнить, - вопрос к авторам требований: нужно ли вернуть деньги за оплаченный заказ, который отменили во время сборки, или отклонить отмену?
Недопустимые переходы
Недопустимый переход (invalid transition) - событие, которое приходит в состояние, где оно не разрешено. Ожидаемый результат такого теста определяют требования. Обычно объект остаётся в том же состоянии, никакое действие не выполняется, а пользователь или вызывающая система получает ошибку. Некоторые события по замыслу игнорируются без ошибки, например повторное deliver от системы курьерской службы. Тест проверяет состояние после события, а не только сообщение.
Недопустимые переходы не всегда достижимы через пользовательский интерфейс. Интерфейс может скрывать кнопку отправки у неоплаченного заказа, а API за ним при этом всё равно принимает запрос. Поэтому тесты недопустимых переходов выполняют и ниже пользовательского интерфейса, где событие можно отправить напрямую.
Критерии покрытия
Силлабус ISTQB определяет три критерия покрытия для тестирования переходов состояний. Каждый измеряется в процентах: задействованные элементы покрытия, делённые на все элементы покрытия.
| Критерий | Элементы покрытия | Пример с заказом |
|---|---|---|
| Покрытие всех состояний | Состояния | 5 состояний |
| Покрытие допустимых переходов (0-switch) | Отдельные допустимые переходы | 6 переходов |
| Покрытие всех переходов | Допустимые и недопустимые переходы таблицы состояний | 6 допустимых и 19 недопустимых |
Критерии образуют иерархию. Полное покрытие допустимых переходов гарантирует полное покрытие всех состояний. Полное покрытие всех переходов гарантирует оба. Силлабус называет покрытие допустимых переходов самым распространённым критерием и рекомендует покрытие всех переходов как минимум для критически важного программного обеспечения и программного обеспечения, от которого зависит безопасность.
Покрытие всех состояний
Покрытие всех состояний (all states coverage) требует, чтобы каждое состояние было достигнуто хотя бы один раз. В примере с заказом достаточно двух тест-кейсов: один проходит через Pending payment, Paid, Shipped и Delivered, другой отменяет заказ. Критерий слабый: его можно выполнить, не задействовав ни возврат денег (T4), ни отклонённую оплату (T2).
Покрытие допустимых переходов
Покрытие допустимых переходов (valid transitions coverage) требует, чтобы каждый допустимый переход был задействован хотя бы один раз. Его также называют покрытием 0-переключений (0-switch coverage). Тест-кейс - это последовательность событий, и один тест-кейс может задействовать несколько переходов. Три тест-кейса покрывают все шесть переходов примера; они перечислены ниже, в разделе о тест-кейсах.
Покрытие всех переходов
Покрытие всех переходов (all transitions coverage) добавляет каждый недопустимый переход таблицы состояний. Силлабус рекомендует проверять один недопустимый переход в одном тест-кейсе. Два недопустимых события в одном тест-кейсе могут привести к маскированию дефектов (defect masking): первый дефект скрывает второй. В примере 19 недопустимых переходов требуют не меньше 19 тест-кейсов. Допустимые переходы укладываются в их первые шаги, которые приводят заказ в состояние, где отправляется недопустимое событие.
Покрытие N-переключений
Покрытие N-переключений (N-switch coverage) - покрытие последовательностей из N+1 идущих подряд допустимых переходов. Покрытие допустимых переходов - случай N = 0. Покрытие 1-переключений требует каждой пары последовательных переходов, где второй начинается в состоянии, в котором закончился первый. В примере с заказом таких пар шесть:
| Промежуточное состояние | Пары переходов |
|---|---|
| Pending payment | T2, затем T1; T2, затем T2; T2, затем T3 |
| Paid | T1, затем T4; T1, затем T5 |
| Shipped | T5, затем T6 |
Пара T2, затем T2 - это две отклонённые оплаты подряд. Она проверяет, что вторая попытка принимается и после неудачи первой, чего отдельные переходы не показывают. По данным силлабуса Test Analyst, на практике часто используют покрытие 0- и 1-переключений, а покрытие 2-переключений и выше оправдано только при высоком риске отказа. Тот же силлабус определяет покрытие круговых путей (round-trip coverage): круговой путь (round trip) - цикл, который начинается и заканчивается в одном и том же состоянии, и никакое другое состояние в нём не встречается дважды.
Тест-кейсы для примера с заказом
Следующие тест-кейсы дают полное покрытие допустимых переходов. Каждая строка - последовательность событий из начального состояния Pending payment.
| Тест-кейс | События | Пройденные состояния | Переходы |
|---|---|---|---|
| ST-1 | pay [declined], pay [approved], ship, deliver | Pending payment, Pending payment, Paid, Shipped, Delivered | T2, T1, T5, T6 |
| ST-2 | cancel | Pending payment, Cancelled | T3 |
| ST-3 | pay [approved], cancel | Pending payment, Paid, Cancelled | T1, T4 |
ST-1 и ST-2 вместе достигают всех пяти состояний, то есть дают покрытие всех состояний. ST-3 добавляет возврат денег - единственный переход, который первые два пропускают. Каждый тест-кейс проверяет состояние и действие после каждого события: сообщение об ошибке после отклонённой оплаты, чек, номер для отслеживания, возврат денег.
Тесты недопустимых переходов строятся так же, с одним недопустимым событием в конце. Например:
| Тест-кейс | События | Ожидаемый результат |
|---|---|---|
| ST-4 | pay [approved], ship, cancel | Ошибка; состояние остаётся Shipped; возврата нет |
| ST-5 | ship | Ошибка; состояние остаётся Pending payment; номера для отслеживания нет |
| ST-6 | cancel, pay [approved] | Ошибка; состояние остаётся Cancelled; оплата не списывается |
Тест-кейсы записываются в обычной форме с предусловиями, шагами и ожидаемыми результатами; структура описана в статье Тест-кейс. За сторожевыми условиями часто скрываются классы входных данных: «оплата одобрена» и «оплата отклонена» - результат данных карты, лимитов суммы и ответа платёжного провайдера. Выбор значений для них - предмет статьи Классы эквивалентности и граничные значения.
Визуализация потока
Диаграмма и таблица - два представления одной модели, и каждое показывает то, что скрывает другое. Диаграмма показывает поток: основной путь от начального состояния к конечным, циклы и ветвления. Таблица показывает полноту: каждую пару состояния и события, включая недопустимые.
Тест-кейсы можно нарисовать на диаграмме как пути. Если отметить путь каждого тест-кейса, пробелы становятся видны: стрелка, через которую не проходит ни один путь, - переход без теста. Ту же проверку можно сделать по списку переходов: столбец на каждый тест-кейс и отметка у каждого перехода, который он задействует.
Для больших моделей используют более выразительные нотации. Силлабус Test Analyst называет расширенные конечные автоматы, диаграммы состояний Харела (statecharts) и машины состояний UML. Статья Дэвида Харела (David Harel) 1987 года описывает statecharts как диаграммы переходов состояний, дополненные иерархией, параллельностью и взаимодействием. Иерархия сохраняет диаграмму читаемой: состояние Active может содержать Paid и Shipped, и одна стрелка cancel из Active заменяет несколько переходов. Для тест-дизайна такую модель снова разворачивают в таблицу, чтобы можно было пересчитать каждый переход и каждую недопустимую ячейку.
Диаграмма состояний в спецификации часто - лишь сводка. RFC 9293, который определяет TCP, говорит о собственной диаграмме состояний, что это только сводка и её нельзя считать полной спецификацией. Тест-кейсы строятся по полному описанию поведения, а не только по картинке.
Где применяется техника
Техника применима ко всему, чьё поведение зависит от истории событий. Типичные области:
- Сценарии пользовательского интерфейса: многошаговые формы и мастера, вход с блокировкой после нескольких неудачных попыток, сессии с ограниченным сроком действия.
- Протоколы: обработка соединений и последовательности сообщений. У TCP, как он описан в RFC 9293, одиннадцать состояний соединения, от LISTEN и SYN-SENT до TIME-WAIT и CLOSED.
- Рабочие процессы: жизненные циклы документов, заказов, заявок и отчётов о дефектах. Состояния отчёта о дефекте описаны в статье Отчёт о дефекте.
- Встроенное и управляющее программное обеспечение: устройства с режимами работы, где событие, допустимое в одном режиме, опасно в другом.
Модель должна оставаться достаточно небольшой, чтобы её можно было проверить на ревью. Когда число состояний растёт, модель делят по областям ответственности или строят с вложенными состояниями. Когда за состояниями скрывается много сочетаний условий, для каждого состояния используют таблицу решений.
Тестирование переходов состояний и смежные техники
Тестирование переходов состояний часто путают с техниками, которые тоже дают пути или правила. Таблица сравнивает их.
| Техника | Что описывает модель | Элементы покрытия | Сильная сторона |
|---|---|---|---|
| Тестирование переходов состояний | Состояния, события и переходы | Состояния, переходы, N-переключения | Порядок событий, недопустимые события |
| Тестирование с таблицами решений | Сочетания условий и действий | Выполнимые столбцы таблицы | Сложные правила для одного ввода |
| Тестирование по вариантам использования | Взаимодействие актора с системой | Основной и альтернативные сценарии | Сквозные цели пользователя |
| Разбиение на классы эквивалентности | Классы входных значений | Классы | Выбор значений |
Таблица решений описывает одну реакцию на сочетание условий; модель состояний описывает, как реакции меняются со временем. Их часто используют вместе: сторожевые условия перехода с несколькими условиями разворачивают в таблицу решений, описанную в статье Таблицы решений.
Вариант использования тоже описывает последовательность, но с точки зрения актора и цели, а не объекта и его состояний. Один вариант использования, например «купить товар», может пройти через несколько состояний заказа. Тестирование по вариантам использования проверяет, что цель достигается в каждом сценарии; тестирование переходов состояний проверяет, что объект правильно реагирует на каждое событие в каждом состоянии, включая события, которых сценарии никогда не отправляют.
Термины
| Термин | Значение |
|---|---|
| Тестирование переходов состояний (state transition testing) | Техника тестирования методом чёрного ящика, при которой тест-кейсы задействуют элементы модели переходов состояний |
| Диаграмма состояний (state diagram) | Диаграмма состояний объекта и допустимых переходов между ними |
| Таблица состояний (state table) | Таблица состояний и событий, в ячейках которой записаны целевые состояния и действия; пустые ячейки - недопустимые переходы |
| Сторожевое условие (guard condition) | Условие, которое должно быть истинным, чтобы событие вызвало переход |
| Недопустимый переход (invalid transition) | Событие, которое приходит в состояние, где модель его не разрешает |
| Покрытие допустимых переходов (valid transitions coverage) | Доля допустимых переходов, задействованных тестами; также называется покрытием 0-переключений |
| Покрытие всех переходов (all transitions coverage) | Доля допустимых и недопустимых переходов таблицы состояний, задействованных или опробованных тестами |
| Покрытие N-переключений (N-switch coverage) | Покрытие последовательностей из N+1 идущих подряд допустимых переходов |
| Круговой путь (round trip) | Цикл, который начинается и заканчивается в одном состоянии, без повторения других состояний |
Источники
- ISTQB Certified Tester Foundation Level Syllabus v4.0.1, ISTQB, 2024(откроется в новой вкладке) (на английском)
- ISTQB Certified Tester Advanced Level Test Analyst Syllabus v4.0, ISTQB, 2025(откроется в новой вкладке) (на английском)
- Глоссарий ISTQB(откроется в новой вкладке) (на английском)
- ISO/IEC/IEEE 29119-4:2021, Software and systems engineering, Software testing, Part 4: Test techniques(откроется в новой вкладке) (на английском)
- Testing Software Design Modeled by Finite-State Machines, T. S. Chow, IEEE Transactions on Software Engineering, vol. SE-4, no. 3, 1978(откроется в новой вкладке) (на английском)
- Statecharts: a visual formalism for complex systems, D. Harel, Science of Computer Programming, vol. 8, no. 3, 1987(откроется в новой вкладке) (на английском)
- RFC 9293, Transmission Control Protocol (TCP), IETF, August 2022(откроется в новой вкладке) (на английском)