Что такое тестирование переходов состояний?

Тестирование переходов состояний моделирует систему как конечный автомат (finite state machine) — систему, которая может находиться в одном из ограниченного числа состояний и переходить между ними в ответ на события. Эта техника идеальна для тестирования workflow, процессов и любых систем с различными режимами работы.

Ключевые концепции

  • Состояние: Условие, в котором находится система (напр., «Сессия закрыта», «Активно», «Заблокировано»)
  • Переход: Перемещение из одного состояния в другое
  • Событие: Что-то, вызывающее переход (напр., «ввод правильного пароля»)
  • Условие-страж (guard): Условие, которое должно быть истинным для совершения перехода
  • Действие: Что-то, происходящее во время перехода (напр., «отправить уведомление»)

Диаграмма переходов состояний

stateDiagram-v2 [*] --> СессияЗакрыта СессияЗакрыта --> СессияОткрыта: Валидные данные СессияОткрыта --> СессияЗакрыта: Выход СессияОткрыта --> Заблокировано: 30 мин неактивности Заблокировано --> СессияОткрыта: Валидные данные Заблокировано --> СессияЗакрыта: Выход СессияЗакрыта --> СессияЗакрыта: Неверные данные [попытки < 3] СессияЗакрыта --> Приостановлено: Неверные данные [попытки = 3] Приостановлено --> СессияЗакрыта: Админ разблокирует

Эта диаграмма показывает систему аутентификации с 4 состояниями и 7 переходами.

Чтение диаграммы

Каждая стрелка представляет переход в формате: Событие [Условие-страж] / Действие

  • Валидные данные → Событие, вызывающее переход
  • [попытки < 3] → Условие-страж, которое должно быть истинным
  • Целевое состояние — куда указывает стрелка

Когда использовать тестирование переходов состояний

Эта техника эффективна когда:

  • Система имеет чётко определённые режимы или статусы (заказ: ожидание → оплачен → отправлен → доставлен)
  • Пользовательские workflow имеют множество путей (корзина, процесс оформления)
  • Протоколы имеют определённые состояния (TCP-соединения, потоки аутентификации)
  • Устройства имеют операционные режимы (ожидание, активный, ошибка)

Построение таблицы переходов состояний

Таблица систематически перечисляет каждую комбинацию состояние-событие:

Текущее состояниеСобытиеСледующее состояниеДействие
СессияЗакрытаВалидные данныеСессияОткрытаСоздать сессию
СессияЗакрытаНеверные данные (< 3)СессияЗакрытаУвеличить счётчик
СессияЗакрытаНеверные данные (= 3)ПриостановленоЗаблокировать аккаунт
СессияОткрытаВыходСессияЗакрытаУничтожить сессию
СессияОткрыта30 мин неактивностиЗаблокированоСохранить состояние
ЗаблокированоВалидные данныеСессияОткрытаВосстановить состояние
ЗаблокированоВыходСессияЗакрытаУничтожить сессию
ПриостановленоАдмин разблокируетСессияЗакрытаСбросить счётчик

Определение невалидных переходов

Настоящая сила таблицы — в нахождении того, что не должно происходить. Для каждой пары состояние-событие, которой НЕТ в таблице, система должна либо игнорировать событие, либо показать ошибку.

Текущее состояниеНевалидное событиеОжидаемый результат
СессияОткрытаВалидные данныеИгнорировать (уже авторизован)
ПриостановленоВалидные данныеОтклонить (аккаунт приостановлен)
Приостановлено30 мин неактивностиИгнорировать (нет активной сессии)

Уровни покрытия

Покрытие 0-switch: Проверить каждый валидный переход хотя бы раз. Минимальное покрытие.

Покрытие 1-switch: Проверить каждую пару последовательных переходов. Обнаруживает дефекты, зависящие от истории системы.

Примеры последовательностей 1-switch:
СессияЗакрыта → СессияОткрыта → Заблокировано
СессияЗакрыта → СессияОткрыта → СессияЗакрыта
Заблокировано → СессияОткрыта → Заблокировано

Продвинутые техники тестирования переходов

Машина состояний заказа в E-Commerce

Реальные машины состояний могут быть сложными. Типичный жизненный цикл заказа:

stateDiagram-v2 [*] --> Создан Создан --> ОжидаетОплаты: Оформление ОжидаетОплаты --> Оплачен: Оплата успешна ОжидаетОплаты --> Создан: Оплата не прошла ОжидаетОплаты --> Отменён: Отмена пользователем Оплачен --> Обработка: Склад подтвердил Обработка --> Отправлен: Курьер забрал Отправлен --> Доставлен: Доставка подтверждена Отправлен --> ЗапросВозврата: Клиент запросил возврат Доставлен --> ЗапросВозврата: Клиент запросил возврат ЗапросВозврата --> Возвращён: Возврат получен Оплачен --> Возмещён: Админ возмещает ЗапросВозврата --> Возмещён: Возврат одобрен Отменён --> [*] Доставлен --> [*] Возмещён --> [*]

Из этой диаграммы выведите тест-кейсы для:

  1. Happy path: Создан → ОжидаетОплаты → Оплачен → Обработка → Отправлен → Доставлен
  2. Ошибка оплаты: Создан → ОжидаетОплаты → Создан (повтор) → ОжидаетОплаты → Оплачен
  3. Отмена: Создан → ОжидаетОплаты → Отменён
  4. Возврат: … → Доставлен → ЗапросВозврата → Возвращён
  5. Невалидные переходы: Может ли «Доставлен» вернуться в «Обработка»? Не должен.

Покрытие N-Switch

Для критических систем тестируйте последовательности из N+1 последовательных переходов:

0-switch: Каждый переход один раз (8 переходов = 8 тестов) 1-switch: Каждая пара переходов 2-switch: Каждая тройка переходов

Больший N обнаруживает больше дефектов, зависящих от истории, но растёт экспоненциально.

Параллельные машины состояний

Некоторые системы имеют несколько независимых машин состояний, работающих одновременно. Например, медиаплеер может иметь:

  • Состояние воспроизведения: Остановлено, Воспроизведение, Пауза
  • Состояние соединения: Онлайн, Офлайн, Переподключение
  • Состояние загрузки: Неактивно, Загрузка, Пауза, Завершено

Тестируйте взаимодействие между машинами состояний: что происходит с загрузкой при обрыве соединения? Что происходит с воспроизведением при завершении загрузки текущего трека?

Тестирование переходов состояний для API

Ресурсы API часто следуют машинам состояний. Тестируйте API-вызовами, которые вызывают переходы:

POST /orders                    → Создан
POST /orders/{id}/checkout      → ОжидаетОплаты
POST /orders/{id}/pay           → Оплачен
POST /orders/{id}/cancel        → 409 Conflict (нельзя отменить оплаченный заказ)

Упражнение: Спроектируйте набор тестов для переходов состояний

Сценарий: Система утверждения документов имеет следующие состояния и переходы:

  • Черновик → Отправить → Ожидает ревью
  • Ожидает ревью → Утвердить → Утверждён
  • Ожидает ревью → Отклонить → Черновик (с комментариями)
  • Ожидает ревью → Запросить изменения → Запрошены изменения
  • Запрошены изменения → Переотправить → Ожидает ревью
  • Утверждён → Опубликовать → Опубликован
  • Опубликован → Архивировать → Архивирован
  • Любое состояние → Удалить → Удалён (только админ)

Задания:

  1. Нарисуйте диаграмму переходов состояний
  2. Постройте таблицу переходов состояний
  3. Перечислите все невалидные переходы
  4. Спроектируйте тест-кейсы для покрытия 0-switch
Подсказка

Есть 7 состояний и 8 валидных переходов (плюс Delete из каждого состояния). Для невалидных переходов подумайте, какие события не должны работать в каждом состоянии — напр., можно ли «Утвердить» черновик без отправки?

Решение

Таблица переходов состояний:

Текущее состояниеСобытиеСледующее состояние
ЧерновикОтправитьОжидает ревью
ЧерновикУдалить (админ)Удалён
Ожидает ревьюУтвердитьУтверждён
Ожидает ревьюОтклонитьЧерновик
Ожидает ревьюЗапросить измененияЗапрошены изменения
Ожидает ревьюУдалить (админ)Удалён
Запрошены измененияПереотправитьОжидает ревью
Запрошены измененияУдалить (админ)Удалён
УтверждёнОпубликоватьОпубликован
УтверждёнУдалить (админ)Удалён
ОпубликованАрхивироватьАрхивирован
ОпубликованУдалить (админ)Удалён
АрхивированУдалить (админ)Удалён

Ключевые невалидные переходы:

СостояниеНевалидное событиеОжидаемый результат
ЧерновикУтвердитьОшибка: сначала нужно отправить
ЧерновикОпубликоватьОшибка: не утверждён
УтверждёнОтправитьОшибка: уже утверждён
АрхивированОпубликоватьОшибка: архивирован
УдалёнЛюбое событиеОшибка: документ удалён

Тест-кейсы 0-switch покрытия: 8 для валидных переходов + 5 для невалидных = 13 тест-кейсов.

Советы профессионала

  • Начинайте с happy path. Сначала постройте основной успешный сценарий, затем добавьте альтернативные и ошибочные пути.
  • Ищите недостающие переходы. Если у состояния нет исходящих переходов, пользователи могут застрять. Если у состояния нет входящих переходов (кроме начального), оно недостижимо.
  • Тестируйте конкурентные события. Что произойдёт, если два события возникнут одновременно? Race conditions в машинах состояний — частый источник дефектов.
  • Используйте машины состояний для автоматизации тестов. Многие тестовые фреймворки поддерживают модели машин состояний для автоматической генерации тестовых последовательностей.
  • Условия-стражи требуют BVA. Если переход имеет условие вроде [попытки < 3], примените анализ граничных значений к условию-стражу.