访问 class 变量时出现 Selenium NoSuchElementException

Selenium NoSuchElementException when accessing a class variable

所以,我有一个 class A,它有一个 (public static WebElement element1, element2)。

public class myClass {
public static WebElement element1, element2;


public myClass(){
    WebDriver driver = new FirefoxDriver();

    this.element1 = driver.findElement(By.id("button"));
    this.element2 = driver.findElement(By.id("text"));
}
}

然后我有一个测试 class,其中有一个名为 @Test public void testClassA 的方法。

@Test
public void testClassA(){

    myClass m = new myClass();

    m.element1.click();

    m.element2.sendKeys("input something");

}

问题是我收到 org.openqa.selenium.NoSuchElementException:无法定位元素:{} 错误。我认为我的错误正在发生,因为 element2 位于下一页,它在单击按钮后显示。我应该在我的代码中做什么,以便当我将两个元素分配给 findBy 方法时,测试将通过第一次单击然后将键发送到 element2?

正如您提到的 element2 出现在下一页中,您必须等到新页面加载。如果没有这个等待,如果你试图找到 element2,它将抛出异常,因为在页面更改之前在当前页面上找不到该元素。

解决方案:

1) 在element1 click() 方法后添加一个Explicit wait。您可以等到 element2 在 click() 之后出现。

m.element1.click();

WebElement myDynamicElement = (new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(By.id("text")));

m.element2.sendKeys("input something");

2) 简单但我不推荐这个。使用 Thread.sleep() 等待新页面加载。

3) 使用页面对象设计模式。

您可以使用webdriver implicitwait 等待页面上的元素加载一段时间。

driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);

正如您在上面的代码中看到的,我用了 8 秒来加载页面上的 elemnet。 Read more about wait in Webdriver

使用 try catch 块来处理异常。

@Test
public void testClassA(){
driver.manage().timeouts().implicitlyWait(8, TimeUnit.SECONDS);
try{
myClass m = new myClass();

m.element1.click();

m.element2.sendKeys("input something");
}catch(NoSuchElementException e){
    e.printStackTrace();
}
}

The way you have written the code will break in scenarios where elements are dynamic and also on page navigation.

在不同的 class 中找到网络元素并在测试中使用该 class 的对象不是一个好习惯 class.

正如您在代码中看到的那样:myClass m = new myClass();,当创建 myClass 的对象时,构造函数被触发并且驱动程序同时找到 element1element2一次。而且,由于element2还是没有显示,所以抛出异常。

我不知道是什么促使您遵循这种做法,而是 仅在您真正需要时才查找网络元素。 似乎有很多选择,这取决于如何你想设计你的代码。

  1. 使用相同的 class 查找元素并对其执行操作。
  2. 使用不同的方法来查找网络元素,而不是使用构造函数来查找它们。
  3. 如果你想让事情变得通用,请为 webdriver 操作使用关键字。
  4. 如果需要,使用属性文件来存储定位器和数据。

更多标准做法(我猜是):

  1. 使用 Page Objects 查找网络元素。
  2. 除了页面对象外,还使用 ​​PageFactory

很好的参考:http://www.guru99.com/page-object-model-pom-page-factory-in-selenium-ultimate-guide.html