3

我想在使用 @dataprovider 的 TestNg 中并行运行硒测试。理想情况下,测试是按方法并行的(一个测试=一种方法),而不是浏览器的简单套件并行性。我在某处读到一次可以控制大约 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 产品之间循环)。

设置驱动程序、数据提供程序和测试运行程序以在运行测试中实现最佳并行性的最佳方法是什么?

4

2 回答 2

3

我对 dataProvider 也有同样的经历。就我而言,我使用了 dataProvider 的 (parallel=true) 属性。您的问题有两种解决方案。

  1. 在测试类中使用 dataProvider 并为您的构造函数使用工厂注释。在工厂注解的属性中,使用 dataProvider="Your dataProvider's name"。在 testng.xml 中,使用 parallel=instances 而不是 parallel=methods。

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

  2. 创建一个工厂类并使用 for 循环在工厂方法中实例化您的测试类。(从 0 开始 for 循环。)在测试类中定义一个从工厂类接收参数的构造函数。在这个测试类中定义一个dataProvider,它可以使用在构造函数中接收到的参数(数据点)。定义可以使用该参数或数据点的 BeforeMethod 或 BeforeClass,并且您的测试方法应该具有指向所需数据提供者的“dataProvider”属性。同样,在 testng.xml 中使用 parallel="instances"。

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

于 2013-09-24T05:56:46.017 回答
1

你真的不需要使用工厂。如果我是你,我会在 dataprovider 方法中调用这段代码:

driver = getBrowser(browser);

然后,将驱动程序实例作为 args 的第二列返回给测试方法。这样做允许数据提供者生成浏览器实例。为了改进这一点,您可以改为使用构建器设计模式,以 DriverHelper 类的形式,它可以替换 getBrowser 方法,以在将驱动程序实例传递给测试方法之前生成更具体的驱动程序配置。

注意:请记住,如果您以后想使用 Spring 加载驱动程序,那么这种方法根本不起作用。事实上,您根本无法使用 DataProvider。但是,如果您不使用 Spring,那么我会说这是最优雅的方式。

于 2014-12-30T17:59:37.423 回答