在 Selenium 中编写 Sleep 以加载页面中的元素?

writing Sleep in Selenium to loading elements in page?

我写了一些代码来比较来自网站的价格和 CSV 文件,我的测试效果很好,但需要很长时间(1 分钟)。在找到网页中的每个元素之前,我使用了 Sleep。你有没有其他方法来编写这个 运行 代码更快的测试,使用这种方法需要 1 秒才能加载每个价格,然后与 CSV file.On 中的价格进行比较,另一方面不睡觉我的代码不会'因为加载页面和查找元素而工作。

public class TestBikeInsurancePrice extends HepsterTest {    
private void prepareTest() {
        initiateBrowserWebShop();
        var url = baseUrl + "/fahrradversicherung-test-2020";
        driver.get(url);
        handleCookie(driver);
    }

    @Test(priority = 1)
    void checkBeschädigung() throws FileNotFoundException {
        prepareTest();
        List<CsvPrice> stuff = readFromCSV("resources/price/Test Fahrradversicherung Upload.csv");

        stuff.forEach(csvPrice -> {
            System.out.println(csvPrice.getQualityName() + " " + csvPrice.getCoverageSum() + " " + csvPrice.getDurationTimeUnit() + " " + csvPrice.getDurationRiskPremium());
            Select price = new Select(driver.findElement(By.id("coverageSum")));
            price.selectByValue(csvPrice.getCoverageSum().toString());

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String qualityName;
            if (csvPrice.getQualityName().equals("Diebstahl")) qualityName = "Nur Diebstahl";
            else qualityName = csvPrice.getQualityName();
            driver.findElement(By.xpath("//*[contains(text(),'" + qualityName + "')]")).click();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            String duration;
            if (!csvPrice.getDurationTimeUnit().equals("MONTHS")) duration = "Preisvorteil";
            else duration = "flexibel, mtl. kündbar";
            driver.findElement(By.xpath("//*[contains(text(),'" + duration + "')]")).click();

            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            WebElement priceElement = driver.findElement(By.xpath("//*[@id='product-configurator-spinner']//parent::span"));
            String priceAsString = priceElement.getText().split(" ")[0];
            System.out.println(priceAsString);
            Assert.assertEquals(csvPrice.getPriceBasePrice().setScale(2), new BigDecimal(priceAsString.replace(",", ".")).setScale(2));
        });
    }

显式等待: Selenium 客户端可以使用命令式过程语言进行显式等待。它们允许您的代码暂停程序执行或冻结线程,直到您传递给它的条件得到解决。以特定频率调用条件,直到等待超时结束。这意味着只要条件 returns 为假值,它就会继续尝试和等待。

我在代码中添加了显式等待。

WebDriverWait wait = new WebDriverWait(driver,10);
        
stuff.forEach(csvPrice -> {
            System.out.println(csvPrice.getQualityName() + " " + csvPrice.getCoverageSum() + " " + csvPrice.getDurationTimeUnit() + " " + csvPrice.getDurationRiskPremium());
            wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("coverageSum")));
            Select price = new Select(driver.findElement(By.id("coverageSum")));
            price.selectByValue(csvPrice.getCoverageSum().toString());


            String qualityName;
            if (csvPrice.getQualityName().equals("Diebstahl")) qualityName = "Nur Diebstahl";
            else qualityName = csvPrice.getQualityName();
            wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + qualityName + "')]")));
            driver.findElement(By.xpath("//*[contains(text(),'" + qualityName + "')]")).click();

            String duration;
            if (!csvPrice.getDurationTimeUnit().equals("MONTHS")) duration = "Preisvorteil";
            else duration = "flexibel, mtl. kündbar";
            wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[contains(text(),'" + duration + "')]")));
            driver.findElement(By.xpath("//*[contains(text(),'" + duration + "')]")).click();

            wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id='product-configurator-spinner']//parent::span")));
            WebElement priceElement = driver.findElement(By.xpath("//*[@id='product-configurator-spinner']//parent::span"));
            String priceAsString = priceElement.getText().split(" ")[0];
            System.out.println(priceAsString);
            Assert.assertEquals(csvPrice.getPriceBasePrice().setScale(2), new BigDecimal(priceAsString.replace(",", ".")).setScale(2));
        });

使用时的实际问题: Thread.sleep()

Thread.sleep() is considered as the worst case of explicit wait because it has to wait for the full time specified as the argument of Thread.sleep(3000), before proceeding further.

As a result, the next step had to wait for the full time to get over.

解决方法:将Thread.sleep()改为explicit wait

在 Selenium 中,在那种情况下“等待”会派上用场或在执行测试中发挥重要作用。

Selenium 中有三种等待类型

  1. 隐式等待: 在隐式等待中,WebDriver 在尝试查找任何元素时轮询 DOM 一段时间。当网页上的某些元素不能立即使用并且需要一些时间加载时,这会很有用。

代码:

WebDriver driver = new FirefoxDriver();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
  1. 显式等待 显式等待允许我们的代码停止程序执行,或冻结线程,直到您传递给它的条件得到解决。以特定频率调用条件,直到等待超时结束。这意味着只要条件 returns 为假值,它就会继续尝试和等待。

代码:

WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("YOUR-LOCATOR")));
  1. 流利等待: FluentWait 实例定义等待条件的最长时间,以及检查条件的频率。

代码:

//Declare and initialise a fluent wait
FluentWait wait = new FluentWait(driver);
//Specify the timout of the wait
wait.withTimeout(5000, TimeUnit.MILLISECONDS);
//Sepcify polling time
wait.pollingEvery(250, TimeUnit.MILLISECONDS);
//Specify what exceptions to ignore
wait.ignoring(NoSuchElementException.class)

//This is how we specify the condition to wait on.
//This is what we will explore more in this chapter
wait.until(ExpectedConditions.alertIsPresent());

参考:

https://www.selenium.dev/documentation/en/webdriver/waits/

https://www.browserstack.com/guide/wait-commands-in-selenium-webdriver