因此,基本上,我正在尝试实现使用JUnit并行运行的Selenium测试。
为此,我找到了这个JUnit运行器。它真的很好,我非常喜欢。
但是,我在处理WebDriver实例时遇到问题。
在@Test
执行方法之前,应为每个类创建一次每个WebDriver元素。
逻辑上,我可以为此使用类构造函数。实际上,这确实是我测试的要求,因为我需要利用,@Parameters
以便可以相应地创建WebDriver实例(Chrome,FF,IE
…)。
问题是我希望在 类* 完成后而不是在 每种 方法
完成后清除(driver.quit()
)WebDriver实例。但是我不能使用,因为我不能使WebDriver成为静态成员,因为每个类实例必须使用自己的实例(否则测试将尝试在同一浏览器中运行)。
@Test
*@AfterClass
我发现了一个可能的建议在这里通过 Mrunal Gosar
。按照他的建议,我将WebDriver改为了ADriver static ThreadLocal<WebDriver>
,然后我在每个构造函数中使用创建它的实例
// in the classes constructor
driver = new ThreadLocal<WebDriver>() {
@Override
protected WebDriver initialValue() {
return new FirefoxDriver(); /
}
};
针说我用代码替换了每个driver.whatever
调用driver.get().whatever
。
现在,为了解决此问题的最终目的,我还编写了一个@AfterClass
方法,该方法将driver.get().quit();
被编译器接受,因为该变量是静态的。
但是,对此进行测试会导致意外行为。我有一个Selenium
Grid设置,其中有2个节点在远程计算机上运行。我曾按预期运行此设置,但是现在浏览器到处都是垃圾邮件,并且测试失败。(虽然应该运行2个浏览器,但要打开8个以上的浏览器)
我链接的建议该解决方案的线程有人评论说,如果已经使用了像JUnit这样的框架,手动处理线程可能是个坏主意。
什么是正确的设计来做到这一点?
我只能想到
@Test
执行每个带注释的方法之前创建一个浏览器(@Before
用于创建WebDriver实例并@After
关闭会话)我不太确定选项3是否会遇到可能的问题。如果我在每种方法后都关闭了会话,那么在该节点完成之前的会话之前,Grid-
Server可能实际上在该节点上打开了一个具有全新类的新会话。尽管测试彼此独立,但我仍然觉得这是潜在的危险。
在座的任何人都在积极使用多线程Selenium测试服并且可以指导我什么是正确的设计吗?
总的来说,我同意:
如果已经使用了像JUnit这样的框架,手动处理线程可能不是一个好主意
但是,看看Parallelized
您提到的运行器以及@Parametrized
junit 4.12的内部实现,这是可能的。
每个测试用例都计划执行。默认情况下,junit在单线程中执行测试用例。Parallelized
扩展Parametrized
方式是用多线程调度程序代替了单线程测试调度程序,因此,要了解这如何影响Parametrized
测试用例的运行方式,我们必须查看JUnit
Parametrized
源代码:
https://github.com/junit-
team/junit/blob/r4.12/src/main/java/org/junit/runners/Parameterized.java#L303
好像:
@Parametrized
测试用例TestWithParameters
针对每个测试参数分为一组TestWithParameters
实例Runner
创建并安排执行(在这种情况下,Runner
实例是专门的 BlockJUnit4ClassRunnerWithParameters
)实际上, 每个@Parametrized测试用例都会生成一组要运行的测试实例(每个参数一个实例),并且每个实例都是独立安排的,
因此在我们的案例中(Parallelized
并@Parametrized
以WebDriver
实例作为参数进行测试),将在专用线程中执行多个独立测试,以用于每种WebDriver
类型。这很重要,因为它允许我们WebDriver
在当前线程的范围内存储特定的实例。
请 记住,此行为依赖于junit 4.12的内部实现细节,并且可能会发生变化 (例如,参见中的注释RunnerScheduler
)。
让我看下面的例子。它依靠提到的JUnit行为,并用于ThreadLocal
存储WebDriver
相同案例组中测试之间共享的实例。唯一的招数ThreadLocal
是只初始化一次(在@Before中)并销毁每个创建的实例(在@AfterClass中)。
package example.junit;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
/**
* Parallel Selenium WebDriver example for http://stackoverflow.com/questions/30353996/selenium-and-parallelized-junit-webdriver-instances
* Parallelized class is like http://hwellmann.blogspot.de/2009/12/running-parameterized-junit-tests-in.html
*/
@RunWith(Parallelized.class)
public class ParallelSeleniumTest {
/** Available driver types */
enum WebDriverType {
CHROME,
FIREFOX
}
/** Create WebDriver instances for specified type */
static class WebDriverFactory {
static WebDriver create(WebDriverType type) {
WebDriver driver;
switch (type) {
case FIREFOX:
driver = new FirefoxDriver();
break;
case CHROME:
driver = new ChromeDriver();
break;
default:
throw new IllegalStateException();
}
log(driver, "created");
return driver;
}
}
// for description how to user Parametrized
// see: https://github.com/junit-team/junit/wiki/Parameterized-tests
@Parameterized.Parameter
public WebDriverType currentDriverType;
// test case naming requires junit 4.11
@Parameterized.Parameters(name= "{0}")
public static Collection<Object[]> driverTypes() {
return Arrays.asList(new Object[][] {
{ WebDriverType.CHROME },
{ WebDriverType.FIREFOX }
});
}
private static ThreadLocal<WebDriver> currentDriver = new ThreadLocal<WebDriver>();
private static List<WebDriver> driversToCleanup = Collections.synchronizedList(new ArrayList<WebDriver>());
@BeforeClass
public static void initChromeVariables() {
System.setProperty("webdriver.chrome.driver", "/path/to/chromedriver");
}
@Before
public void driverInit() {
if (currentDriver.get()==null) {
WebDriver driver = WebDriverFactory.create(currentDriverType);
driversToCleanup.add(driver);
currentDriver.set(driver);
}
}
private WebDriver getDriver() {
return currentDriver.get();
}
@Test
public void searchForChromeDriver() throws InterruptedException {
openAndSearch(getDriver(), "chromedriver");
}
@Test
public void searchForJunit() throws InterruptedException {
openAndSearch(getDriver(), "junit");
}
@Test
public void searchForStackoverflow() throws InterruptedException {
openAndSearch(getDriver(), "stackoverflow");
}
private void openAndSearch(WebDriver driver, String phraseToSearch) throws InterruptedException {
log(driver, "search for: "+phraseToSearch);
driver.get("http://www.google.com");
WebElement searchBox = driver.findElement(By.name("q"));
searchBox.sendKeys(phraseToSearch);
searchBox.submit();
Thread.sleep(3000);
}
@AfterClass
public static void driverCleanup() {
Iterator<WebDriver> iterator = driversToCleanup.iterator();
while (iterator.hasNext()) {
WebDriver driver = iterator.next();
log(driver, "about to quit");
driver.quit();
iterator.remove();
}
}
private static void log(WebDriver driver, String message) {
String driverShortName = StringUtils.substringAfterLast(driver.getClass().getName(), ".");
System.out.println(String.format("%15s, %15s: %s", Thread.currentThread().getName(), driverShortName, message));
}
}
它将打开两个浏览器并在每个浏览器窗口中同时执行三个测试用例 。
控制台将打印如下内容:
pool-1-thread-1, ChromeDriver: created
pool-1-thread-1, ChromeDriver: search for: stackoverflow
pool-1-thread-2, FirefoxDriver: created
pool-1-thread-2, FirefoxDriver: search for: stackoverflow
pool-1-thread-1, ChromeDriver: search for: junit
pool-1-thread-2, FirefoxDriver: search for: junit
pool-1-thread-1, ChromeDriver: search for: chromedriver
pool-1-thread-2, FirefoxDriver: search for: chromedriver
main, ChromeDriver: about to quit
main, FirefoxDriver: about to quit
您可以看到驱动程序为每个辅助线程创建一次,并在最后销毁。
总而言之,我们需要类似的东西,@BeforeParameter
并且@AfterParameter
在执行线程的上下文中,快速搜索表明该想法已在Junit中注册为问题。
问题内容: 设置 因此,基本上,我正在尝试实现使用JUnit并行运行的Selenium测试。 为此,我找到了这个JUnit运行器。它真的很好,我非常喜欢。 但是,我在处理WebDriver实例时遇到问题。 我想要的是 在执行方法之前,每个WebDriver元素应为每个类创建一次。 从逻辑上讲,我可以为此使用类构造函数。实际上,这确实是我测试的要求,因为我需要利用,以便可以相应地创建WebDrive
我用cucumber配水豚和硒-WebDriver。到目前为止,我一直使用Chrome,但该项目也要求对Firefox进行一些跨浏览器测试。 在Firefox中运行时,我只是得到一个空白窗口,网页不出现。
工具:Java、Selenium WebDriver、Maven、Git、Bamboo 我不知道如何在Bamboo下运行我的测试用例,这些测试用例由java编写,由maven构建,并存储在Git存储库中。Bamboo无法打开真正的浏览器(即Firefox、chrome…)当我尝试使用HTMLUnitdriver(无头浏览器)而不是真正的浏览器时,它是有效的,但HTMLUnitdriver的问题是它
如果我使用,如下所示: 然后,当测试执行第一次开始时,所有的web驱动程序都填满了,但是它很快就开始删除并一次执行一个驱动程序。 所以我的问题是: null
嘿,我在POM中做了这个配置。xml文件并行运行测试。但当我使用cmd进行“mvn验证”时,只有一个浏览器正在运行一个功能,而在完成一个功能文件的执行后,另一个功能正在运行。这是我的代码和pom。xml请建议我怎么做? 我正在使用cucumber 这是我的pom.xml代码: 提前感谢。