9 ноября 2010 г.

State-Transition Testing

До этого мы разобрали 3 техники тест дизайна:
 * Decision Table Testing
 * Boundary Value Testing
 * Equivalence Class Testing

Теперь пришел черед 4ой техники - State-Transition testing.

Вступление

State-Transition testing, как и decision tables testing, отличный инструмент для фиксирования требований и описания дизайна приложения. В отличии от Decision tables testing, которые описывают конкретное состояние приложения, State-Transition testing описывают как эти состояния приложения могут меняться. Диаграммы определяют все события, которые возникают во время работы приложения, и как приложение реагирует на эти события.

Подход

Использование техники State-Transition testing легче объяснять сразу в работе, на примерах. Разберем 2 вида визуального представления этой техники:
 * State-Transition Diagrams (диаграмы)
 * State-Transition Tables (таблицы)

State-Transition Diagrams

Разберем пример резервации авиабилетов. Работает она следующим образом.

Сначала, мы как клиенты, предоставляем авиакомпании информацию для резервации - место отправления, место прибытия, дату и время отправления. Служащий авиакомпании служит интерфейсом между нами и системой резервации авиабилетов, и использует предоставленную нами информацию для создания резервации. После этого наша резервация находиться в состоянии "Made" (сделана). Вдобавок, после создания резервации, система резервации, запускает таймер. Если таймер выходит, а зарезервированный билет не оплачен - система отменяет резервацию.
В виде State-Transition diagrams это будет выглядеть так:




Круг представляет собой состояние системы резервации авиабилетов, в нашем случае это "Made" состояние. Стрелка показывает переход в состояние "Made". Описание под стрелкой ("giveInfo") это событие исходящие извне системы. Команда, в описании под стрелкой (после "/"), говорит нам, что система сделала какое то действие в ответ на событие, в нашем случае это запуск таймера. Черная точка указывает на начало/вход диаграммы.





Далее. Если таймер не истекает и мы оплатили зарезервированный билет, то система приобретает состояние "Paid" (оплаченный). Это показано стрелкой "payMoney" (заплатить деньги) и переходом из состояния "Made" в состояние "Paid".

Перед тем как продолжим стоит определиться с понятиями:

 * Состояние (state)(представленное в виде круга на диаграмме) - это состояние приложения, в котором оно ожидает 1 или более событий. Состояние помнит входные данные полученные до этого и показывает как приложение будет реагировать на полученные события. События могут вызывать смену состояния и/или инициировать действия.
 * Переход (transition) (представленное в виде стрелки на диаграмме) - представляет переход одного состояния в другое, происходящий по событию.
 * Событие (event) (представленное ярлыком над стрелкой) - событие это что то, что заставляет приложение поменять свое состояние. Cобытия могут поступать извне приложения, поступающие через интерфейс приложения. Так же само приложение может генерировать события, например как событие "истек таймер". Когда происходит событие приложение может поменять состояние или остаться в том же состоянии и/или выполнить действие. События могут иметь параметры, например событие "payMoney" может иметь параметры "Cash", "Check", "Debit Card", или "Credit Card".
 * Действие (action) (представлено после "/" в ярлыке над преходом) - это действие инициированное сменой состояния. Это может быть "напечатать билет", "показать на экране" и др. Обычно действия создают что то, что является выходными/возвращаемыми данными системы. Действия возникают при переходах, сами по себе состояния пассивны.
 * Точка входа показывается на диаграмме как черная точка.
 * Точка выхода показывается на диаграмме как мишень.

Вернемся к нашей диаграмме резервации.

Из состояния "Paid" должен быть переход в состояние "Ticketed" (обилечен), когда билет будет напечатан и передан нам в руки. Обратите внимание, что при переходе в состояние "Ticketed", авиабилет (Ticket) является входными данными состояния.



Из состояния "Ticketed" мы переходим в состояние "Used" (использованный), когда отдаем свой билет персоналу аэропорта, при посадке в самолет.



После какого то действия(в этот раз не указанного на диаграмме) путь диаграммы заканчивается символом мишени.



Но эта диаграмма показывает еще не все возможные состояния и переходы в жизненном цикле резервации. Начнем дополнять.

Если резервация не оплачена по истечению таймера, то она отменяется как не оплаченная.



Иногда клиенты отменяют заказы из состояния "Made". На это дело нам нужно еще 1 состояние "Cancelled By Customer".



Так же, клиент может отменить резервацию на состоянии "Paid". В этом случае состояние тоже становиться "Cancelled By Customer" и стоимость билета клиенту возмещают.



Отменить резервацию можно и с состояния "Ticketed". В этом случае состояние опять становиться "Cancelled By Customer" и авиакомпания возмещает стоимость билета клиенту. Но! Компания возместит стоимость билета только тогда, когда клиент вернет билет. Этот случай представляет еще один не описанный элемент диаграмм - квадратные скобки " [ ] ", которые представляют условие к переходу. Переход в состояние в этом случае случится только если условие (то что в " [ ] ") =  true.



Диаграмма все еще не закончена, ибо нет перехода в точку выхода из "Cancelled" состояний, но для примера этой диаграммы достаточно. К слову, каждое состояние диаграммы можно подробней описать с помошью Decision Table.

State-Transition Tables

State-Transition Tables имеет не такой наглядный вид, зато более полный и систематизированный. State-transition tables состоит из 4ех столбцов - Текущее состояние (Current State), Событие (Event), Действие (Action) и Следующее состояние (next state).

Опишем уже известный нам процесс резервации авиабилетов с помощью State-Transition Table:

Текущее состояниеСобытиеДействиеСледующее состояние
null giveInfostartPayTimerMade
null payMoney--null
nullprint--null
nullgiveTicket--null
nullcancel--null
nullPayTimerExpires--null

MadegiveInfo--Made
MadepayMoney--Paid
Madeprint--Made
MadegiveTicket--Made
Madecancel--Can-Cust
MadePayTimerExpires --Can-NonPay

PaidgiveInfo--Paid
PaidpayMoney--Paid
Paid print TicketTicketed
Paid giveTicket-- Paid
Paidcancel RefundCan-Cust
PaidPayTimerExpires--Paid

TicketedgiveInfo--Ticketed
TicketedpayMoney--Ticketed
Ticketedprint--Ticketed
TicketedgiveTicket--Used
TicketedcancelRefundCan-Cust
TicketedPayTimerExpires --Ticketed

UsedgiveInfo--Used
Used payMoney-- Used
Used print --Used
Used giveTicket--Used
Used cancel--Used
UsedPayTimerExpires--Used

Can-NonPaygiveInfo--Can-NonPay
Can-NonPaypayMoney--Can-NonPay
Can-NonPayprint--Can-NonPay
Can-NonPaygiveTicket--Can-NonPay
Can-NonPaycancel--Can-NonPay
Can-NonPayPayTimerExpires--Can-NonPay

Can-Custgivelnfo--Can-Cust
Can-CustpayMoney--Can-Cust
Can-Custprint-- Can-Cust
Can-CustgiveTicket--Can-Cust
Can-Custcancel--Can-Cust
Can-CustPayTimerExpires--Can-Cust

Преимущество State-Transition Tables в том, что они определяют все возможные State-Transition варианты, а не только валидные. Поэтому State-Transition Tables часто приводят к нахождению не определенных, не документированных State-Transition комбинаций, которые лучше находить перед написанием кода.

Создание тест кейсов

State-Transition Diagrams могут быть легко использованы для создания тест кейсов. Необходимо создать набор тест-кейсов, который должен пройти по всем переходам хотя бы раз.



Из State-Transition Tables тоже достаточно легко делать тест кейсы. Стоит пройтись по всем валидным комбинациям (если есть время или не позволяют рискиможно пройтись и по всем невалидным комбинациям). В таблице отмечены все валидные комбинации жирным:

Текущее состояниеСобытиеДействиеСледующее состояние
null giveInfostartPayTimerMade
null payMoney--null
nullprint--null
nullgiveTicket--null
nullcancel--null
nullPayTimerExpires--null

MadegiveInfo--Made
MadepayMoney--Paid
Madeprint--Made
MadegiveTicket--Made
Madecancel--Can-Cust
MadePayTimerExpires --Can-NonPay

PaidgiveInfo--Paid
PaidpayMoney--Paid
Paid print TicketTicketed
Paid giveTicket-- Paid
Paidcancel RefundCan-Cust
PaidPayTimerExpires--Paid

TicketedgiveInfo--Ticketed
TicketedpayMoney--Ticketed
Ticketedprint--Ticketed
TicketedgiveTicket--Used
TicketedcancelRefundCan-Cust
TicketedPayTimerExpires --Ticketed

UsedgiveInfo--Used
Used payMoney-- Used
Used print --Used
Used giveTicket--Used
Used cancel--Used
UsedPayTimerExpires--Used

Can-NonPaygiveInfo--Can-NonPay
Can-NonPaypayMoney--Can-NonPay
Can-NonPayprint--Can-NonPay
Can-NonPaygiveTicket--Can-NonPay
Can-NonPaycancel--Can-NonPay
Can-NonPayPayTimerExpires--Can-NonPay

Can-Custgivelnfo--Can-Cust
Can-CustpayMoney--Can-Cust
Can-Custprint-- Can-Cust
Can-CustgiveTicket--Can-Cust
Can-Custcancel--Can-Cust
Can-CustPayTimerExpires--Can-Cust

Ну вот и всё. Надеюсь получилось понятно описать суть техники.

Этот пост является вольным переводом Chapter 7 из книги "A Practitioner'S Guide To Software Test Design" by Lee Copeland.

19 комментариев:

  1. Предлагаю еще оставить ссылку на первоисточник!!!

    А именно на книгу "A practitioner's Guid to Software Test Design" Lee Copeland

    А то как получается не очень честно...

    ОтветитьУдалить
  2. В первом посте, в блоге, был указан ресурс:)

    http://w1zle.blogspot.com/2010/11/blog-post.html

    Сергей.

    ОтветитьУдалить
  3. Алексей, считаете в каждом посте стоит ссылку на автора давать?

    ОтветитьУдалить
  4. мне кажется ссылку нужно давать в каждом посте, потому что я например не видел предыдущего поста.

    Спасибо, полезный материал :)

    ОтветитьУдалить
  5. Без проблем. Добавил ссылку на книгу в каждый пост.

    ОтветитьУдалить
  6. Книга действительно стоящая. Молодец, что переводишь!

    ОтветитьУдалить
  7. Спасибо за перевод, очень полезный блог)

    ОтветитьУдалить
  8. Могли бы вы уточнить разницу между итоговыми тест-кейсами, полученными на основе диаграмм и на основе таблиц? (Извините, если запутаюсь с терминологией - я только в начале пути тестировщика :)

    Я так понял, что на основе диаграмм мы получаем по-сути, Test script - тестовый сценарий, где результат выполнения предыдущего теста является предварительным условием для следующего.

    А на основе таблиц - мы получили отдельные тесты, но в которых нам придется беспокоиться каждый раз об исходном состоянии системы. Или их потом нужно разворачивать в цепочки, аналогичные диаграммам?

    Как это выглядит практически?

    ОтветитьУдалить
  9. Этот комментарий был удален автором.

    ОтветитьУдалить
  10. Как вы будете создавать тест кейсы - это уже ваш выбор, техника тут вам не диктует.

    Диаграммы отличаются от таблиц только формой представления информации.

    В случае диаграмм или таблиц вам главное тест кейсами покрыть все возможные пути смены состояний - будет это покрыто цепочками тест кейсов или отдельными тест кейсами не суть важно, делайте как удобно или как считаете нужным. Можете покрыть частично цепочками, частично отдельными тест кейсами, если хотите :)

    Но если честно, то эту технику чаще используют для описания логики системы на абстрактном уровне, настолько абстрактном, что о создании тест кейсов речь пока не идёт, но разбить функциональные области системы можно достаточно просто и наглядно, а дальше от этого плясать.

    А что б сложную бизнес логику детализировали диаграммами или таблицами настолько, что б можно было с них прям тест кейсы писать, я пока не встречал, хотя теоретически это возможно :)

    ОтветитьУдалить
  11. Спасибо за перевод! Очень полезная информация, и почему -то незаслуженно забыта. Даже странно что так мало внимания на всяких тренингах и конференциях уделяют внимания базовым техникам тест дизайна при том что больше половины тестировщиков уверен не знают чего то более классов эквивалентности и граничных значений. У меня даже знакомый тимлид есть, который не знал даже про эквивалентные классы. Вообщем спасибо, весьма полезна инфа, при грамотном подходе пылиться не будет.

    ОтветитьУдалить
  12. Спасибо! На собесах спрашивают.

    ОтветитьУдалить
  13. Скажу, очевидно, то же что и все: спасибо, информация очень полезная! :)

    ОтветитьУдалить
  14. Павел, огромное спасибо очень полезный материал

    ОтветитьУдалить
  15. Спасибо большое за полезный материал! Очень жаль, что вы больше не ведете свой блог(

    ОтветитьУдалить
  16. Большое спасибо за доступно изложенный материал, очень полезный и практически применяемый на этапе работы с требованиями! И поддержу предыдущего комментатора призывом к Паше - продолжить сие отличное дело, ведение блога и раскрытие интересных и очень нужных тем.

    ОтветитьУдалить