【问题标题】:Selenium headless mode few tests failing with NoSuchElementException using AjaxElementLocatorFactorySelenium 无头模式很少使用 AjaxElementLocatorFactory 的 NoSuchElementException 测试失败
【发布时间】:2021-12-19 07:40:37
【问题描述】:

如果我在非无头模式下运行它,并且如果在无头模式下运行我的测试,那么我有一些测试通过,那么一些测试将失败,但无法找到元素的异常。遇到这种情况怎么办

窗口大小有多大也有关系吗?目前我有以下内容,但我想如果他们希望这样的窗口大小没有无头,为什么有些会无头失败

@BeforeEach
public void setUp() {
    WebDriverManager.chromedriver().setup();
    driver = new ChromeDriver(new ChromeOptions()
            .addArguments("start-maximized")
            .addArguments("--disable-popup-blocking")
            .addArguments("--headless"));
    driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
    loginToEnvironment();
}

在无头模式下,某些元素找不到

由 PageFactory.init 完成的元素初始化

public class BasePage {

    public WebDriver driver;
    protected Wait wait;

    public BasePage(WebDriver driver) {
        initializePage(driver);
        this.wait = new Wait(driver);
    }

    final protected void initializePage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(new AjaxElementLocatorFactory(driver, 20), this);
    }
}

注册测试

@Test
    public void shouldSignUpSuccessfully() {
        signUpModal.signUp((SignUp) credentials)
                .getCountryModalInstance()
                .chooseCountry(((SignUp) credentials).getCountry())
                .clickOnSaveButton();
        assertTrue(homePage.getMyAccountName().getText().isEmpty());
    }

堆栈跟踪:

Timed out after 20 seconds. Unable to locate the element
org.openqa.selenium.NoSuchElementException: Timed out after 20 seconds. Unable to locate the element
    at org.openqa.selenium.support.pagefactory.AjaxElementLocator.findElement(AjaxElementLocator.java:99)
    at org.openqa.selenium.support.pagefactory.internal.LocatingElementHandler.invoke(LocatingElementHandler.java:38)
    at com.sun.proxy.$Proxy17.getText(Unknown Source)
    at com.opngo.nowos.selenium.SignUpServiceTest.shouldSignUpSuccessfully(SignUpServiceTest.java:50)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:628)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:117)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:184)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:180)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:127)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:171)
    at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:115)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:171)
    at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService.invokeAll(ForkJoinPoolHierarchicalTestExecutorService.java:115)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService$ExclusiveTask.compute(ForkJoinPoolHierarchicalTestExecutorService.java:171)
    at java.util.concurrent.RecursiveAction.exec(RecursiveAction.java:189)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
Caused by: org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":".user-name"}
  (Session info: headless chrome=95.0.4638.69)
For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/no_such_element.html
Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
System info: host: 'MacBook-Pro-3.local', ip: 'fe80:0:0:0:869:afaa:89ee:2f42%en0', os.name: 'Mac OS X', os.arch: 'x86_64', os.version: '10.15.7', java.version: '1.8.0_302'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 95.0.4638.69, chrome: {chromedriverVersion: 95.0.4638.54 (d31a821ec901f..., userDataDir: /var/folders/fy/4f9mrb0n1fq...}, goog:chromeOptions: {debuggerAddress: localhost:62396}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: MAC, platformName: MAC, proxy: Proxy(), setWindowRect: true, strictFileInteractability: false, timeouts: {implicit: 0, pageLoad: 300000, script: 30000}, unhandledPromptBehavior: dismiss and notify, webauthn:extension:credBlob: true, webauthn:extension:largeBlob: true, webauthn:virtualAuthenticators: true}
Session ID: 968cb69072e7bbe6a92b2822d8ad26ee
*** Element info: {Using=css selector, value=.user-name}
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.createException(W3CHttpResponseCodec.java:187)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:122)
    at org.openqa.selenium.remote.http.W3CHttpResponseCodec.decode(W3CHttpResponseCodec.java:49)
    at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:158)
    at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
    at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:552)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:323)
    at org.openqa.selenium.remote.RemoteWebDriver.findElementByCssSelector(RemoteWebDriver.java:420)
    at org.openqa.selenium.By$ByCssSelector.findElement(By.java:431)
    at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:315)
    at org.openqa.selenium.support.pagefactory.DefaultElementLocator.findElement(DefaultElementLocator.java:69)
    at org.openqa.selenium.support.pagefactory.AjaxElementLocator.access$001(AjaxElementLocator.java:39)
    at org.openqa.selenium.support.pagefactory.AjaxElementLocator$SlowLoadingElement.isLoaded(AjaxElementLocator.java:165)
    at org.openqa.selenium.support.ui.SlowLoadableComponent.get(SlowLoadableComponent.java:72)
    at org.openqa.selenium.support.pagefactory.AjaxElementLocator.findElement(AjaxElementLocator.java:95)
    ... 48 more

【问题讨论】:

  • 也使用这个参数options.add_argument("--start-maximized")
  • 错误说明了什么?
  • @cruisepandey 嘿,可悲的是,它没有用,而且在 headless 中元素仍然不是棘手的
  • @DebanjanB 元素在 headless 中不是难以处理的,但它不是 headless
  • 用错误堆栈跟踪更新问题

标签: java selenium xpath css-selectors ajax-element-locator-factory


【解决方案1】:

对于这个 CSS 选择器:

.user-name

如果我们在HTML DOM 中有唯一条目,请检查dev tools(谷歌浏览器)。

你应该检查的css:

.user-name

检查步骤:

Press F12 in Chrome -> 转到element 部分 -> 做一个CTRL + F -> 然后粘贴css 看看,如果你想要的element 用@ 得到高亮 987654330@匹配节点。

如果我们有 1/1 匹配节点,请确保:

  1. 此网络元素不在 iframe 下。
  2. 此 Web 元素不在影子根下。
  3. 您不应该在 selenium 启动的新选项卡/窗口上。

如果它属于上述任何类别,您将不得不处理该特定情况。

【讨论】:

  • 嘿伙计,感谢您的时间和贡献,我在上面添加了我的屏幕截图和测试。
  • 您可以检查//div[@class='icon-profile-container']//child::span[@class='user-name'] xpath,它是否显示 1/1 匹配节点?请参阅上面的如何检查部分。
  • 嘿,它以这种方式定位 //div[@class='icon-profile-container'] 但如果在字符串中添加子元素,它不会...
  • 那么这就是问题所在.. //div[@class='icon-profile-container']//child::span[@class='user-name'] 有多少个节点?你会看到类似 1/2 或 1/3 或类似的东西
  • 如果我在聊天中给你发消息,你会接受吗?
【解决方案2】:

AjaxElementLocatorFactory

​​>

AjaxElementLocatorFactory 是页面工厂模式中的延迟加载概念,仅当 WebElement 用于任何操作时才识别它们,即 WebElement 的 timeOut 可以在 AjaxElementLocatorFactory 的帮助下分配给 Object 页面类。

所以理想情况下,您需要将 implicitlyWait 删除为:

Warning:不要混合隐式和显式等待。这样做会导致 不可预知的等待时间。例如,将隐式等待设置为 10 秒和 15 秒的显式等待可能会导致超时 20 秒后发生。


NoSuchElementException 表示没有找到元素。

要定位元素,您可以使用以下任一Locator Strategies

  • 使用css_selector

    div.header-menu-item > div.header-menu-name span.user-name
    
  • 使用xpath

    //div[@class='header-menu-item']/div[@class='header-menu-item']//span[@class='user-name']
    

【讨论】:

  • 嘿,感谢您抽出宝贵的时间,所以如果我有延迟加载的概念,我不需要在我的设置中隐式等待?
  • 理想情况下,您不应该这样做,我已链接文档供您参考。
猜你喜欢
  • 1970-01-01
  • 2019-02-05
  • 2022-12-24
  • 1970-01-01
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
  • 1970-01-01
  • 2015-05-05
相关资源
最近更新 更多