【问题标题】:What's the alternative to use Thread.Sleep when working with Selenium in system testing?在系统测试中使用 Selenium 时使用 Thread.Sleep 的替代方法是什么?
【发布时间】:2012-01-26 17:15:58
【问题描述】:

我有一个使用 Selenium 的测试方法,如下所示:

 [TestMethod]
        public void ShouldSendPasswordReminder()
        {
            // go to loginregister url
            _fireFoxWebDriver.Navigate().GoToUrl(UkPaBaseUrl + "loginregister.aspx");
            Thread.Sleep(1000);

            // click the forgotten password
            _fireFoxWebDriver.FindElement(By.LinkText("Forgotten your password?")).Click();
            Thread.Sleep(1000);

            // enter your email address

            _fireFoxWebDriver.FindElement(By.Id("PasswordResetRequest1_PasswordResetRequest_Username"))
                .SendKeys("username.lastname@domain.com");
            Thread.Sleep(1000);

            // click submit
            _fireFoxWebDriver.FindElement(By.Id("PasswordResetRequest1_PasswordResetRequest_PasswordResetRequestSubmit")).Click();
            Thread.Sleep(5000);

            // assert
            Assert.IsTrue(_fireFoxWebDriver.Url.Contains("ThankYou"));
        }

如您所见,几乎在每次操作之后,我都必须多次调用 Thread.Sleep(因为页面可能需要一些时间才能完成它所做的事情,因为 javascript 等),因为 Selenium 似乎不是能够处理与 WatiN 不同的页面加载和延迟。

这使得代码相当丑陋而且不太可靠。

处理这种情况的更好方法是什么?您是否也在测试中编写频繁的 Thread.Sleep 调用?

谢谢,

【问题讨论】:

标签: c# unit-testing selenium mstest system-testing


【解决方案1】:

您可以使用管理功能来设置您希望FindElement() 在失败前等待的基线时间:

_fireFoxWebDriver.Manage()
                 .Timeouts()
                 .ImplicitlyWait(TimeSpan.FromSeconds(1000));

【讨论】:

【解决方案2】:

显式等待。 根据官方文档(http://www.seleniumhq.org/docs/0...),Thread.sleep() 是显式等待的最坏情况。

在显式等待中,不等待最长时间结束,只要条件发生,如果该条件在指定的最长时间结束之前发生,它就会继续。因此必须等到最长时间(因为在指定的最长时间内条件没有发生)是显式等待的最坏情况。

我认为 Thread.sleep() 被认为是显式等待的最坏情况,因为对于 Thread.sleep(),它必须等待指定为 Thread.sleep() 参数的完整时间,然后再继续进行.

你可能会想为什么 Thread.sleep() 不是隐式等待。我认为这是因为 Thread.sleep() 的效果只在它被写入的地方,比如显式等待。然而,隐式等待的影响是针对驱动程序实例的整个生命周期。

**JAVA**
WebDriver driver = new FirefoxDriver();
driver.get("http://somedomain/url_that_delays_loading");
WebElement myDynamicElement = (new WebDriverWait(driver, 10)).until(ExpectedConditions.presenceOfElementLocated(By.id("myDynamicElement")));

**C#**
using (IWebDriver driver = new FirefoxDriver())
{
driver.Url = "http://somedomain/url_that_delays_loading";
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
IWebElement myDynamicElement = wait.Until<IWebElement>(d => d.FindElement(By.Id("someDynamicElement")));
}

这会在抛出 TimeoutException 之前等待最多 10 秒,或者如果它发现元素将在 0 - 10 秒内返回它。

我的示例代码,我的测试用例希望我最多等待 10 秒,之前我在使用 Thread.Sleep 找到下一个元素之前等待了 10 秒。现在我使用 WebDriverWait,所以如果找到该元素,它会继续执行,这会加快我的日常活动并节省时间。

using (IWebDriver driver = new ChromeDriver(options))
        {
            TimeSpan t = TimeSpan.FromSeconds(10);
            WebDriverWait wait = new WebDriverWait(driver,t);
            try
            {  
                driver.Navigate().GoToUrl("URL");
                //IWebElement username = driver.FindElement(By.Name("loginfmt"));
                IWebElement username = wait.Until(ExpectedConditions.ElementIsVisible(By.Name("loginfmt")));                                      
                username.SendKeys(dictionaryItem);
                //Thread.Sleep(10000); Removed my Thread.Sleep and tested my wait.Until and vola it works awesome.
                IWebElement next = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("idSIButton9")));
                //IWebElement nextdriver.FindElement(By.Id("idSIButton9"));
                next.Click();

【讨论】:

    【解决方案3】:

    当我的脚本比我的应用程序更快时引入延迟的一般启发式方法是真正考虑我在等待什么。在我看来,睡眠类型的调用实际上只适用于我实际上在等待时间过去的情况。在我测试自动超时的情况下,在其中调用 Thread.sleep 类型可能是有意义的,因为我实际上是在等待特定的时间过去。然而,通常,我正在等待其他事情发生——要加载的页面、要执行的 javascript 等等。在这些情况下,等待一段设定的时间似乎是一种简单的方法,似乎可以克服检查的潜在更大复杂性对于我真正在等待的东西。但是,这有多个陷阱-您可能会过多地减慢测试速度(例如,如果您在上面的每个等待时间只需要 200 毫秒,那么现在即使是上面的简短 sn-p 也需要额外的 2.5 秒(这是没有调整的)最后的 5 秒等待)。这本身可能看起来并不多,但随着你的套件变大,它会加起来。)另一个陷阱发生在你移动到较慢的机器或环境因素减慢你的应用程序时 - 如果它花了怎么办1.5 秒后,您可以点击忘记密码?一台机器上的链接。您的测试会失败,但这可能仍然在您的应用程序可接受的性能阈值范围内,因此您现在有一个错误的失败。这通常通过简单地增加等待时间来解决,但这又回到了我再次提到的第一个陷阱。

    为了打破这个循环,我发现在等待事情时尽可能具体是非常重要的。 Selenium 提供了一个 Wait 类,可用于等待满足特定条件。我不知道 .Net 绑定是否包含它,但我会期待它使用它们。在 Ruby 版本中,我们给 Wait 一个代码块 - 它可以查找元素的存在或我们需要检查的任何其他内容。 wait 方法获取一个超时值和一个间隔值,然后每隔间隔秒运行一次块,直到块返回 true 或超时期限已过。设置这样的类允许您将超时值设置得足够高以处理性能规模的低端,但不会因在给定运行中等待的时间比实际需要的时间长很多。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 1970-01-01
      • 1970-01-01
      • 2011-08-11
      • 2021-09-18
      • 1970-01-01
      相关资源
      最近更新 更多