2017-02-28 56 views
1

TLDR - 编写specFlow场景的最佳方法是相互连接并共享数据?例如场景A - 创建一个用户,然后使用该用户登录场景B(登录将需要在创建用户场景中指定的用户名和密码)。如何编写遵循对方并共享数据的specflow场景?

大家好,

我得到自己在一点咸菜在试图找出最好的方式来写一个网站上一个典型的用户注册形式的情况下,随后的场景来测试登录。

我试图创建一个单独的类的实例来存储我的登记表的所有细节,当它达到这一步(认为这是上下文注射液)。例如

[Binding] 
public class AdmissionsPortalFeaturesSteps : BaseStep 
{ 
    private UserDetails userDetails; 

我有如下情形的问题,需要在前面的场景中生成的密码,我不能喜欢的东西来访问它...

userDetails.Password 

这是什么我有,我想从第一个场景到第二遍密码值目前没有工作......(注意如果该字段设置为“随机”随机在我的C#代码生成值)

Scenario: Create a new user via the Admissions Portal 
    Given I will navigate to the Admissions Portal login page 
    When I click the Create an Account link 
    Then I will be on the ontrack: prospect - Register page 
    Given I have entered the following values on the registration page 
    | fieldName     | value | 
    | Title      | random | 
    | Firstname     | random | 
    | Middlename     | random | 
    | Surname     | random | 
    | DOB      | random | 
    | Gender      | random | 
    | EmailAddress    | random | 
    | MobileNumber    | 0  | 
    | Password     | random | 
    | SecurityQuestion   | random | 
    | SecurityAnswer    | random | 
    And I click on the Register button 
    Then I will be on the Login page 
     And I will get a popup confirming my registration details 
    Then I close the browser window 

Scenario: I am able to login to the Admissions Portal with a newly created user 
    Given I will navigate to the Admissions Portal login page 
     And I enter a username and password and click to login 
    Then I will be on the ontrack: prospect - Home page 
    Then I close the browser window 

目前,我看到,我有以下选择

  1. 扩展第一个场景,包括登录,以及和共享使用上下文注入步骤之间的数据。
  2. 在我的登录步骤中重复包含表格的注册步骤。
  3. 写一个新的更短的步骤,生成我的用户没有表,并在这两种情况下使用这个(我可能要稍后指定与表单中设置特定值的情况,但承认,我可能会更好抛弃它)。

或者别的东西,我还没有想过......

非常感谢,

回答

2

我试图确保我specflow方案不共享任何数据了,如果我能明确在每次测试之间尽可能重新生成整个数据库模式。

这可确保只有您已经安排在测试数据在数据库

所以我想创建一个单独的定步骤,要么通过所有的步骤来创建一个帐户运行(你可以调用这些步骤以编程方式)或有一个单独的给定步骤,短路所有种子的数据库与您需要的信息。

我也注意到你明确关闭浏览器在测试中。我为启动/停止Selenium的Web创建了BeforeScenario/AfterScenario标签。所以你的测试只需要测试实际的功能,而不是Selenium的启动/停止。

public class SeleniumController 
{ 
    public static readonly SeleniumController Instance = new SeleniumController(); 
    public static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(10); 

    public IWebDriver Selenium { get; private set; } 

    private void Trace(string message) { Console.WriteLine("-> {0}", message); } 

    public void Start() 
    { 
     if (Selenium != null) 
      return; 

     string appUrl = ConfigurationManager.AppSettings["AppUrl"]; 

     var options = new ChromeOptions(); 
     options.AddArgument("test-type"); 
     Selenium = new ChromeDriver(options); 
     Selenium.Manage().Timeouts().ImplicitlyWait(DefaultTimeout); 

     Trace("Selenium started"); 
    } 

    public void Stop() 
    { 
     if (Selenium == null) return; 

     try 
     { 
      Selenium.Quit(); 
      Selenium.Dispose(); 
     } 
     catch (Exception ex) 
     { 
      Debug.WriteLine(ex, "Selenium stop error"); 
     } 
     Selenium = null; 
     Trace("Selenium stopped"); 
    } 
} 

场景标签

public static class SeleniumSupport 
{ 
    private static bool ReuseWebSession 
    { 
     get { return ConfigurationManager.AppSettings["ReuseWebSession"] == "true"; } 
    } 

    [BeforeScenario("web")] 
    public static void BeforeWebScenario() 
    { 
     SeleniumController.Instance.Start(); 
    } 

    [AfterScenario("web")] 
    public static void AfterWebScenario() 
    { 
     if (!ReuseWebSession) 
      SeleniumController.Instance.Stop(); 
    } 
} 

抽象步骤的基类来访问硒的webdriver

public abstract class SeleniumStepsBase 
{ 
    protected IWebDriver Selenium { get { return SeleniumController.Instance.Selenium; } } 
} 
+0

感谢您的支持。是的,这听起来像个好主意。需要整理一下,所以会在适当的时候添加Before和After。 – Konzy262

+0

我将为Selenium管理添加一些支持代码。 – Fran

0

我用FeatureContext.Current或ScenarioContext.Current来存储我通过情景或功能之间的信息。 FeatureContext是Specflow全球词典,可以在任何地方访问。 Specflow FeatureContext

FeatureContext.Current["username"] = "someUsername"; 

或者

ScenarioContext.Current["username"] = "someUsername"; 
+0

我会避免这种共享数据的方法,因为如果没有将上下文注入到步骤类中,它将无法在并行场景中工作,并且我认为它将在某些未来版本中被弃用 –

2

你使用一个场景来设置数据的另一种情况的目的是有缺陷的,注定要失败恕我直言。

一个场景应该是完全自包含的,并且能够独立运行,而不依赖于其他场景。 Specflow是一个单元测试生成框架,但测试运行者可以决定运行测试的顺序。如果你有像你所说的那样的依赖关系,那么如果它们不按顺序运行会发生什么?如果他们平行运行会发生什么?试图使这项工作将游泳上游,不要这样做。

取而代之的是让每个场景自成一体。如果您有很多重复设置,请将其置于后台步骤中,或者创建一个调用所有其他步骤来执行设置的步骤,或者只创建一个只需执行所需设置的步骤,然后使用标准方式在步骤之间共享数据以管理您生成的密码等。

+1

谢谢。看了更多一点,你完全正确。我试图在一个场景中设置我的数据,然后在所有其他场景中使用这些数据。正如你指出的那样,如果测试失败了,他们会倒下。我决定保留我的特定注册用户场景,然后有一个较短的版本'鉴于我创建了一个用户',它调用用户场景中注册的所有步骤。然后我使用它作为我的其他场景的设置。测试执行时间更长,因为我每次都创建一个用户,但现在测试完全独立。 – Konzy262

-1

我们尝试独立编写每个场景/脚本。如果确实需要通过,我们将脚本1创建的数据写入Excel,稍后再由另一个脚本2检索。 excel数据仅对一次运行/构建有效。当测试再次运行时,Excel数据将被清除,脚本1必须创建数据,脚本2必须读取并使用它。 我们使用MS Excel Interop Excel dll