Java Selenium Web驱动程序并行执行测试用例时的过时元素引用异常

Java Selenium Web驱动程序并行执行测试用例时的过时元素引用异常,java,selenium-webdriver,testng-dataprovider,Java,Selenium Webdriver,Testng Dataprovider,这是我的类,其中包含我希望并行执行的测试方法f()。数据提供者向测试方法提供输入 public class DemoTest { private WebDriver driver; @Test(dataProvider = "dp") public void f(Integer n, String s) { try { driver.get("www.google.com"); driver.findElement(By.id("lst-ib")).sendKeys("12345

这是我的类,其中包含我希望并行执行的测试方法f()。数据提供者向测试方法提供输入

public class DemoTest {
private WebDriver driver;

@Test(dataProvider = "dp")
public void f(Integer n, String s) {
  try {

  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();
  }
}

@BeforeSuite
 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();
  }
 }

@AfterSuite
public void afterMethod() {
  try {
      System.out.println("After method id:"+Thread.currentThread().getId());
  if(driver != null ) {
  driver.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

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

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

我想在两个线程中并行执行test f()。 对于findElement方法的一次迭代,我得到了陈旧的元素引用异常。
有谁能告诉我要添加到这个代码段中的内容吗?

请将您的数据提供者的名称包括在内

这应该是这样的,

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

};
}
还有你的司机,应该是

driver.get("https://www.google.co.in");
最后是你的问题

如果在您最初找到
元素
后对页面进行了任何更改,那么webdriver引用现在将包含一个
过时的
引用。由于页面已更改,元素将不再位于
webdriver
期望的位置

要解决您的问题,请尝试在每次需要使用元素时找到它——编写一个小方法,您可以在适当的时候调用它

private void clickAnElementByLinkText(String id) {
    WebDriverWait wait = new WebDriverWait(driver, 10);
    wait.until(ExpectedConditions.presenceOfElementLocated(By.id(id)));
    driver.findElement(By.id(id)).sendKeys("1234567");
}

@Test(dataProvider = "dp")
public void f(Integer n, String s) {
  try {

  driver.get("https://www.google.co.in");
  clickAnElementByLinkText("lst-ib");
  System.out.println("method f id:"+Thread.currentThread().getId()+" n:"+n+" s:"+s);
  }
  catch(Exception e) {
      e.printStackTrace();
  }
}

现在您不会看到过时的元素引用异常,这是由两个独立测试使用一个
WebDriver
实例引起的。在
@BeforeMethod
中,您正在通过
driver=new FirefoxDriver()创建一个新实例,但这将替换该字段

private WebDriver driver;
通过这个例子。每个线程都创建了一个新实例,但只使用最后一个实例,
private WebDriver
字段当前引用的实例。您需要告诉每个测试方法保留单独的WebDriver实例,而不将其用作类字段


当Webdriver注意到页面上的某些内容已更改时,将引发
StaleElementReference
异常。在您的情况下会发生这种情况,因为当时另一个线程正在使用同一个WebDriver。

为什么只有在并行执行方法时才会出现过时的元素引用异常?这不是在并行执行时发生的,您是否尝试过不并行执行?Google.com被加载了四次[4次来自数据提供程序的输入],因此元素将不再是webdriver期望的位置。是的,我没有并行执行,所以我从来没有得到过此异常是由于每个线程使用相同的web驱动程序实例而导致的此异常吗?您已经询问了陈旧的元素引用异常,在您最初找到元素后,当页面发生任何更改时,就会发生这种情况。所以我提供了解决方案,如果我有10个或更多的测试并行运行,该怎么办?我理解为什么会有例外,但我不知道如何解决this@Prozorov如果您想并行运行这些测试,您必须为每个线程创建一个新的WebDriver实例并跟踪它们。原始代码不起作用,因为新实例总是替换
私有WebDriver
,但是如果您只是为它们创建十个变量,例如
webdriver1
webdriver10
,那么问题就应该解决了。只要记住使用
synchronized
关键字,你需要在每个线程中执行可见的操作。不,不要为同一个属性创建10个不同的变量,这绝对不是一个干净的代码,相反,我只使用了1个驱动程序->当你运行测试时,每个线程都有自己的webdriver,您可以在pom或gradle文件测试中指定{systemProperty(“junit.jupiter.execution.parallel.enabled”,true)systemProperty(“junit.jupiter.execution.parallel.mode.default”,“CONCURRENT”)}