使用dataprovider执行并行的TestNG selenium测试时的驱动行为

3
我想在TestNg中并行运行使用@dataprovider的selenium测试。理想情况下,测试应该是按方法并行的(一个测试=一个方法),而不是简单的通过浏览器进行套件并行。我曾经在某个地方读到过,大约可以同时控制5个ChromeDriver实例,所以我认为应该可以做到这一点。稍后,我计划转移到grid2。为了开发,我正在使用IntelliJ Idea测试运行程序,通过右键单击+在XML配置文件上运行。
我在并行运行我的测试时遇到了问题(在grid2和本地运行),因此我创建了一个示例来展示我想要做的事情。以下是我的测试类。
package tests;

import org.openqa.selenium.By;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.interactions.Actions;
import org.testng.annotations.*;
import java.util.concurrent.TimeUnit;
import static org.testng.Assert.assertNotNull;

public class ParallelTest {
    public static final String SEARCH_TERMS = "search-terms";
    private WebDriver driver;

    @BeforeMethod
    @Parameters({"browser"})
    public void beforeMethod(@Optional("chrome") String browser){
        driver = getBrowser(browser);
        driver.manage().deleteAllCookies();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
    }

    private WebDriver getBrowser(String browser) {
        if(browser.equals("chrome")){
            System.setProperty("webdriver.chrome.driver", "webdrivers\\chromedriver.exe");
            return new ChromeDriver();
        }
        return new FirefoxDriver();
    }

    @AfterMethod
    public void afterMethod(){
        driver.quit();
    }

    @Test(description = "Check parallel selenium works.",
          dataProvider = SEARCH_TERMS)
    public void parallelSeleniumTest(String searchTerm){
        driver.get("http://google.com");
        WebElement search = driver.findElement(By.id("gbqfq"));
        new Actions(driver)
                .sendKeys(search, searchTerm)
                .sendKeys(search, Keys.ENTER)
                .perform();
        String firstResult = driver.findElements(By.className("r")).get(0).getText();
        assertNotNull(firstResult);
        System.out.println(firstResult);
    }

    @DataProvider(name = SEARCH_TERMS, parallel = true)
    public Object[][] getSearchTerms(){
        return new Object[][]{
                {"google"},
                {"microsoft"},
                {"facebook"},
                {"amazon"},
                {"apple"},
                {"oracle"},
                {"yahoo"},
                {"jetbrains"},
                {"intellij idea"},
                {"selenium"},
                {"java"},
                {"testng"},
                {"code"}
        };
    }
}

我在我的测试套件中广泛使用本地事件,因此我添加了一些本地事件。

这是TestNg的xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite thread-count="4" name="vfr6-ui-tests" parallel="methods">
    <test name="parallel-test-firefox">
        <parameter name="browser" value="firefox"/>
        <classes>
            <class name="tests.ParallelTest"/>
        </classes>
    </test>
    <test name="parallel-test-chrome">
        <parameter name="browser" value="chrome"/>
        <classes>
            <class name="tests.ParallelTest"/>
        </classes>
    </test>
</suite>

我了解到,每个测试实例化一个驱动程序通常是最易维护的。问题在于Firefox测试以串行方式运行,而Chrome测试则将所有数据点作为测试用例输出,试图打开一堆浏览器实例,结果一切都失败了。我的测试将具有10-25或300-500个数据点(在客户端或客户端x产品之间循环)。
如何设置驱动程序、数据提供程序和测试运行器以实现最佳的测试并发性?
2个回答

3

我也遇到过dataProvider的问题。在我的情况下,我使用了dataProvider的(parallel=true)属性。有两种解决方法:

  1. 在测试类中使用dataProvider,并使用构造函数的factory注释。在factory注释的属性中,使用dataProvider="你的dataProvider名称"。在testng.xml中,使用parallel=instances而不是parallel=methods。

    以上方法的缺点是当你获得报告时;可能是maven-surefire、testng Eclipse报告或reportNG报告,你不会看到事先传递的参数。为了克服这个问题,可以使用以下方法。

  2. 创建一个工厂类,在工厂方法中使用for循环实例化你的测试类。(从0开始循环。)在测试类中定义一个构造函数,该构造函数从工厂类接收一个参数。在这个测试类中定义一个dataProvider,它可以使用在构造函数中接收的参数(data-point)。定义一个BeforeMethod或BeforeClass,它可以使用该参数或数据点,你的测试方法应该具有指向所需dataProvider的"dataProvider"属性。再次,在testng.xml中使用parallel="instances"。

    此外,使用try/catch块来实例化driver对象和关闭浏览器。这将帮助你避免由于setUp或tearDown方法失败而导致的跳过。


回复很好,听起来相当合理。我早就转回了应用程序所编写的语言(C#)。希望其他人也会发现这很有用! - craastad

1

您其实不需要使用工厂模式。 如果我是您,我会在数据提供者方法中调用此代码:

driver = getBrowser(browser);

然后,将驱动程序实例作为测试方法的第二列参数返回。以这种方式做可以让dataprovider生成浏览器实例。要改进它,你可以使用生成器设计模式来创建一个DriverHelper类,用于在将驱动程序实例传递到测试方法之前生成更具体的驱动程序配置。

注意:请记住,如果您将来想要使用Spring来加载驱动程序,则这种方法将根本无法使用。事实上,您将无法使用DataProvider。但是,如果您不使用Spring,那么我认为这是最优雅的方式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接