当前位置: 首页 > 知识库问答 >
问题:

Selenium异常处理、问题

薛保臣
2023-03-14

我对Java硒有问题。我用它来自动化测试web页面,它的结构非常复杂--大量的元素是动态加载的,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++;
    }
}

我知道它看起来很糟糕,我还没有重构它,但是method通常在大多数情况下工作良好--在第二个或第三个循环中输入字段被填充。

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

我想知道..如果有类似于Selenium IDE中的“暂停1000”方法,则会更容易。有时我的网页工作速度快,效果好,有时页面加载过程很长,我必须等待。

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

这个网页的自动化测试过程让我头疼。拜托,请放心,我没有技术支持,我只能靠自己。

共有2个答案

孙琨
2023-03-14

这段代码适用于我:

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;
}
丁晋
2023-03-14

在我看来,你是想把整件事想得太过分了。我认为您试图编写一个可以处理所有情况的函数,但我认为这不是一个好方法。每种情况都可能是不同的,您需要理解每种情况并适当地处理它。

一些小窍门。

>

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

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

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

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

    如果您正在获取StaleElementReferenceException,那么您缺少了一些东西。我不是说这是批评...这是常有的事。您需要了解页面的HTML是如何变化的,因为您正在寻找一个正在消失的元素,然后您尝试刮去它。您将需要更改您正在查找的元素或您正在查找它的时间。

    不要使用thread.sleep()。一般来说,这是一个糟糕的实践,因为它是硬编码的。根据环境的不同,等待时间可能太长,也可能不够长。相反,更喜欢您已经使用的wait.untial()机制。有时,困难的部分是找到等待什么。

    如果您试图在项目排序后刮取页面,那么您需要确定排序发生后发生了哪些更改。可能列标题上有一个箭头,显示排序方向(升序和降序)?您可以做的一件事是抓取其中一个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,我不确定我们还能提供什么。

  •  类似资料:
    • 问题内容: 我有一个关于异常处理的问题。考虑以下Java代码段。 我知道这是处理异常的推荐方法。但是我可以通过使用以下代码片段来实现相同的目的。 有人可以告诉我第二种方法的弊端吗? 问题答案: 第二种方法可读性较差。此外,即使“聪明”的窍门是使用instanceof关键字,Pokemon异常处理也永远不会走。无论如何,我不是在取笑或嘲笑您,但最好是编写供人类阅读和维护的代码,而不是计算机。

    • 我不知道该怎么办。 当我试图从解析器获取语法错误的数量时,它显示0。 编辑: 它返回null。

    • Blade 内置了 异常处理器,在开发者模式下它会将异常输出在前端页面,并在控制台打印堆栈信息,生产环境只打印在控制台。 有些时候不满足我们的需求,这时候就需要自定义异常处理了,比如针对某个自定义的异常进行特殊处理。 我们用一个例子来解释如何操作。 定义了一个名为 TipException 的运行时异常类,用于输出错误消息到前台。 按照上面对异常的处理情况这个异常的堆栈信息会被输出在控制台,生产环

    • 任何方法都可以抛出不同类型的异常。这些异常可能是需要应用程序重新部署来解决的编程错误,或者是不需要重新部署但可以解决的暂时性错误。 Hangfire可以处理所有内部的(属于Hangfire本身)和相关的外部方法(任务,过滤器等)的异常,因此不会导致整个应用程序被关闭。所有内部异常都被记录(所以不要忘记 启用日志),最糟糕的情况是导致后台任务被暂停并延时重试 10 次。 当Hangfire遇到在执行

    • 我们在编写程序的时候,经常需要对异常情况做处理。比如,当一个数试图除以 0 时,我们需要捕获这个异常情况并做处理。你可能会使用类似 if/else 的条件语句来对异常情况做判断,比如,判断除法的分母是否为零,如果为零,则打印错误信息。 这在某些简单的情况下是可以的,但是,在大多数时候,我们应该使用 Python 的异常处理机制。这主要有两方面的好处: 一方面,你可以选择忽略某些不重要的异常事件,或

    • 异常处理可以使程序在流程上更加完善。 在 JavaScript 中可以使用 throw 抛出异常,使用 try ... catch 捕获错误。 1. throw throw 语句用来抛出一个用户自定义的异常。(MDN) throw 用于抛出一个异常,这种异常通常是程序出现了不符合预期的错误。 alert('出错前'); throw '发生了一个错误!'; alert('出错后'); 当出现