Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Selenium和并行化JUnit-WebDriver实例 设置_Java_Multithreading_Selenium_Junit - Fatal编程技术网

Java Selenium和并行化JUnit-WebDriver实例 设置

Java Selenium和并行化JUnit-WebDriver实例 设置,java,multithreading,selenium,junit,Java,Multithreading,Selenium,Junit,因此,基本上我正在尝试使用JUnit实现并行运行的Selenium测试 我已经找到了。它真的很好用,我很喜欢 但是,我在处理WebDriver实例方面遇到了问题 我想要什么 在执行@Test方法之前,应该为每个类创建一个WebDriver元素 从逻辑上讲,我可以使用类构造函数来实现这一点。实际上,这正是我测试的要求,因为我需要使用@参数,这样我就可以相应地创建WebDriver实例(Chrome、FF、IE…) 问题 问题是我希望WebDriver实例在类完成后被清除(driver.quit()

因此,基本上我正在尝试使用JUnit实现并行运行的Selenium测试

我已经找到了。它真的很好用,我很喜欢

但是,我在处理WebDriver实例方面遇到了问题

我想要什么 在执行
@Test
方法之前,应该为每个类创建一个WebDriver元素

从逻辑上讲,我可以使用类构造函数来实现这一点。实际上,这正是我测试的要求,因为我需要使用
@参数
,这样我就可以相应地创建WebDriver实例(Chrome、FF、IE…)

问题 问题是我希望WebDriver实例在完成后被清除(
driver.quit()
),而不是在每个
@Test
方法完成后被清除。 但是我不能使用
@AfterClass
,因为我不能使WebDriver成为静态成员,因为每个类实例都必须使用自己的实例(否则测试将尝试在同一浏览器中运行)

可能的解决办法 我发现了一个可能的建议,由穆纳尔·戈萨尔先生提出。 按照他的建议,我将WebDriver改为
静态ThreadLocal
,然后使用

 // in the classes constructor

driver = new ThreadLocal<WebDriver>() {
           @Override
           protected WebDriver initialValue() {
                 return new FirefoxDriver(); /
           }
};
//在类构造函数中
驱动程序=新线程本地(){
@凌驾
受保护的WebDriver initialValue(){
返回新的FirefoxDriver()/
}
};
我想说我用我的代码中的
driver.get()替换了每个
driver.whatever
调用

现在,为了解决这个问题,我还编写了一个
@AfterClass
方法,该方法将调用
driver.get().quit()
现在被编译器接受,因为变量是静态的

然而,测试这一点会导致意外的行为。我有一个Selenium网格设置,在远程机器上运行两个节点。我已经按照预期运行了这个安装程序,但是现在浏览器被垃圾处理,测试失败。(当打开8+浏览器时,应运行2个浏览器)

我链接的建议此解决方案的线程有人评论说,如果已经使用JUnit之类的框架,手动处理线程可能是个坏主意

我的问题 这样做的正确设计是什么

我只能想到

  • 让这里的建议发挥作用
  • 编写一个带注释的@Test 方法,该方法执行所有其他方法,然后使用@After 达到与@AfterClass相同的效果
  • 将构造函数参数保存在一个成员变量中,并处理这样一个事实:在执行每个
    @Test
    带注释的方法之前,我必须创建一个浏览器(使用
    @before
    创建WebDriver实例,使用
    @After
    关闭会话)
  • 不过,我不太清楚选项3是否会遇到可能的问题。如果我在每个方法之后关闭会话,那么网格服务器实际上可能会在这个节点上用一个全新的类打开一个新会话,而这个类还没有完成以前的会话。虽然测试是相互独立的,但我仍然觉得这是潜在的危险


    这里是否有人积极使用多线程Selenium测试套件,并能指导我什么是正确的设计

    总的来说,我同意:

    如果已经在使用 类似JUnit的框架

    但是,看看您提到的
    并行化
    运行程序和JUnit4.12中
    @参数化
    的内部实现,这是可能的

    每个测试用例都计划执行。默认情况下,junit在单线程中执行测试用例<代码>并行化
    扩展了
    参数化
    ,单线程测试调度程序被多线程调度程序取代,因此,要了解这对
    参数化
    测试用例运行方式的影响,我们必须查看JUnit
    参数化
    源代码:

    看起来像:

  • @parameterized
    测试用例被拆分为一组
    TestWithParameters
    用于 各测试参数
  • 为每个
    TestWithParameters
    创建并计划
    Runner
    的实例 用于执行(在本例中,
    Runner
    实例是专用的
    BlockJUnit4ClassRunnerWithParameters
  • 实际上,每个@Parameterized测试用例生成一组要运行的测试实例(每个参数都有一个实例),每个实例都是独立调度的,因此在我们的例子中(
    并行化
    @Parameterized
    测试,使用
    WebDriver
    实例作为参数)对于每个
    WebDriver
    类型,将在专用线程中执行多个独立测试。这很重要,因为它允许我们在当前线程的范围内存储特定的
    WebDriver
    实例

    记住,此行为依赖于junit 4.12的内部实现细节,可能会发生更改(例如,请参见
    RunnerScheduler
    中的注释)

    让我看看下面的例子。 它依赖于前面提到的JUnit行为,并使用
    ThreadLocal
    存储相同案例组中测试之间共享的
    WebDriver
    实例。使用
    ThreadLocal
    的唯一诀窍是只初始化它一次(在@Before中),然后销毁每个创建的实例(在@AfterClass中)

    您可以看到,驱动程序为每个工作线程创建一次,并在最后销毁


    总之,,在执行线程的上下文中,我们需要类似于
    @BeforeParameter
    @AfterParameter
    的内容,快速搜索显示这种想法已经注册为一个简短的注意:我当前解决方案遇到的问题与这样一个事实有关:似乎每个类方法都调用了类构造函数。因此,与其有x amoun
    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