Selenium异常处理,问题

时间:2015-11-02 09:03:07

标签: java selenium selenium-webdriver automated-tests

我遇到了Java Selenium的问题。我用它来自动化测试网页,结构非常复杂 - 动态加载很多元素,html页面中有很多不必要的元素。让我的测试可靠是非常困难的。有时页面无法加载或我尝试点击尚不存在的按钮(当然用类似的方法)。

所以,我用这样的方法编写了Util类:

public static void findAndSendKeys(String vToSet, By vLocator) {
    log.info("findAndSendKeys " + vLocator.toString());
    int attempts = 0;
    while (attempts < ATTEMPTS) {
        WebElement element = null;
        try {

            element = webDriverWait.until(ExpectedConditions.presenceOfElementLocated(vLocator));
            element.sendKeys(vToSet);
            break;

        } catch (TimeoutException e) {
            log.error("timeOut exception " + e.getMessage());
        } catch (StaleElementReferenceException e) {
            log.error("StaleElementReference exception " + e.getMessage());
        } catch (UnhandledAlertException e) {
            log.error("UnhandledAlert exception " + e.getMessage());
            Alert alert = driver.switchTo().alert();
            alert.accept();
        }
        attempts++;
    }
}

我知道它看起来很糟糕,我还没有对它进行重构,但是对于大多数情况,方法通常都能正常工作 - 在第二个或第三个循环输入字段上填充。

首先我只使用带有异常处理的sendKeys,但是我注意到虽然存在输入字段,但是抛出StaleElementReferenceException,所以我将while()放在这个静态方法中并尝试再次发送Keys。 有时我的webPage显示只是验证的警报,在捕获异常并忽略警报后,我可以继续工作。

我想知道..如果在Selenium IDE中存在类似于“Pause 1000”方法的方法,可能会更容易。有时我的网页工作得很快,很好,有时页面加载过程很长,我不得不等待。

while()循环也存在问题。我不知道如果while循环结束并且没有发送任何内容该怎么办 - 例如加载的页面/容器是空白的,动态加载失败,所以没有机会找到我们的输入字段

自动化此网页的测试过程让我头疼。请原谅,我没有技术支持,而且我独自一人。

2 个答案:

答案 0 :(得分:0)

在我看来,你正试图过度设计整个事情。我认为你正在尝试编写一个能够处理所有情况的函数,我认为这不是一个好方法。每个案例都可能有所不同,您需要了解每个案例并妥善处理。

一些提示。

  1. 不要循环wait.until()。而不是

    for (int i = 0; i < 5; i++)
    {
        WebDriverWait wait = new WebDriverWait(driver, 10);
        wait.until(...);
    }
    

    DO

    WebDriverWait wait = new WebDriverWait(driver, 50);
    wait.until(...);
    

    最终结果是相同的(最多50秒等待),但第二个代码不那么令人困惑。阅读等待以更好地理解它们。等待的默认行为是等待最长时间并每500ms轮询一次条件。

  2. 如果你得到StaleElementReferenceException,你就会遗漏一些东西。我并不是说这听起来很关键......它发生了。你需要了解页面的HTML是如何变化的,因为你正在寻找一个正在消失的元素,而然后你试图抓住它。您需要更改要查找的元素或查找元素。

  3. 请勿使用Thread.sleep()。一般来说,这是一种不好的做法,因为它是硬编码的。根据环境的不同,可能太长或等待时间不够长。而是更喜欢您已经使用的wait.until()机制。有时,困难的部分是找到等待的东西。

  4. 如果您在项目排序后尝试抓取页面,则需要确定排序后的更改。也许列标题上有一个箭头,表示排序方向(升序与降序)?你可以做的一件事是抓住一个TD元素,等待它变得陈旧(当元素被分类时),然后重新调整所有元素?

    也许是这样的

    WebDriverWait wait = new WebDriverWait(driver, 10);
    // grab the first TD as a stale reference
    WebElement td = driver.findElement(By.tagName("td"));
    // wait for it to go stale
    wait.until(ExpectedConditions.stalenessOf(td));
    // now grab them all and do something with them
    List<WebElement> tds = driver.findElements(By.tagName("td"));
    

    如果没有指向页面的链接或对页面上发生的事情和一些相关HTML的更多解释,我不确定我们还能提供什么。

答案 1 :(得分:0)

此代码适用于我:

jsPageLoadWait ="
try {
  if (document.readyState !== 'complete') {
    return false; // Page not loaded yet
  }
  if (window.jQuery) {
    if (window.jQuery.active) {
      return false;
    } else if (window.jQuery.ajax && window.jQuery.ajax.active) {
      return false;
    } else if ($(':animated').length != 0) {
      return false;
    }
  }
  if (window.angular) {
    if (!window.qa) {
      // Used to track the render cycle finish after loading is complete
      window.qa = {
        doneRendering: false
      };
    }
    // Get the angular injector for this app (change element if necessary)
    var injector = window.angular.element('body').injector();
    // Store providers to use for these checks
    var $rootScope = injector.get('$rootScope');
    var $http = injector.get('$http');
    var $timeout = injector.get('$timeout');
    // Check if digest
    if ($rootScope.$$phase === '$apply' || $rootScope.$$phase === '$digest' || $http.pendingRequests.length !== 0) {
      window.qa.doneRendering = false;
      return false; // Angular digesting or loading data
    }
    if (!window.qa.doneRendering) {
      // Set timeout to mark angular rendering as finished
      $timeout(function() {
        window.qa.doneRendering = true;
      }, 0);
      return false;
    }
  }
  return true;
} catch (ex) {
  return false;
}"



public static Boolean WaitLoad(this ISearchContext context, UInt32 timeoutInMilliseconds = 10000, UInt32 millisecondPolling = 1000)
{
  Boolean waitReadyStateComplete;

  var wait = new DefaultWait<ISearchContext>(context);
  wait.Timeout = TimeSpan.FromMilliseconds(timeoutInMilliseconds);
  wait.PollingInterval = TimeSpan.FromMilliseconds(millisecondPolling);
  wait.IgnoreExceptionTypes(typeof(NoSuchElementException), typeof(StaleElementReferenceException));

  waitReadyStateComplete = wait.Until<Boolean>(ctx =>
  {
    if ((Boolean)((IJavaScriptExecutor)context).ExecuteScript(jsPageLoadWait))
      return true;
    else
      return false;
  });

  return waitReadyStateComplete;
}