selenium
Selenium等待页面加载在Selenium脚本中起着重要的作用。 它们有助于使它们不易剥落,更可靠。 Selenium提供多次等待,以根据某些条件在脚本执行中提供足够的等待或暂停。 从而确保您在使用Selenium执行自动化测试时不会导致脚本失败。 在本教程中,我们将解释Selenium等待和睡眠的类型,并提供实时示例以及对它们的比较研究。 让我们首先回答一个关键问题:“为什么要使用Selenium等待?”
为什么我们需要Selenium等待?
大多数现代应用程序的前端都是基于JavaScript或Ajax构建的,使用诸如React,Angular之类的框架,或任何其他需要花费一定时间才能在页面上加载或刷新Web元素的框架。 因此,如果您倾向于在脚本中找到尚未加载到页面上的元素,则selenium会向您抛出“ ElementNotVisibleException ”消息。
下面的代码片段将帮助您展示与使用Selenium执行自动化测试时相同的问题。 在此代码段中,我使用的是easymytrip.com的示例,在该示例中,post用户选择行程日期的“ From”和“ To”目的地,Web应用程序需要花费一些时间来加载所需的航班详细信息。 在这种情况下,用户无需等待就可以从列表中预订第一班航班。 现在,由于页面尚未加载,脚本无法找到“立即预订”按钮。 结果抛出“ NoSuchElementException ”。 下面的代码段和控制台输出:
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.gargoylesoftware.htmlunit.javascript.background.JavaScriptExecutor; public class NoWaitImplemented {
public static void main(String[] args) throws InterruptedException {
System.setProperty( "webdriver.chrome.driver" , ".\\Driver\\chromedriver.exe" );
WebDriver driver= new ChromeDriver();
driver.manage().window().maximize();
driver.get( " https://www.easemytrip.com/ " );
driver.findElement(By.id( "FromSector_show" )).sendKeys( "Delhi" , Keys.ENTER);
driver.findElement(By.id( "Editbox13_show" )).sendKeys( "Mumbai" , Keys.ENTER);
driver.findElement(By.id( "ddate" )).click();
driver.findElement(By.id( "snd_4_08/08/2019" )).click();
driver.findElement(By.className( "src_btn" )).click();
driver.findElement(By.xpath( "//button[text()='Book Now']" )).click();
}
}
控制台输出:
我已经使用XPath通过脚本对Selenium进行自动化测试来定位Web元素。
阅读更多:带有示例的在Selenium中使用XPath的完整指南
Selenium等待页面加载有助于解决此问题。 Selenium等待有不同类型,例如隐式等待和显式等待,可确保在Selenium脚本发现元素以进行进一步操作之前将其加载到页面中。
Selenium类型等待页面加载
使用Selenium执行自动化测试时,我们在生成Selenium脚本时使用以下类型的等待:
- Thread.Sleep()方法
- 隐式等待
- 显式等待
- 流利的等待
让我们深入了解其中的每一个。
Thread.Sleep()用于使用Selenium进行自动化测试
Sleep是属于线程类的静态方法。 可以使用类名(即Thread)的引用来调用此方法。 如果在使用Selenium执行自动化测试时使用Thread.sleep ,则此方法将在指定的持续时间内停止执行脚本,而不管是否在网页上找到了该元素。 它接受持续时间(以毫秒为单位)。 相同的语法是:
Thread.sleep(3000);
睡眠函数抛出InterruptedException,因此应使用try-catch块进行处理,如下所示:
try {
Thread.sleep( 5000 );
}
catch (InterruptedException ie){
}
为什么使用Thread.Sleep()不是一个好主意?
现在,我将重点介绍使用thread.sleep()的一些缺点。
- Selenium Webdriver等待指定的时间,无论是否找到元素。 如果在指定的持续时间之前找到元素,脚本将仍然等待该持续时间,从而增加了脚本的执行时间。
- 如果要显示的元素在静态时间后没有出现并保持更改,那么您将永远不会知道睡眠功能所需的估计时间。 如果花费的时间超过了定义的时间,脚本将抛出错误。 这就是为什么,如果您正在使用Selenium waits处理动态元素,那么最好不要使用Thread.sleep()。
- Thread.sleep仅适用于之前编写的元素。 如果您有两到四个元素需要等待一定的时间才能加载,则在这种情况下,需要多次指定Thread.sleep。 如果这样做的话! 好吧,您到处都会发现脚本中充满了Thread.sleep()语法。
由于上述缺点,在脚本创建中使用Thread.Sleep()被认为是一种不好的做法。
下面的代码片段突出显示了Thread.Sleep()在Selenium自动化测试中的用法。 在此示例中,我们使用与上面的easymytrip相同的示例,一旦用户单击搜索,我们将停止线程执行。 在这种情况下,代码可以正常工作,而不会引发任何错误。
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import com.gargoylesoftware.htmlunit.javascript.background.JavaScriptExecutor; public class ThreadWait {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
//setting the driver executable
System.setProperty( "webdriver.chrome.driver" , ".\\Driver\\chromedriver.exe" );
//Initiating your chromedriver
WebDriver driver= new ChromeDriver();
driver.manage().window().maximize();
driver.get( " https://www.easemytrip.com/ " );
driver.findElement(By.id( "FromSector_show" )).sendKeys( "Delhi" , Keys.ENTER);
driver.findElement(By.id( "Editbox13_show" )).sendKeys( "Mumbai" , Keys.ENTER);
driver.findElement(By.id( "ddate" )).click();
driver.findElement(By.id( "snd_4_08/08/2019" )).click();
driver.findElement(By.className( "src_btn" )).click();
Thread.sleep( 5000 );
driver.findElement(By.xpath( "//button[text()='Book Now']" )).click();
}
}
现在,如果我有同一应用程序的另一个页面需要花费一些时间来加载,该怎么办? 在这种情况下,我不想在脚本中多次使用thread.sleep()。
您可能会认为,如果不是Thread.sleep(),那么哪个Selenium等待页面加载就足以满足测试要求?
在这种情况下,这就是隐式等待的地方。 让我们详细检查隐式Selenium。
Selenium隐式等待自动化测试
Selenium解决了Thread.sleep()提供的问题,并提出了两个Selenium等待页面加载的方法。 其中之一是隐式等待,它允许您将WebDriver暂停特定的时间,直到WebDriver在网页上找到所需的元素为止。
这里要注意的关键点是,与Thread.sleep()不同,它不等待整个时间段。 如果在指定的持续时间之前找到了元素,它将继续执行代码的下一行,从而减少了脚本执行的时间。 这就是为什么隐式等待也称为动态等待的原因。 如果未在指定的持续时间内找到该元素,则抛出ElementNotVisibleException 。
关于隐式等待的另一件值得注意的事情是,它是全局应用的,这使其比Thread.sleep()更好。 这意味着您只需编写一次即可,它适用于整个WebDriver实例中脚本上指定的所有Web元素。 方便吗? 实现相同的语法是:
driver.manage().timeouts().implicitlyWait(Time Interval to wait for , TimeUnit.SECONDS);
隐式等待的默认时间为零,并且每隔500毫秒会不断轮询所需的元素。 让我们看下面的代码片段,展示隐式等待的用法。 在此示例中,我使用了相同的easymytrip示例。 在这种情况下,我们将向前迈进并继续进行预订过程,在此过程中页面需要花费更多的时间来加载。 这里存在两个页面的页面加载问题,我们使用隐式等待而不是多次使用Thread.sleep()来处理一行代码。
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.Select;
import com.gargoylesoftware.htmlunit.javascript.background.JavaScriptExecutor; public class ImplicitWait {
public static void main(String[] args) throws InterruptedException {
// TODO Auto-generated method stub
//setting the driver executable
System.setProperty( "webdriver.chrome.driver" , ".\\Driver\\chromedriver.exe" );
//Initiating your chromedriver
WebDriver driver= new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait( 30 , TimeUnit.SECONDS);
driver.get( " https://www.easemytrip.com/ " );
driver.findElement(By.id( "FromSector_show" )).sendKeys( "Delhi" , Keys.ENTER);
driver.findElement(By.id( "Editbox13_show" )).sendKeys( "Mumbai" , Keys.ENTER);
driver.findElement(By.id( "ddate" )).click();
driver.findElement(By.id( "snd_4_08/08/2019" )).click();
driver.findElement(By.className( "src_btn" )).click();
driver.findElement(By.xpath( "//button[text()='Book Now']" )).click();
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript( "window.scrollBy(0,750)" );
driver.findElement(By.xpath( "//input[@type='email']" )).sendKeys( "[email protected]" );
driver.findElement(By.xpath( "//span[text()='Continue Booking']" )).click();
WebElement title=driver.findElement(By.id( "titleAdult0" ));
Select titleTraveller= new Select(title);
titleTraveller.selectByVisibleText( "MS" );
driver.findElement(By.xpath( "//input[@placeholder='Enter First Name']" )).sendKeys( "Sadhvi" );
driver.findElement(By.xpath( "//input[@placeholder='Enter Last Name']" )).sendKeys( "Singh" );
driver.findElement(By.xpath( "//input[@placeholder='Mobile Number']" )).sendKeys( "9958468819" );
driver.findElement(By.xpath( "//div[@class='con1']/span[@class='co1']" )).click();
}
}
现在,我们知道了一个事实,即应该在一定的持续时间内加载页面,但是如果我们不知道加载时元素是可见/可点击的,该怎么办。 正如它出现的时候一样,它是动态的,并且会不时地变化。 在这种情况下,显式等待将帮助您克服此问题。 让我们研究它的细节。
明确等待使用Selenium进行自动化测试
显式等待是动态Selenium等待的另一种。 显式等待帮助,用于在特定的时间内基于特定条件停止脚本的执行。 时间到头后,您将获得ElementNotVisibleException 。 在您不知道要等待的时间的情况下,此显式等待会派上用场。 使用elementToBeClickable()或textToBePresentInElement()之类的条件,可以等待指定的持续时间。 可以结合使用WebDriverWait和ExpectedConditions类来使用这些预定义方法。 为了使用这种情况,请在您的课程中导入以下软件包:
import org.openqa.selenium.support.ui.ExpectedConditions
import org.openqa.selenium.support.ui.WebDriverWait
发布该代码后,需要为WebDriverWait类创建一个引用变量,并使用WebDriver实例实例化该变量,并提供可能需要的Selenium等待页面加载的数量。 时间单位是秒。 可以如下定义它:
WebDriverWait wait = new WebDriverWait(driver, 30 );
为了使用ExpectedCondition类的预定义方法,我们将使用如下的wait引用变量:
wait.until(ExpectedConditions.visibilityOfElementLocated(Reference of Element to be located using locator));
预期条件的类型:
以下是在使用Selenium执行自动化测试时通常使用的几种预期条件。
- visibleOfElementLocated()-验证给定元素是否存在
- alertIsPresent()-验证是否存在警报。
- elementToBeClickable()-验证给定元素是否在屏幕上存在/可单击
- textToBePresentInElement()-验证给定元素是否具有必需的文本
- titlels()-验证条件,等待具有给定标题的页面
还有更多可用的预期条件,您可以通过Selenium官方GitHub页面进行引用。 像隐式等待一样,显式等待也会在每500毫秒后继续轮询。
下面是突出显示显式Selenium等待的用法的代码段。 在此示例中,我们使用的是“ rentomojo”应用程序,其中的模式在动态时间显示在主页上。 使用显式等待,基于元素的可见性,我们将等待元素并关闭弹出窗口。 参考代码:
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.By; import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
public class ExplicitWait {
public static void main(String[] args) {
// TODO Auto-generated method stub
//setting the driver executable
System.setProperty( "webdriver.chrome.driver" , ".\\Driver\\chromedriver.exe" );
//Initiating your chromedriver
WebDriver driver= new ChromeDriver();
driver.manage().window().maximize();
driver.get( " https://www.rentomojo.com/ " );
driver.findElement(By.xpath( "//span[@class='rm-city__selectorBoxLoca'][contains(text(),'Delhi')]" )).click();
WebDriverWait wait= new WebDriverWait(driver, 120 );
wait.until(ExpectedConditions.visibilityOf(driver.findElement(By.xpath( "//div[@class='Campaign__innerWrapper']/button" ))));
driver.findElement(By.xpath( "//div[@class='Campaign__innerWrapper']/button" )).click();
}
}
注意-当同时使用隐式等待和显式等待时,它们将按累积时间工作,而不是按单个等待条件工作。 例如,如果给定隐式等待30秒,给定显式等待10秒,那么它正在寻找的显式元素将等待40秒。
Selenium等待之间的区别:显式与隐式
现在,由于您已经知道隐式等待和显式等待的用法,因此让我们研究一下这两个Selenium等待之间的区别:
隐式等待 |
显式等待 |
---|---|
默认情况下,它将应用于脚本中的所有元素。 | 它仅适用于特定条件的特定元素。 |
我们不能根据指定条件(例如元素选择/可点击)而不是显式进行等待。 | 明确地说,我们可以根据特定条件指定等待时间。 |
当您确定该元素在特定时间内可能可见时,通常使用它 | 当您不知道元素可见性的时间时,通常使用它。 它具有动态性质。 |
Fluent等待使用Selenium进行自动化测试
就其功能而言,Fluent等待类似于显式等待。 在Fluent等待中,当您不知道某个元素可见或单击所需的时间时,将对它执行Selenium等待。 Fluent等待提供的一些差异因素是:
- 轮询频率-在显式等待的情况下,默认情况下此轮询频率为500毫秒。 使用Fluent wait,您可以根据需要更改此轮询频率,即可以告诉脚本在每隔“ x”秒后继续检查一个元素。
- 忽略异常-在轮询期间,如果找不到元素,则可以忽略任何异常,例如'NoSuchElement'异常等。
除了这些差异因素(例如显式等待或隐式等待)之外,您还可以定义等待元素可见或可操作的时间。 以下语法或代码行用于定义Selenium中的Fluent等待:
默认情况下,它将应用于脚本中的所有元素。
语法似乎很复杂,但是一旦开始使用,它可能会变得很方便。 可能这是测试人员选择显式等待而不是Fluent等待的最大原因之一。 另外,Explicit等待和Fluent等待之间的主要区别在于Explicit Selenium Wait提供了预定义条件,这些条件适用于我们需要等待的元素,而对于Fluent Selenium Wait,则可以定义自己的自定义条件适用方法中的条件。
我对Fluent Selenium Wait的看法?
我个人还没有在实时示例中找到任何有用的流畅等待的实现,因此到目前为止,我希望自己不要执行它。 我和您一样渴望Selenium 4的发布。 我希望在发布之后,我们可以对使用Fluent等待而不是其他Selenium等待的实际优势有更多的了解。 到目前为止,根据我的经验,由于它比Fluent Selenium wait更容易实现代码,因此我倾向于使用Explicit Selenium wait。 如果您有其他意见,请在下面的评论中告诉我。
Selenium的角色等待基于云的Selenium网格
大多数测试人员通常更喜欢使用基于云的服务提供商执行自动化的网站测试,以进行Selenium测试,例如LambdaTest(云上的跨浏览器测试工具)。 想知道为什么?
那么,如果您在基于云的Selenium网格(例如LambdaTest)上运行自动化脚本,会发生什么情况? Selenium等待如何有助于有效的测试结果?
每个基于云的提供程序都会在抛出Selenium超时异常之前提供默认的时间限制。 这样做是为了防止过度利用云资源。 在LamdaTest中,默认超时为90秒。 现在,如果您对Web元素的加载时间超过90秒,那该怎么办?
这就是Selenium等待出现的地方。 如果您的测试套件很复杂,可能会在云Selenium Grid上面临超时问题,那么您可以使用Selenium wait将WebDriver暂停默认时间超过90秒。 因此,避免了在成功运行自动化脚本时发生超时错误。
Selenium的最终裁决正在等待中!
Selenium Waits可以帮助您减少脚本的脆弱性和可靠性。 无论选择哪种等待方式,都要确保它能帮助您实现Selenium自动化测试背后的目标。 另一要注意的关键是要确保在应用程序中不保留不必要的Selenium等待。 Thread.sleep()过去可能是一个选项,但现在我们有新的Selenium等待和即将来临,我宁愿建议您远离Thread.sleep()来推动Selenium自动化测试。 因此,下一次您遇到了元素或页面加载问题时,便知道在哪里寻找。 测试愉快!
翻译自: https://www.javacodegeeks.com/2019/08/selenium-waits-implicit-explicit-fluent-sleep.html
selenium