总的来说,我同意:
如果已经使用了像JUnit这样的框架,手动处理线程可能是一个坏主意
但是,看看
Parallelized您提到的运行器以及
@Parametrizedjunit 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;@RunWith(Parallelized.class)public class ParallelSeleniumTest { enum WebDriverType { CHROME, FIREFOX } 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: createdpool-1-thread-1, ChromeDriver: search for: stackoverflowpool-1-thread-2, FirefoxDriver: createdpool-1-thread-2, FirefoxDriver: search for: stackoverflowpool-1-thread-1, ChromeDriver: search for: junitpool-1-thread-2, FirefoxDriver: search for: junitpool-1-thread-1, ChromeDriver: search for: chromedriverpool-1-thread-2, FirefoxDriver: search for: chromedrivermain, ChromeDriver: about to quitmain, FirefoxDriver: about to quit
您可以看到驱动程序为每个辅助线程创建一次,并在最后销毁。
总而言之,我们需要类似的东西,@BeforeParameter
并且@AfterParameter
在执行线程的上下文中,快速搜索表明该想法已在Junit中注册为问题。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)