2012-01-19 39 views
1

我一直在使用Selenium Grid对Selenium 2的RemoteWebDriver进行大量的读取。目前我的测试是使用[Test]属性在Test()中生成的。使用数据驱动测试案例与MBUnit/Gallio的并行测试

我有一个TestCriteria类,我充满了信息,然后使用硒的webdriver“页面对象设计模式”作为一种方式“控制”这个数据是如何进入我的测试。

所以,我有一个简单的标准对象,例如:

public class Credentials 
{ 
    public string Username { get; set; } 
    public string Password { get; set; } 
} 

然后用在LoginPage对象信息。现在

public class LoginPage 
{ 
    [FindsByAnnotation] 
    public IWebElement UsernameField { get; set; } 

    [FindsByAnnotation] 
    public IWebelement PasswordField { get; set; } 

    [FindsByAnnotation] 
    public IWebelement SubmitButton { get; set; } 

    public HomePage Login(Credentials cred) 
    { 
     UsernameField.SendKeys(cred.user); 
     // code for login and return new HomePage object 
    } 
} 

,这种类型的结构,我能够创建在我的测试中一些好的方法链一旦我有测试数据,像我的凭据对象,数据需要被填补在其他网页等。

[TestFixture] 
public class TestFixture 
{ 
    private IWebDriver driver; 
    private TestCaseData data; // Which contains a Credentials object etc etc 

    [SetUp] 
    public void SetUp() 
    { 
     data = new TestCaseData() 
     { 
       Credentials = new Credentials() 
       { 
        Username = "username", 
        Password = "password" 
       } 
      // Other test case data objects can be populated here 
     }; 

     driver = new FireFoxDriver(); 
    } 

    [Test] 
    public void Test() 
    { 
      new LoginPage().Login(data.Credentials) 
         .NavigateToSearchPage() 
         .EnterSearchCriteria(data.SearchCritiera) 
      // etc 
    } 

}

这是一切都很好,但是......如果我想从中可以从XML被deserialised序列化对象TESTDATA在这个测试数据加载。

我也有兴趣使用RemoteWebDriver,但我已经使用但是仍然是flappy相比,只使用IWebDriver driver = new FireFoxDriver();,但是忽略这些问题,我真的很想运行一个TESTCASE不止一次......在相同的时间。这给我带来了平行测试的问题。

我知道MBUnit可以处理这是Gallio的一部分,我也研究过PUnit,它是Nunit的扩展,但它还有很长的路要走。所以我决定坚持使用MbUnit。

这使我能够运行带有属性[Parallelizable]的TestFixtures。因此,如果我编译我的项目并将项目dll加载到Gallio TestRunner GUI中,我可以同时运行4个测试用例,这反过来又会打开4个浏览器同时运行每个测试,同时还能够强调网站而所有4个测试正在运行。 (显然这将增加在Selenium Grid上使用Selenium RemoteWebDriver在多台机器上运行数百个浏览器。

有没有人知道我可以加载xml序列化对象集合的方式,GENERATE可以有新的TestFixture对象将[Parallelizable]属性添加到测试夹具的顶部,并使它们在从例如C:\ TestCase目录加载1 - 10个.xml文件后同时运行?

我的想法是让这些全部加载进来,然后让Selenium Grid处理浏览器会话,并使用连接到主硒网格集线器的1 - 5个Selenium节点。

当我找不到允许我生成Test Fixture(其中包括[SetUp][TearDown][Test])以及根据加载的内容将某些测试条件设置为“测试属性”的能力时,我只是难以真正利用Selenium Grid来自TestCase .xml文件。

例如,如果一个TestCase .xml文件有一个失败的元素,那我该如何加载这个.xml文件并在TestFixture的[Test]上设置一个属性,或者映射TestCase。xml运行时对[Test(Description = "")]属性的测试说明。

我已经知道硒的webdriver,页面对象设计模式,硒EventFiringWebDriver功能的截屏的功能。

我如何可以利用几种XML序列化TestCaseData加载已经加载的能力,产生后这些新的TestFixture对象?

理想情况下,我希望每个TestFixture的[SetUp]设置IWebDriver,因为根据TestCase.xml文件将包含的内容,某些URL会有所不同,例如此测试将在UAT环境中运行,Test环境,Pre-Production环境,我需要在测试运行之前设置它。

有没有人有一个基本的例子,它使用Selenium Grid/Selenium WebDriver的这些主要概念,并行运行这些测试夹具以利用运行多个浏览器的Selenium Grid功能。

所以,这是我要寻找一个在伪代码。

public class Main() 
{ 
    // Load Testfixtures 
    List<TestCase> testCases = Deserialise("\\Some\\FolderLocation"); 

    foreach(test in testCases) 
    { 
     // create NEW testFixture, not [Test] 
     // ability to attach parallel TestFixture 
    } 
} 

[Testfixture] 
[Parallelizable] 
public class TestFixture 
{ 

    public TestCase testCase { get; set; } 
    public IWebDriver driver { get; set; } 

    [SetUp] 
    public void SetUp() 
    { 
     if(testCase.Environment == "UAT") 
     { 
      driver = new FireFoxDrive() 
      driver.NavigateTo("http://localhost/uat/Login"); 
     } 

     // What if the testCase.ShouldPass is false? 

     // How can i generate my [Test] with ExpectedException? 

    } 

     [Test] 
     public void Test() 
     { 
      // code here with page object method chaining passing in testCase data objects 
     } 
} 

也许我会以错误的方式讨论这个设计。任何建议请最好的方式来并行化这些?

回答

1

这个怎么样?

public class TestCase 
{ 
    public string Name { get; set; } 
} 

public static class TestCaseFactory 
{ 
    public static IEnumerable<TestCase> TestCases() 
    { 
     yield return new TestCase { Name = "one" }; 
     yield return new TestCase { Name = "two" }; 
    } 
} 

[Factory(typeof(TestCaseFactory), "TestCases"), Parallelizable] 
public class DataDrivenFixture 
{ 
    private readonly TestCase testCase; 

    public DataDrivenFixture(TestCase testCase) 
    { 
     this.testCase = testCase; 
    } 

    [SetUp] 
    public void SetUp() 
    { 
     Console.WriteLine("SetUp " + testCase.Name); 
    } 

    [Test] 
    public void Test() 
    { 
     Console.WriteLine("Test " + testCase.Name); 
    } 
} 
+0

我终于找到了这一个,它的奇妙,我发现几乎与Nunit TestCaseSource一样。谢谢:) +1 –

0

很好的解决方案。 但在并行不同的浏览器中运行测试呢? 如果我在[FixtureSetUp]中初始化IWebDriver,然后浏览器打开并运行测试但出现错误(基本上是NoSuchElement)。

public static IEnumerable<TestCase> TestCases() 
     { 
      yield return new TestCase { Name = "internet explorer" }; 
      yield return new TestCase { Name = "firefox" }; 
     } 

[FixtureSetUp] 
     public void SetUp() 
     { 
      Console.WriteLine("SetUp " + testCase.Name); 
      switch (testCase.Name) 
      { 
       case "internet explorer": 
        driver = new InternetExplorerDriver(); 
        break; 
       case "chrome": 
        driver = new ChromeDriver(); 
        break; 
       case "firefox": 
        driver = new FirefoxDriver(); 
        break; 
      } 
     } 
+0

如果你想并行运行测试,你必须充分利用硒网格。这样selenium网格可以跟踪会话以及它应该发送请求的浏览器。 –

+0

我尝试在Grid上运行,没有它。这并不重要,测试失败与nosuchelement。我认为这是因为Webdriver不是线程安全的。但我不知道如何使WebDriver安全线程或其他方式在不同的浏览器中同时使用它。 – TheX

+0

点是使用RemoteWebDriver,它不需要线程安全的,你不运行相同RemoteWebDriver两次,创建RemoteWebDriver的两个实例,其连接到同一硒电网2服务器。这将为您处理浏览器。 如果您向我展示了更多代码可能更容易理解您遇到的问题。 你看过使用TPL吗?这为您提供了并行执行任务的方法。您可以使用此方法在同一个[Test]中创建两个RemoteWebDriver实例。 http://msdn.microsoft.com/en-us/library/dd537609.aspx –