SpecFlow – zdarzenia

Kiedyś w jednym z komentarzu ktoś zasugerował, aby opisać również zdarzenia (hooks) w specflow. Wszystko można znaleźć w dokumentacji, ale również preferuję kilka zwięzłych przykładów niż suchy opis.

Tak jak w nUnit czy jakimkolwiek innym framework’u, możemy definiować co powinno wykonać się przed lub po testach. Atrybutami BeforeTestRun oraz AfterTestRun dekorujemy metody, które mają się wykonać przed i po wszystkich testach:

[Binding] public class Hooks { [BeforeTestRun] public static void BeforeTestRun() { } [AfterTestRun] public static void AfterTestRun() { } }

Atrybut Binding jest niezbędny, gdy definiujemy zdarzenia w osobnej klasie. W przypadku BeforeTestRun ma to sens, ponieważ nie są one specyficzne dla żadnego zestawu testów. Jeśli mamy 10 scenariuszy, BeforeTestRun oraz AfterTestRun wykonają się tylko raz – przed i po wykonaniu wszystkich testów (a nie po każdym scenariuszu osobno). Metoda powinna być również statyczna.

Jeśli mamy logikę, która powinna być wykonana dla każdego scenariusza osobno, wtedy korzystamy z BeforeScenario oraz AfterScenario:

[Binding] public class Hooks { [BeforeFeature] public static void BeforeFeature() { } [AfterFeature()] public static void AfterFeature() { } }

Dla 10 scenariuszy,  metody zatem zostaną wykonane również po 10 razy. Z poprzedniego posta, pamiętamy, że mamy do dyspozycji jeszcze tagi:

@myFirstTag Feature: EditPost Jakis opis tutaj... Scenario: Edit a post Given I have logged into CMS When I press the edit a post button Then article should be updated.

W takim scenariuszu, możliwe jest powiązanie hook’a ze specyficznym tagiem:

[BeforeFeature("myFirstTag")] public static void BeforeFeature() { }

Parametr to lista tagów więc można stworzyć jeden hook dla kilku scenariuszy jednocześnie.

Before i After to aliasy dla BeforeScenario oraz AfterScenario. Moim zdaniem jednak, jeśli ktoś nie jest obeznany z SpecFlow, wtedy nazwa Before może być mało dokładna. Tak czy inaczej, odpowiednik powyższego kodu to:

[Binding] public class Hooks { [Before("myFirstTag")] public static void BeforeFeature() { } [After()] public static void AfterFeature() { } }

Jeśli chcemy wykonać kod pomiędzy Given, When, Then wtedy:

[Binding] public class Hooks { [BeforeScenarioBlock] public static void BeforeScenarioBlock() { } [AfterScenarioBlock] public static void AfterScenarioBlock() { } }

Atrybuty również wspierają tagi. Nazwa Block może być trochę myląca, ale chodzi tutaj, jak wspomniałem o GWT.

Jeśli potrzebujemy bardziej szczegółowe zdarzenia, możemy:

[Binding] public class Hooks { [BeforeStep] public static void BeforeStep() { } [AfterStep] public static void AfterStep() { } }

Pozostaje wyjaśnić czym różni się krok od bloku.  Załóżmy, że mamy zaprezentowany wcześniej test:

@myFirstTag Feature: EditPost Jakis opis tutaj... Scenario: Edit a post Given I have logged into CMS When I press the edit a post button Then article should be updated.

W tym przypadku, blok i krok stanowią to samo i można to byłoby rozdzielić w następujący sposób:

[Blok 1, Krok 1] Given I have logged into CMS

[Blok 2, Krok 2] When I press the edit a post button

[Blok 3, Krok 3] Then article should be updated.

Różnica jest, gdy mamy bloki złożone z And, tzn.:

Feature: EditPost ... Scenario: Edit a post Given I have logged into CMS And I have enough permissions When I press the edit a post button Then article should be updated and afafa

Given składa się z dwóch kroków, zatem można byłoby to rozpisać:

[Blok 1, Krok 1] Given I have logged into CMS

[Krok 2] And I have enough permissions

[Blok 2, Krok 3] When I press the edit a post button

[Blok 3, Krok 4] Then article should be updated and afafa   

Leave a Reply

Your email address will not be published.