在 table 中断言数据时出现 StaleElement 异常错误

StaleElement exception error when asserting data in a table

我正在尝试向 table 添加数据,然后断言通过在列表中收集 table 数据来添加数据,但每次它都会向我抛出 StaleElement 异常错误,现在我猜这是因为列表正在刷新,所以我不确定如何处理它。

这是我的实现

    private static List<WebElement> listOfJobs = 
    driver.findElements(By.xpath(("//*[@id='resultTable']//tbody/tr//a")));

    public static List<WebElement> getListOfJobs() 
        {
            try 
            {
                return listOfJobs;
            } 
            catch (Exception e) 
            {
                e.printStackTrace();
            }
            return null;
        }

    public static String generateName()
        {
            String AlphaNumericString = "abcdefghijklmnopqrstuvxyz";
            StringBuilder sb = new StringBuilder(9);
    
            for (int i = 0; i < 9; i++) 
            {
                int index = (int)(AlphaNumericString.length() * Math.random());
                sb.append(AlphaNumericString.charAt(index));
            }
            return sb.toString()+"digi";
        }
    
    @SuppressWarnings({ "null" })
        public static List<String> listOfJobs()
        {
            List<String> jobs = null;
            for(int i=0; i < OrangeHRMAddJobCategories.getListOfJobs().size(); i++)
            {
                jobs.add(OrangeHRMAddJobCategories.getListOfJobs().get(i).getText());
            }
            return jobs;
        }

    OrangeHRMAddJobCategories jobCategories = new OrangeHRMAddJobCategories();
            jobCategories.clickJobTab().clickJobCategoires().clickAdd().setJobCategoryName(UsefulFunctionUtils.generateName()).saveJobCategory();   

    Assertions.assertThat(UsefulFunctionUtils.listOfJobs().contains("digi"));

我觉得 listOfJobs 应该重新注入某个地方,但不确定我应该把它放在哪里,因为刷新页面不起作用。

完整的堆栈跟踪


    org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document
      (Session info: chrome=94.0.4606.61)
    For documentation on this error, please visit: https://www.seleniumhq.org/exceptions/stale_element_reference.html
    Build info: version: '3.141.59', revision: 'e82be7d358', time: '2018-11-14T08:17:03'
    System info: host: 'DESKTOP-R3JT7MO', ip: '192.168.0.103', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '16.0.1'
    Driver info: org.openqa.selenium.chrome.ChromeDriver
    Capabilities {acceptInsecureCerts: false, browserName: chrome, browserVersion: 94.0.4606.61, chrome: {chromedriverVersion: 94.0.4606.61 (418b78f5838ed..., userDataDir: C:\Users\CHINMA~1\AppData\L...}, goog:chromeOptions: {debuggerAddress: localhost:62489}, javascriptEnabled: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: WINDOWS, platformName: WINDOWS, 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: 8b68238ee73ae8190f250fa15fbb41f1
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:78)
        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
        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.RemoteWebElement.execute(RemoteWebElement.java:285)
        at org.openqa.selenium.remote.RemoteWebElement.getText(RemoteWebElement.java:166)
        at com.digicorp.utils.UsefulFunctionUtils.listOfJobs(UsefulFunctionUtils.java:45)
        at com.digicorp.testcases.TC_AddJobCategory.testAddJobCategory(TC_AddJobCategory.java:26)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:78)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:567)
        at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:133)
        at org.testng.internal.TestInvoker.invokeMethod(TestInvoker.java:598)
        at org.testng.internal.TestInvoker.invokeTestMethod(TestInvoker.java:173)
        at org.testng.internal.MethodRunner.runInSequence(MethodRunner.java:46)
        at org.testng.internal.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:824)
        at org.testng.internal.TestInvoker.invokeTestMethods(TestInvoker.java:146)
        at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:146)
        at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:128)
        at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
        at org.testng.TestRunner.privateRun(TestRunner.java:794)
        at org.testng.TestRunner.run(TestRunner.java:596)
        at org.testng.SuiteRunner.runTest(SuiteRunner.java:377)
        at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:371)
        at org.testng.SuiteRunner.privateRun(SuiteRunner.java:332)
        at org.testng.SuiteRunner.run(SuiteRunner.java:276)
        at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:53)
        at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:96)
        at org.testng.TestNG.runSuitesSequentially(TestNG.java:1212)
        at org.testng.TestNG.runSuitesLocally(TestNG.java:1134)
        at org.testng.TestNG.runSuites(TestNG.java:1063)
        at org.testng.TestNG.run(TestNG.java:1031)
        at org.testng.remote.AbstractRemoteTestNG.run(AbstractRemoteTestNG.java:115)
        at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:251)
        at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:77)

org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document

表示对元素的引用现在是“陈旧的”--- 元素不再出现在页面的 DOM 上。这种期望的原因可能是您的 DOM 已更新或刷新。例如,执行 click() 等操作后,您的 DOM 可能会更新或刷新。此时当您尝试在 DOM 上查找元素时,您将遇到此错误。

您必须在更新或刷新中重新找到该元素 DOM

try{
    jobs.add(OrangeHRMAddJobCategories.getListOfJobs().get(i).getText());
   }catch(org.openqa.selenium.StaleElementReferenceException e){
     new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOf(OrangeHRMAddJobCategories.getListOfJobs().get(i)));
     jobs.add(OrangeHRMAddJobCategories.getListOfJobs().get(i).getText());
   }

根据与 OP 的对话,它在这一点上变得陈旧

jobs.add(OrangeHRMAddJobCategories.getListOfJobs().get(i).getText());

可能是因为他正在调用 getListOfJobs 其中 returns WebElement 列表。 当您再次致电时,page dom 无法再使用它们,因为您可能已经在 first iteration 中与 web element/elements 进行过交互。修复很少,例如使用 Explicit wait staleness 或 redefining the elements again and again for next iteration.

修复 1 :

private static List<WebElement> listOfJobs = driver.findElements(By.xpath(("//*[@id='resultTable']//tbody/tr//a")));

public static List<WebElement> getListOfJobs(int j) 
 {
     try 
     {
         List<WebElement> listOfJobs = driver.findElements(By.xpath("(//*[@id='resultTable']//tbody/tr//a)['"+j+"']"));
         return listOfJobs;
     } 
     catch (Exception e) 
     {
         e.printStackTrace();
     }
     return null;
 }
 
 
    @SuppressWarnings({ "null" })
    public static List<String> listOfJobs()
    {
        int j = 1;
        List<String> jobs = null;
        for(int i=0; i < listOfJobs.size(); i++)
        {
            jobs.add(OrangeHRMAddJobCategories.getListOfJobs(j).get(i).getText());
            j++;
        }
        return jobs;
    }

您是在网页加载元素之前进行操作,请添加等待条件后再进行操作。

By divCss = By.xpath(("//*[@id='resultTable']//tbody/tr//a"));
wait.until(ExpectedConditions.elementToBeClickable(divCss));
wait.until(ExpectedConditions.presenceOfAllElementsLocatedBy(divCss));