前言
这些是过去学习和工作中积累的个人总结,不过可能会存在一些主观臆断,如果有说错的地方,请指出来哦!
回答
在UI自动化测试中,页面元素定位是至关重要的。虽然Selenium Webdriver提供了多种元素定位方法,但在实际测试过程中,常常会遇到这样的报错:
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":".top\-center1"}
此类报错就是告知元素无法定位或者没有找到。遇到这样的错误,需要怎么去处理排查呢?
下面列举了几种常见的元素无法定位或者没有找到的情况,并提供了相应的解决方法。
元素未加载出来
在自动化测试过程中,有时候计算机运行速度比较快,导致页面元素没有完全加载,就已经开始定位了,这种情况导致元素定位失败的情况占绝大部分。为了解决这个问题,可以使用强制等待、隐式等待,显式等待以及FluentWait等待。
-
强制等待:Thread.sleep(x)
是一种简单的等待方法,它可以让程序暂停执行,等待指定的毫秒数后再继续执行下一步操作。这种方法的优点在于简单易用,但缺点是无法准确控制等待时间,可能会浪费一些时间,影响程序执行速度。一般情况下,在脚本调试或者编写阶段,我们可以使用Thread.sleep()来进行暂停和等待操作。
-
隐式等待:driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));
为了确保在整个Driver生命周期内能够及时找到所需元素,可以在代码中设置一个默认的等待时间。在等待期间,程序会定期进行轮询查找,以便尽快发现元素的存在。如果等待时间到达后仍然未能找到元素,可以抛出异常来提醒开发者处理这种情况。虽然这种方式可以确保在整个Driver生命周期内能够及时找到所需元素,但由于其仅关注元素的存在性,而无法处理元素的交互问题,因此在实际开发中需要谨慎使用。在大多数情况下,我们会使用这种方式来寻找元素。
-
显示等待:WebDriverWait(driver实例, 最长等待时间).until(结束条件);
最长等待时间是否符合结束条件,满足则结束,不满足则提示。这种方法优点在于更准确的等待时间,脚本更灵活,且稳定性更高。但缺点是增加了代码复杂性和依赖性,主要用于特定条件下的等待问题,如点击等交互性行为。
-
FluentWait等待
于显示等待类似,可以设置自定义超时时间、轮询频率,以及忽略特定类型的异常。
元素在Iframe中
iframe(内嵌框架)是 HTML 中一种用于将一个网页嵌入到另一个网页中的标签,它可以在一个页面中显示来自其他页面的内容。在网页中,使用iframe标签可以将一个网页嵌套在另一个网页中,实现网页间的互联互通。所以如果元素是嵌入到ifame中的话,需要切换到元素所在的Iframe。
Selenium针对这种情况也提供了iframe的切换的方法:
- webDriver.switchTo().frame(id/name/WebElement):切换到 frame
- webDriver.switchTo().parentFrame():切换到父框架
- webDriver.switchTo().defaultContent():切回到最外层
元素在另一个窗口中
在执行WEB自动化测试的时候,有时候会打开新的窗口或者是项卡,而元素可能在新的Windows窗口,此时需要切换Windows。
Selenium针对这种情况也提供了窗口的的切换的方法:
webDriver.switchTo().window(windowHandle);
元素在弹窗中
弹窗有alert(警告信息),confirm(确认信息),prompt(提示输入)三种样式。
在UI自动化中针对弹窗,Selenium提供了下列的方法:
- driver.switchTo().alert().accept():点击弹窗中的确认按钮
- driver.switchTo().alert().dismiss():点击弹窗中的取消按钮
- driver.switchTo().alert().getText():获取弹框文本
- driver.switchTo().alert().sendKeys(text):在弹窗中输入文本内容
元素ID动态变化
当页面刷新后,页面中元素的ID属性值会随机变化,因此仅仅依赖于定位元素的ID属性值已经不再有效。此时,我们需要使用多种定位方式来定位页面中的元素,例如xpath或者css selector的相对定位方式,有时候甚至需要使用绝对定位才能成功定位。灵活运用这些定位方式可以帮助我们快速定位页面中的元素。
元素定位信息错误
该错误主要是发生在xpath定位上。由于xpath层级太复杂,很容易犯错。但该定位方式能够有效定位绝大部分的元素。可以采取下列两种方式解决
- 可以使用Firefox的firePath,复制xpath路径。该方式容易因为层级改变而需要重新编写过xpath路径,不建议使用,初学者可以先复制路径,然后尝试去修改它。
- 提高下写xpath的水平。
如何检验编写的xpath是否正确?编写好xpath路径,在浏览器的开发者模式下中的Elements模块中按下ctrl+F中进行验证。
特殊元素
- 点击元素由于父元素和子元素联动,导致子元素的点击事件被父元素消费掉,导致子元素无法被点击,此时可以尝试使用JavaScript去操作
- 开发自定义控件,此元素没有属性信息,无法通过常规的元素定位方法定位,此时可以尝试使用图像识别方式定位:
- 显示的是::before、::after这类的元素,被伪元素包裹起来的元素经常会定位不到,此时就需要对伪元素进行处理了,此时可以尝试使用JavaScript去操作
总结
在元素定位不到的时候,优先考虑是不是因为元素未加载出来导致。在这种情况下,可以使用浏览器提供的强制等待功能,确保代码成功调试,然后再切换为显示或隐式等待。
其次考虑是不是元素在iframe、另一个窗口或弹窗中。如果是的,则可以使用Selenium提供的相应API方法来切换,在重新定位元素。
而当元素动态变化时,可以优先使用css selector定位和xpath定位方式,但在使用xpath时需要确保编写正确。
如果上述方法都无法解决问题,可以考虑使用JavaScript进行操作。