【问题标题】:Session not found exception with Selenium Web driver parallel execution of Data Provider test caseSelenium Web 驱动程序并行执行数据提供程序测试用例时找不到会话异常
【发布时间】:2015-12-04 23:36:35
【问题描述】:

这是我的测试类,我想在新浏览器中并行执行 Data Provider 的每个输入。我能够打开新的浏览器,但我得到 Session Not Found Exception 并且没有这样的元素异常

public class DemoTest {
private WebDriver driver;
@Test(dataProvider = "dp")
public void f(Integer n, String s) {
  try {
      System.out.println("Driver: "+driver.toString());
      driver.get("www.google.com");
      driver.findElement(By.id("lst-ib")).sendKeys("1234567");
      System.out.println("method f id:"+Thread.currentThread().getId()+" n:"+n+" s:"+s);
  }
  catch(Exception e) {
      e.printStackTrace();
  }
}
@BeforeMethod
public void beforeMethod() {
  try {
  driver= new FirefoxDriver();
  driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  driver.manage().window().maximize();
  System.out.println("Before method id:"+Thread.currentThread().getId());
  }
  catch (Exception e) {
      e.printStackTrace();
  }
 }

@AfterMethod
public void afterMethod() {
  try {
      System.out.println("After method id:"+Thread.currentThread().getId());
  if(driver != null ) {
  driver.quit();
 // driver.close();
  }
  }
  catch(Exception e) {
      e.printStackTrace();
  }
}


@DataProvider(parallel=true)
public Object[][] dp() {
return new Object[][] {
  new Object[] { 1, "a" },
  new Object[] { 2, "b" },
  new Object[] { 3, "c" },
  new Object[] { 4, "d" },

};
}
}

这是 testng.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >

<suite name="Suite" parallel="methods"> 
<test name="prelogin">
<classes>
    <class name="com.package.DemoTest"></class>
</classes>
</test>
</suite> 

谁能告诉我为什么会出现这个异常以及如何解决它?

【问题讨论】:

  • 能否请您提供带有完整堆栈跟踪等的控制台输出?
  • 顺便说一句,我建议不要将您的代码包装在 try-catch 块中。如果您的 BeforeMethod 引发异常,那么您不希望 TestNG 跳过测试执行吗? TestNG 将处理来自测试和配置方法的异常,并为您打印堆栈跟踪。

标签: java selenium-webdriver testng-dataprovider


【解决方案1】:

您正在跨多个线程共享一个WebDriver 实例。因此,一个测试可以在另一个测试的afterMethod 已经退出它(因此会话未找到异常)或尚未加载google.com(因此没有此类元素异常)之后尝试使用WebDriver。

如果您想使用 TestNG 并行运行 Selenium WebDriver 测试,那么您可以使用 ThreadLocal 来为每个线程维护一个 WebDriver 实例。

例如

public class DemoTest {
    private static final ThreadLocal<WebDriver> WEB_DRIVER_THREAD_LOCAL = new InheritableThreadLocal<>();

    @Test(dataProvider = "dp")
    public void f(Integer n, String s) {
        WebDriver driver = WEB_DRIVER_THREAD_LOCAL.get();
        System.out.println("Driver: " + driver.toString());
        driver.get("www.google.com");
        driver.findElement(By.id("lst-ib")).sendKeys("1234567");
        System.out.println("method f id:" + Thread.currentThread().getId() + " n:" + n + " s:" + s);
    }

    @BeforeMethod
    public void beforeMethod() {
        WebDriver driver = new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.manage().window().maximize();
        WEB_DRIVER_THREAD_LOCAL.set(driver);
        System.out.println("Before method id:" + Thread.currentThread().getId());
    }

    @AfterMethod
    public void afterMethod() {
        WebDriver driver = WEB_DRIVER_THREAD_LOCAL.get();
        System.out.println("After method id:" + Thread.currentThread().getId());
        if (driver != null) {
            driver.quit();
        }
    }


    @DataProvider(parallel = true)
    public Object[][] dp() {
        return new Object[][]{
                new Object[]{1, "a"},
                new Object[]{2, "b"},
                new Object[]{3, "c"},
                new Object[]{4, "d"},

        };
    }
}

我省略了用 try-catch 块包装每个测试,因为 TestNG 已经捕获了测试/配置方法抛出的异常并为它们打印堆栈跟踪等。

上面的示例将为每个测试创建一个与测试线程关联的WebDriver 实例。即,如果它们都真正并行运行,您将打开 4 个 Firefox 实例(我认为这是您想要的)。

如果您有比线程更多的测试并且想要重用WebDriver 实例,那么您可以使用具有初始值的 ThreadLocal。

例如

public class DemoTest {
    private static final Set<WebDriver> WEB_DRIVERS = new HashSet<>();
    private static final ThreadLocal<WebDriver> WEB_DRIVER_THREAD_LOCAL = InheritableThreadLocal
            .withInitial(new Supplier<WebDriver>() {
                @Override
                public WebDriver get() {
                    WebDriver driver = new FirefoxDriver();
                    driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
                    driver.manage().window().maximize();
                    WEB_DRIVERS.add(driver);
                    System.out.println("Before thread id:" + Thread.currentThread().getId());
                    return driver;
                }
            });

    @Test(dataProvider = "dp")
    public void f(Integer n, String s) {
        WebDriver driver = WEB_DRIVER_THREAD_LOCAL.get();
        System.out.println("Driver: " + driver.toString());
        driver.get("www.google.com");
        driver.findElement(By.id("lst-ib")).sendKeys("1234567");
        System.out.println("method f id:" + Thread.currentThread().getId() + " n:" + n + " s:" + s);
    }

    @AfterClass
    public void afterClass() {
        for (WebDriver webDriver : WEB_DRIVERS) {
            try {
                webDriver.quit();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    @DataProvider(parallel = true)
    public Object[][] dp() {
        return new Object[][]{
                new Object[]{1, "a"},
                new Object[]{2, "b"},
                new Object[]{3, "c"},
                new Object[]{4, "d"},

        };
    }
}

还有一个testng.xml来减少线程总数来证明这一点:

<suite name="Suite" parallel="methods" thread-count="2" data-provider-thread-count="2">
    <test name="prelogin">
        <classes>
            <class name="DemoTest"/>
        </classes>
    </test>
</suite>

示例输出(看看它如何只创建 2 个 FirefoxDriver 实例,并行运行两个测试,然后并行运行接下来的两个测试,使用所有可用线程并为每个线程重用 Web 驱动程序):

Before thread id:14
Driver: FirefoxDriver: firefox on WINDOWS (e924b5f1-9ace-46e5-a6b3-d1494de7e94d)
method f id:14 n:2 s:b
Before thread id:13
Driver: FirefoxDriver: firefox on WINDOWS (8dc8a53c-5a96-41e8-9383-e552c7c8f680)
method f id:13 n:1 s:a
Driver: FirefoxDriver: firefox on WINDOWS (8dc8a53c-5a96-41e8-9383-e552c7c8f680)
method f id:13 n:3 s:c
Driver: FirefoxDriver: firefox on WINDOWS (8dc8a53c-5a96-41e8-9383-e552c7c8f680)
method f id:13 n:4 s:d

【讨论】:

  • 我在我的应用程序中使用了这种方法。但是,当我使用 2 个线程(即一个浏览器中的一个线程)进行多线程处理时,一个线程似乎在执行期间挂起,另一个线程完成。我该如何解决这个问题?
  • 奇怪。您是否对代码进行了任何更改,或者我的示例是否对您有问题?
  • 这个例子没有任何问题,但是我已经在实际应用中使用过这个场景,我遇到了问题
  • 您可以创建一个新问题,并通过一个简单的示例重现您的问题。我们可以从那里看。
【解决方案2】:

问题与数据提供者无关。问题在于driver.get("www.google.com");。 WebDriver api 向 Selenium 服务器发送 RESTfull 请求以执行命令。 REST 服务使用http 或https 协议进行请求/响应。因此,当我们在不提及协议前缀的情况下调用 url(在本例中为 http)时,会引发异常。

改为:

driver.get("http://www.google.com/");

这会起作用。

【讨论】:

  • 您遇到了什么问题?我照原样复制了您的 java 文件 &testng.xml 文件。它确实正确启动了所有会话,并且所有 4 个参数都通过了测试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-29
相关资源
最近更新 更多