В Specflow мога ли да стартирам един тест като стъпка от друг?

TL;DR; Как мога да създам тест на specflow, който извиква друг тест като първа стъпка?

Given I already have one specflow test
And I want to run another test that goes deeper than the first test  
Then I create a second test that runs the first test as its first step
And I add additional steps to test the deeper functionality

Съжалявам, има малко специфичен хумор.

например имам тест, който вече създава продажба:

Given I want to create a sales order
And I open the sales order page
And I click the add new order button
Then a new sales order is created

И искам да имам друг тест, който тества добавянето на линия за продажби

И още един тест, който тества завършването на продажбата

И още един тест, който отменя продажбата

И така нататък

Всички тези тестове ще започнат със същите първи четири стъпки като простия тест, който нарушава принципа DRY. И така, как мога да го направя така, че първата стъпка от втория тест да изпълни само първия тест? напр. нещо като:

Given I have run the create sales order test  // right here it just runs the first test
And I add a sales order line
Then the order total is updated

Ако всеки тест започва с едни и същи първи четири реда и по-късно осъзная, че трябва да променя простия тест за създаване на продажба, тогава ще трябва да отида и да намеря и поправя навсякъде другаде, което повтаря тези четири реда.

РЕДАКТИРАНЕ: Имайте предвид, че това също трябва да може да работи във всички функции. например простият тест по-горе е дефиниран в функцията за продажби. Но също така ще имам функция за кредити и това ще изисква създаване на продажба всеки път, за да мога да я кредитирам:

Given I want to credit a sale
And I run the create sales order test
And I complete the the sale
And I click the credit button
Then the sale is credited

person JK.    schedule 17.03.2015    source източник
comment
Създаването на вашата Given I have run the create sales order test стъпка, която изпълнява трите предишни метода на Given стъпки, не работи ли? Или искате друг начин? Съмнявам се, че искате да повторите частта Assert в следващите си тестове.   -  person Pierre-Luc Pineault    schedule 18.03.2015
comment
Нямам нищо против, че ще трябва да повтори твърденията, които ще съществуват в първия тест. Искам да мога да го стартирам, без да се налага да пиша същите 4 стъпки в много различни тестове.   -  person JK.    schedule 18.03.2015
comment
да, но защо не създадете новия Given като вашата част "нещо като", която извиква трите предишни Given ръчно? Също така отговаря на сценария във вашата редакция, тъй като можете да използвате повторно вашата I have run the create sales order test стъпка, където искате. Вие бяхте там 99% във вашия въпрос.   -  person Pierre-Luc Pineault    schedule 18.03.2015
comment
@Pierre-LucPineault Мисля, че ОП не е наясно с това като възможност и това е, което той иска   -  person Sam Holder    schedule 18.03.2015


Отговори (4)


Както вече беше отбелязано, можете да използвате фон за това (и това вероятно е най-добрият вариант в повечето ситуации), но можете също да създадете стъпка, която извиква другите стъпки.

[Binding]
public class MySteps: Steps //Inheriting this base class is vital or the methods used below won't be available
{
    [Given("I have created an order")]
    public void CreateOrder()
    {
         Given("I want to create a sales order");
         Given("I open the sales order page");
         Given("I click the add new order button");
         Then("a new sales order is created");
    }
}

които след това можете да използвате във вашия сценарий:

Scenario: I add another sale
    Given I have created an order
    When I add a sales order line
    Then the order total is updated

Това има предимството, че тази съставна стъпка може да се използва навсякъде в сценария, а не само като отправна точка. След това тази стъпка може да се използва повторно в множество функции, ако имате нужда

person Sam Holder    schedule 17.03.2015
comment
Благодаря, всъщност е доста близо. Въпреки това все още искам първият тест да има действително записани стъпки във файла с функции, така че пак ще има известно дублиране (но само 2 пъти вместо n пъти). - person JK.; 18.03.2015
comment
Това е добре. Можете да използвате стъпките, ако желаете, или можете да ги групирате заедно с „съставна“ стъпка, от която се нуждаете. Той дава най-доброто от двете произведения - person Sam Holder; 18.03.2015
comment
Няколко неща, за които трябва да внимавате: 1. трябва да използвате правилното Given(...) When(...) Then(...) или And(...), за да съответства на вашата дефиниция на стъпка и 2. ако използвате И след стъпката, тогава ще наследи това, което последно сте използвали в кода, вместо това, което последно сте използвали във файла с функции. - person Steve; 18.07.2016
comment
Този бъг трябва да бъде коригиран в следващото издание @steve - person Sam Holder; 18.07.2016
comment
@SamHolder Мислех, че е функция :) - person Steve; 18.07.2016
comment
Виждам само няколко проблема с това, 1) ако промените основния сценарий, трябва да промените дефиницията на стъпка CreateOrder, за да съответства на това, което е податливо на потребителска грешка 2) трудно е да се параметризират данните, използвани от основния сценарий. Има ли някакъв начин за автоматично генериране на дефиницията на стъпка за I have created an order, така че да съответства на дефиницията на сценария? - person MikeW; 07.12.2016
comment
Това не е добър вариант. Първо, той свързва извикването на метода динамично по време на изпълнение, така че ако актуализирате дефиницията на стъпката и забравите за това място, то дори няма да се провали, просто ще се опита да извика метода и тихо ще го пропусне, ако не може да намери метод на съвпадение. Това е много досадно, когато трябва да отстранявате грешки. - person metabuddy; 01.06.2018

Използвайте фон:

Background:
    Given I want to create a sales order
    And I open the sales order page
    And I click the add new order button
    Then a new sales order is created

Scenario: I add another sale
    When I add a sales order line
    Then the order total is updated

Scenario: I add cancel a sale
    When I cancel a sale
    Then the order total is updated to 0

etc.
person RagtimeWilly    schedule 17.03.2015
comment
Това изглежда добре, но ще работи само в рамките на една функция, нали? Има ли някакъв начин за повторно използване на теста в множество функции? Ще актуализирам въпроса. - person JK.; 18.03.2015
comment
Можете да използвате [BeforeTestRun] или [BeforeScenario], но тогава ще се прилага за всеки сценарий. Не съм сигурен дали това е, което искаш? - person RagtimeWilly; 18.03.2015
comment
Не, ще бъде само за конкретни свързани тестове. Тестове, които започват по същия начин, но след това продължават, за да тестват нещо по-нататък. - person JK.; 18.03.2015

Не е необходимо да изпълнявате действителни стъпки, за да създадете поръчка за продажба. Просто внедрете дефиниция на стъпка, която прави това вместо вас като едноредова.

Първо, измисленият SalesOrder клас:

public class SalesOrder
{
    public double Amount { get; set; }
    public string Description { get; set; }
}

След това дефинициите на стъпките

using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;

[Binding]
public class SalesOrderSteps
{
    [Given("I have already created a Sales Order")]
    public void GivenIHaveAlreadyCreatedASalesOrder()
    {
        var order = new SalesOrder()
        {
            // .. set default properties
        };

        // Save to scenario context so subsequent steps can access it
        ScenarioContext.Current.Set<SalesOrder>(order);

        using (var db = new DatabaseContext())
        {
            db.SalesOrders.Add(order);
            db.SaveChanges();
        }
    }

    [Given("I have already created a Sales Order with the following attributes:")]
    public void GivenIHaveAlreadyCreatedASalesOrderWithTheFollowingAttributes(Table table)
    {
        var order = table.CreateInstance<SalesOrder>();

        // Save to scenario context so subsequent steps can access it
        ScenarioContext.Current.Set<SalesOrder>(order);

        using (var db = new DatabaseContext())
        {
            db.SalesOrders.Add(order);
            db.SaveChanges();
        }
    }
}

Сега можете да създавате поръчки за продажба като едноредови и по избор да включвате някои персонализирани атрибути:

Scenario: Something
    Given I have already created a Sales Order

Scenario: Something else
    Given I have already created a Sales Order with the following attributes:
        | Field       | Value             |
        | Amount      | 25.99             |
        | Description | Just a test order |

Ако трябва да получите достъп до този SalesOrder обект в други дефиниции на стъпка, без да го търсите в базата данни, използвайте ScenarioContext.Current.Get<SalesOrder>(), за да извлечете този обект от контекста на сценария.

person Greg Burghardt    schedule 19.03.2015

Ако разбирам правилно въпроса, искате да извикате други сценарии в различни файлове с функции.

  1. Можете да се справите с това, като създадете стъпка, която ще извика стъпките в сценария (основно вложени стъпки като приетия отговор по-горе).
  2. Добавете създадената стъпка към фона

or

  1. Създайте функция, която да извиква стъпките в сценария.
  2. Добавете етикет @create_sale_order към сценариите, които се нуждаят от поръчка за продажба като предварително условие.
  3. Приложете кука преди сценарий за етикета @create_sale_order и извикайте функцията, създадена на стъпка 1.
person Navin    schedule 16.08.2017