Что такое тестирование переходов состояний?
Тестирование переходов состояний моделирует систему как конечный автомат (finite state machine) — систему, которая может находиться в одном из ограниченного числа состояний и переходить между ними в ответ на события. Эта техника идеальна для тестирования workflow, процессов и любых систем с различными режимами работы.
Ключевые концепции
- Состояние: Условие, в котором находится система (напр., «Сессия закрыта», «Активно», «Заблокировано»)
- Переход: Перемещение из одного состояния в другое
- Событие: Что-то, вызывающее переход (напр., «ввод правильного пароля»)
- Условие-страж (guard): Условие, которое должно быть истинным для совершения перехода
- Действие: Что-то, происходящее во время перехода (напр., «отправить уведомление»)
Диаграмма переходов состояний
Эта диаграмма показывает систему аутентификации с 4 состояниями и 7 переходами.
Чтение диаграммы
Каждая стрелка представляет переход в формате: Событие [Условие-страж] / Действие
Валидные данные→ Событие, вызывающее переход[попытки < 3]→ Условие-страж, которое должно быть истинным- Целевое состояние — куда указывает стрелка
Когда использовать тестирование переходов состояний
Эта техника эффективна когда:
- Система имеет чётко определённые режимы или статусы (заказ: ожидание → оплачен → отправлен → доставлен)
- Пользовательские workflow имеют множество путей (корзина, процесс оформления)
- Протоколы имеют определённые состояния (TCP-соединения, потоки аутентификации)
- Устройства имеют операционные режимы (ожидание, активный, ошибка)
Построение таблицы переходов состояний
Таблица систематически перечисляет каждую комбинацию состояние-событие:
| Текущее состояние | Событие | Следующее состояние | Действие |
|---|---|---|---|
| СессияЗакрыта | Валидные данные | СессияОткрыта | Создать сессию |
| СессияЗакрыта | Неверные данные (< 3) | СессияЗакрыта | Увеличить счётчик |
| СессияЗакрыта | Неверные данные (= 3) | Приостановлено | Заблокировать аккаунт |
| СессияОткрыта | Выход | СессияЗакрыта | Уничтожить сессию |
| СессияОткрыта | 30 мин неактивности | Заблокировано | Сохранить состояние |
| Заблокировано | Валидные данные | СессияОткрыта | Восстановить состояние |
| Заблокировано | Выход | СессияЗакрыта | Уничтожить сессию |
| Приостановлено | Админ разблокирует | СессияЗакрыта | Сбросить счётчик |
Определение невалидных переходов
Настоящая сила таблицы — в нахождении того, что не должно происходить. Для каждой пары состояние-событие, которой НЕТ в таблице, система должна либо игнорировать событие, либо показать ошибку.
| Текущее состояние | Невалидное событие | Ожидаемый результат |
|---|---|---|
| СессияОткрыта | Валидные данные | Игнорировать (уже авторизован) |
| Приостановлено | Валидные данные | Отклонить (аккаунт приостановлен) |
| Приостановлено | 30 мин неактивности | Игнорировать (нет активной сессии) |
Уровни покрытия
Покрытие 0-switch: Проверить каждый валидный переход хотя бы раз. Минимальное покрытие.
Покрытие 1-switch: Проверить каждую пару последовательных переходов. Обнаруживает дефекты, зависящие от истории системы.
Примеры последовательностей 1-switch:
СессияЗакрыта → СессияОткрыта → Заблокировано
СессияЗакрыта → СессияОткрыта → СессияЗакрыта
Заблокировано → СессияОткрыта → Заблокировано
Продвинутые техники тестирования переходов
Машина состояний заказа в E-Commerce
Реальные машины состояний могут быть сложными. Типичный жизненный цикл заказа:
Из этой диаграммы выведите тест-кейсы для:
- Happy path: Создан → ОжидаетОплаты → Оплачен → Обработка → Отправлен → Доставлен
- Ошибка оплаты: Создан → ОжидаетОплаты → Создан (повтор) → ОжидаетОплаты → Оплачен
- Отмена: Создан → ОжидаетОплаты → Отменён
- Возврат: … → Доставлен → ЗапросВозврата → Возвращён
- Невалидные переходы: Может ли «Доставлен» вернуться в «Обработка»? Не должен.
Покрытие 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 (нельзя отменить оплаченный заказ)
Упражнение: Спроектируйте набор тестов для переходов состояний
Сценарий: Система утверждения документов имеет следующие состояния и переходы:
- Черновик → Отправить → Ожидает ревью
- Ожидает ревью → Утвердить → Утверждён
- Ожидает ревью → Отклонить → Черновик (с комментариями)
- Ожидает ревью → Запросить изменения → Запрошены изменения
- Запрошены изменения → Переотправить → Ожидает ревью
- Утверждён → Опубликовать → Опубликован
- Опубликован → Архивировать → Архивирован
- Любое состояние → Удалить → Удалён (только админ)
Задания:
- Нарисуйте диаграмму переходов состояний
- Постройте таблицу переходов состояний
- Перечислите все невалидные переходы
- Спроектируйте тест-кейсы для покрытия 0-switch
Подсказка
Есть 7 состояний и 8 валидных переходов (плюс Delete из каждого состояния). Для невалидных переходов подумайте, какие события не должны работать в каждом состоянии — напр., можно ли «Утвердить» черновик без отправки?
Решение
Таблица переходов состояний:
| Текущее состояние | Событие | Следующее состояние |
|---|---|---|
| Черновик | Отправить | Ожидает ревью |
| Черновик | Удалить (админ) | Удалён |
| Ожидает ревью | Утвердить | Утверждён |
| Ожидает ревью | Отклонить | Черновик |
| Ожидает ревью | Запросить изменения | Запрошены изменения |
| Ожидает ревью | Удалить (админ) | Удалён |
| Запрошены изменения | Переотправить | Ожидает ревью |
| Запрошены изменения | Удалить (админ) | Удалён |
| Утверждён | Опубликовать | Опубликован |
| Утверждён | Удалить (админ) | Удалён |
| Опубликован | Архивировать | Архивирован |
| Опубликован | Удалить (админ) | Удалён |
| Архивирован | Удалить (админ) | Удалён |
Ключевые невалидные переходы:
| Состояние | Невалидное событие | Ожидаемый результат |
|---|---|---|
| Черновик | Утвердить | Ошибка: сначала нужно отправить |
| Черновик | Опубликовать | Ошибка: не утверждён |
| Утверждён | Отправить | Ошибка: уже утверждён |
| Архивирован | Опубликовать | Ошибка: архивирован |
| Удалён | Любое событие | Ошибка: документ удалён |
Тест-кейсы 0-switch покрытия: 8 для валидных переходов + 5 для невалидных = 13 тест-кейсов.
Советы профессионала
- Начинайте с happy path. Сначала постройте основной успешный сценарий, затем добавьте альтернативные и ошибочные пути.
- Ищите недостающие переходы. Если у состояния нет исходящих переходов, пользователи могут застрять. Если у состояния нет входящих переходов (кроме начального), оно недостижимо.
- Тестируйте конкурентные события. Что произойдёт, если два события возникнут одновременно? Race conditions в машинах состояний — частый источник дефектов.
- Используйте машины состояний для автоматизации тестов. Многие тестовые фреймворки поддерживают модели машин состояний для автоматической генерации тестовых последовательностей.
- Условия-стражи требуют BVA. Если переход имеет условие вроде
[попытки < 3], примените анализ граничных значений к условию-стражу.