随着Web技术的不断发展,各种新技术也不断被应用到Web页面中,如AJAX( Asynchronous JavaScript and XML )有关更多AJAX的介绍,可参考W3School(http://www.w3school.com.cn/ajax/ajax_intro.asp) ,当浏览器加载解析页面时,页面中各个元素可能并不能被同时加载完成的。在网络环境比较好的情况,用户或许觉得不到,但在网络环境较差的时候,我们就能看到浏览器在加载显示页面时,是有先后顺序的。如果在使用Selenium进行定位时,经常会出现ElementNotVisibleException等错误。针对这种问题,Selenium API提供了两种类型的等待:显式等待和隐藏等待。Selenium API提供等待的方法如下:
如下图所示,在输入用户名和密码后,点击“SUBMIT”将会进行验证,同时页面上也会显示验证进度。
在得到服务器的响应后,下面会显示验证的结果,如下图红色框中提示。
从测试的角度而言,希望验证的结果能立刻得到服务器的响应并被正确返回和显示在页面中,在某些情况下,网络会存在一些延迟。如果我们测试这种情况下的场景,应该怎么做了?在通常的测试中,会存在两种方法:等待足够长的时间或者在可接受的最长时间内进行验证。
Sleep方法
Sleep()方法并不是Selenium提供的API,而是.NET平台自带的。这种方法对我们调试非常有用,可以让我们以慢镜头观看整个测试过程,在使用时需要添加引用using System.Threading; 在点击“SUBMIT”后,我们设定一个足够长的时间里等待直到服务器返回验证结果,代码如下所示:
IWebDriver driver = new ChromeDriver();
driver.Url = "http://www.freejs.net/demo/98/index.php";
driver.Manage().Window.Maximize();
driver.FindElement(By.Id("username")).SendKeys("Test");
driver.FindElement(By.Id("password")).SendKeys("1");
driver.FindElement(By.Name("submit")).Click();
Thread.Sleep(10000);
string text=driver.FindElement(By.Id("status")).Text;
Assert.IsTrue(text.Contains("invalid username or password"));
Thread.Sleep(10000)意味着在点击SUBMIB按钮后,需要等待10秒钟,然后再验证从服务器返回的结果。在这段时间返回的结果是正确的,则测试通过,否则测试失败。换句话说,如果服务器在第11秒返回了正确的结果,测试也是失败的。
显示等待
很显然,在上面的代码中直接指定一个时间也并不是一个好的解决方案,为什么了?如果指定的操作提前完成,而仍然需要等待直到达到指定时间,这样显然有些浪费时间了。那么我们有没有更好的方式了?在Selenium提供了一种方式:显式等待,它指的是让Webdriver等待某个条件成立时继续执行,否则则是在达到设定的时间后,抛出超时异常。
IWebDriver driver = new ChromeDriver();
driver.Url = "http://www.freejs.net/demo/98/index.php";
driver.Manage().Window.Maximize();
driver.FindElement(By.Id("username")).SendKeys("Test");
driver.FindElement(By.Id("password")).SendKeys("1");
driver.FindElement(By.Name("submit")).Click();
//Thread.Sleep(10000);
WebDriverWait explicitWait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
string text = explicitWait.Until(d => d.FindElement(By.Id("status"))).Text;
Assert.IsTrue(text.Contains("invalid username or password"));
在上面的代码里面涉及到了C#中的委托和lambda表达式,大家可以了解一下。
隐式等待
隐式等待允许Web页面中的元素在特定的时间内加载完成。如果超出了设定的时间,指定的元素仍没有被加载完,则抛出异常。**默认的时间为 0 **
IWebDriver driver = new ChromeDriver();
driver.Url = "http://www.freejs.net/demo/98/index.php";
driver.Manage().Window.Maximize();
driver.FindElement(By.Id("username")).SendKeys("Test");
driver.FindElement(By.Id("password")).SendKeys("1");
driver.FindElement(By.Name("submit")).Click();
//driver.Manage().Timeouts().ImplicitWait=TimeSpan.FromSeconds(10);
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
string text = driver.FindElement(By.Id("status")).Text;
Assert.IsTrue(text.Contains("invalid username or password"));
driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));这种可能在后续版本将被移除,官方推荐我们使用driver.Manage().Timeouts().ImplicitWait=TimeSpan.FromSeconds(10);,Selenium API中的截图如下: