Selenium 不会刷新 Jenkins 上的页面

Posted

技术标签:

【中文标题】Selenium 不会刷新 Jenkins 上的页面【英文标题】:Selenium doesn't refresh page on Jenkins 【发布时间】:2020-02-25 23:37:28 【问题描述】:

我有一个类似这样的测试用例:

打开主页 如果没有内容存在 刷新页面 继续其他步骤...

这是代码的相关部分:

public JpoPO() 
        driver.get(Settings.JPO_TEST_URL);
        PageFactory.initElements(driver, this);
        System.out.println("[INFO] Homepage initialized.");
        zatvoriModal();
        refreshIfNeeded();
        zatvoriModal();
        (new WebDriverWait(driver, 30)).until(ExpectedConditions.invisibilityOfElementLocated(By.cssSelector("#loading")));
        System.out.println("[DEBUG] broj .ng-scope elemenata: " +driver.findElements(By.cssSelector(".ng-scope")).size());
        System.out.println("[OK] JpoPO() initialized.");

这是refreshIfNeeded() 部分:

public void refreshIfNeeded() 
    if(System.getProperty("os.name").equals("Linux"))
        System.out.println("### A"+now());
        int broj = driver.findElements(By.cssSelector(".ng-scope")).size();
        javascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("location.reload()");
        //driver.findElement(By.cssSelector("header")).sendKeys(Keys.F5);
        driver.get(driver.getCurrentUrl());
        waitForNoSpinner();
        System.out.println("[DEBUG] location reloaded, .ng-scope elements: "+broj);
        System.out.println("### B"+now());
    else
        System.out.println("[] Starting refreshIfNeeded()");
        Date ts1 = new Date();
        int count = 0;
        while (driver.findElements(By.cssSelector(".ng-scope")).size()==0 && count < 10)
            driver.navigate().refresh();
            zatvoriModal();
            try 
                (new WebDriverWait(driver, 10)).until(ExpectedConditions.numberOfElementsToBeMoreThan(By.cssSelector(".ng-scope"), 0));
                Date ts2 = new Date();
                long trajanje = ts2.getTime() - ts1.getTime();
                System.out.println(String.format("[INFO] Učitavanje sadržaja: %s ms.", trajanje));
             catch (Exception e)
                try 
                    Thread.sleep(3000);
                 catch (InterruptedException ex) 
                    ex.printStackTrace();
                
            
            System.out.println("[] Count: "+count);
            count++;
        
    

在我的 Windows 机器上运行 本地 时,事情正常,但是当它在 remote Jenkins linux 机器上运行时,刷新不会似乎不起作用。

这是 Jenkins 控制台输出:

16:18:48 [INFO] Homepage initialized.
16:18:48 ### A2019-10-30T16:18:48.904
16:18:49 [INFO] Spinner (ili uvjet čekanja) je trajao: 117 ms. (waitForNoSpinner-try)
16:18:49 [INFO] Spinner (ili uvjet čekanja) je trajao: 89 ms. (waitForNoSpinner-finally)
16:18:49 [DEBUG] location reloaded, .ng-scope elements: 0
16:18:49 ### B2019-10-30T16:18:49.417
16:18:49 [DEBUG] broj .ng-scope elemenata: 0
16:18:49 [OK] JpoPO() initialized.

在尝试查找不存在的元素时,测试在以下步骤中失败,除非刷新页面。 使用我无法分享的屏幕截图也证实了这一点。

有多种使用 Selenium here 刷新页面的方法,但没有一种方法有效。

似乎js.executeScript("location.reload()")driver.navigate().refresh() 都不起作用。

我正在使用以下 Chromedriver 选项:

if(System.getProperty("os.name").equals("Linux"))
    options.addArguments("--headless");
    options.addArguments("--proxy-server='direct://'");
    options.addArguments("--proxy-bypass-list=*");
    options.addArguments("--window-size=1200,800");
    WebDriverManager.chromedriver().version("77.0.3865.40").setup();


编辑:

当我尝试使用 Robot 类进行刷新时,我会得到一个 java.awt.AWTException: headless environment,所以我将 System.setProperty("java.awt.headless", "false"); 添加到我的代码中。

现在我得到了一个

java.awt.AWTError: Can't connect to X11 window server using ':0.0' as the value of the DISPLAY variable.

我对 Linux 几乎一无所知,这可能是原因吗?

【问题讨论】:

您在 Jenkins 服务器上使用哪个版本的 Chrome? 它是 77.0.3865.40。 您是否尝试过您提供的链接中提到的所有方法? sendKeys.Keys , navigate.to() , sendKeys() , get() 是的,我都试过了。 你能在driver.get(driver.getCurrentUrl()); waitForNoSpinner();之后叫它int broj = driver.findElements(By.cssSelector(".ng-scope")).size(); 【参考方案1】:

您在刷新之前存储了 .ng-scope 元素的大小,之后就不再获取大小。这就是您在日志中得到 0 的原因。您应该搜索waitForNoSpinner 之后的元素以获取更新大小值:

if(System.getProperty("os.name").equals("Linux"))
    System.out.println("### A"+now());
    int broj = driver.findElements(By.cssSelector(".ng-scope")).size();
    JavascriptExecutor js = (JavascriptExecutor) driver;
    js.executeScript("location.reload()");
    //driver.findElement(By.cssSelector("header")).sendKeys(Keys.F5);
    driver.get(driver.getCurrentUrl());
    waitForNoSpinner();
    broj = wait.until(ExpectedConditions.numberOfElementsToBeMoreThan(By.cssSelector(".ng-scope"), 0)).size();
    System.out.println("[DEBUG] location reloaded, .ng-scope elements: "+ broj);
    System.out.println("### B"+now());

这里是替代的refreshIfNeeded 方法,其中waitForNoSpinnerzatvoriModal 基于操作系统。如果waitForNoSpinnerzatvoriModal 之间没有区别,请将if 替换为其中之一。如果 20 秒后找不到 .ng-scope,方法将抛出 TimeoutException

public void refreshIfNeeded() 
    WebDriverWait wait = new WebDriverWait(driver, 20, 1000);

    System.out.println("[DEBUG] check .ng-scope elements and refresh if not located");

    wait.until(d -> 
        if (d.findElements(By.cssSelector(".ng-scope")).isEmpty()) 
            System.out.println("[DEBUG] no .ng-scope elements, refresh..");
            driver.navigate().refresh();
            waitForNoSpinner();
            /*if (System.getProperty("os.name").equals("Linux")) 
                waitForNoSpinner();
             else 
               zatvoriModal();
            */
        
        return !d.findElements(By.cssSelector(".ng-scope")).isEmpty();
    );

    System.out.println("[DEBUG] .ng-scope elements: " + driver.findElements(By.cssSelector(".ng-scope")).size());

带循环:

public void refreshIfNeeded() throws InterruptedException 
    WebDriverWait wait = new WebDriverWait(driver, 20, 1000);

    System.out.println("[DEBUG] check .ng-scope elements and refresh if not located");

    for (int i=0; i < 10; i++) 
        try 
            wait.until(d -> 
                if (d.findElements(By.cssSelector(".ng-scope")).isEmpty()) 
                    System.out.println("[DEBUG] no .ng-scope elements, refresh..");
                    driver.navigate().refresh();
                    if (System.getProperty("os.name").equals("Linux")) 
                        waitForNoSpinner();
                     else 
                        zatvoriModal();
                    
                
                return !d.findElements(By.cssSelector(".ng-scope")).isEmpty();
            );
            break;
         catch (Exception e) 
            Thread.sleep(3000);
        
    

【讨论】:

问题是:driver.navigate().refresh(); 不会做任何事情。这不仅基于broj 值,还基于屏幕截图。 可以分享截图吗?为什么需要刷新? 你可以从 Jenkins 访问网页吗? 让我们continue this discussion in chat。

以上是关于Selenium 不会刷新 Jenkins 上的页面的主要内容,如果未能解决你的问题,请参考以下文章

Selenium Grid Docker-通过 Jenkins 实现自动化

我应该为jenkins中的selenium测试添加excel数据的路径

Jenkins 从属环境变量刷新

Selenium-IDE:如何验证/断言页面刷新

使用 UIScrollView 分页拉动刷新

mysql 学习 - InnoDB的页