首页 > 解决方案 > 在 Selenium 中测试一个自删除/动态 Webelement

问题描述

我在做什么

我一直在试验 Selenium 并制作了一个简单的程序来让我的 Selenium 测试生活更轻松。其中一部分是测试 webelements 并找出哪些方法(单击提交等)使它们重新加载页面、保持静态或在不重新加载页面的情况下变得陈旧。在这个问题中,我对第三种情况特别感兴趣,因为前两种情况我已经实现了。

我遇到的问题

我遇到的问题是找到一个过时且不会导致页面重新加载的 Web 元素。我想不出一种搜索的好方法,我没有 HTML 和 javascript 技能来制作一个(无论如何),除非我实际测试它,否则我无法验证我的代码是否有效。

我做过/尝试过的事

我想寻找的第一件事是弹出窗口,但它们实际上并不是网页的一部分,而且它们也很不可靠。我想要一些行为一致的东西,否则测试将无法正常工作。我认为动态Webelements,那些在采取行动时会改变定位器的元素将适合我的需求,但我没有找到它们的好方法。任何“自我删除 webelement 示例”“Webelement 过时不会导致页面重新加载示例”或类似内容的谷歌结果,只会给我这样的关于 stackoverflow 的问题,而不是我想要的 - 具体示例。我正在运行的代码只是在 javascript 中等待一个staleReferenceException和一个onload事件。如果staleReferenceException发生但onload事件没有,那么我知道我找到了一个自删除/动态 web 元素(至少我认为这是检测这个的正确方法)。这是我正在运行的代码:

try {
    //wait until the element goes stale
    wait.until(ExpectedConditions.stalenessOf(webElement));
    //init the async javascript callback script
    String script = "var callback = arguments[arguments.length - 1];" +
            "var classToCall = 'SeleniumTest.isPageReloaded';" +
            "window.addEventListener('onload'," + "callback(classToCall));";
    //execute the script and wait till it returns (unless timeout exceeded)
    JavascriptExecutor js = (JavascriptExecutor) driver;
    //execute the script and return the java classname to call 
    //if/when the callback function returns normally
    String classToCall = (String) js.executeAsyncScript(script);
    clazz = Class.forName(classToCall);
    callbackMethod = clazz.getMethod("JavascriptWorking");
    callbackMethod.invoke(null,null);
    //page reloaded
    threadcase = 1;
}
//waiting until webElement becomes stale exceeded timeoutSeconds
catch (TimeoutException e) {
    //page was static
    threadcase = 2;
}
//waiting until webElement Reloaded the page exceeded timeoutSeconds
catch (ScriptTimeoutException e) {
    //the webElement became stale BUT didn't cause a page reload.
    threadcase = 3;

正如您在上面所注意到的,此代码中int命名了一个变量。threadcase从 1 开始的三个“案例”(0 是表示程序流错误的起始值)代表了该测试的三个(非错误)可能结果:

  1. 页面重新加载
  2. 页面保持静态,webelement 不会改变
  3. 页面保持静态,webelement 发生变化

我需要一个很好的例子来测试第三种情况。

我考虑过的解决方案

我已经对删除 javascript 中的 webelements 进行了一些基础研究,但是 IA:我什至不知道我是否可以像那样在 Selenium 中的页面上采取行动和 B:我宁愿得到一个只使用网页的测试用例,因为引入我的编辑使我的测试用例的有效性依赖于我的更多代码(这很糟糕!)。因此,我需要一种找到符合我的标准的 web 元素的好方法,而无需在打开 f12 窗口的情况下搜索互联网,希望找到一个可以满足我需要的按钮。

编辑 1

我只是尝试更手动地进行此测试,在答案中建议我在正确的时间手动删除一个 web 元素,然后以这种方式测试我的程序。我测试的是谷歌主页。我尝试使用谷歌应用程序按钮,因为单击它不会导致整个页面重新加载。所以我的想法是,我会单击它,停止程序执行,手动删除它,运行我的其余代码,并且由于不会发生 onload 事件,我的程序将通过测试。令我惊讶的是,事实并非如此。

我运行的确切代码如下。我在第一行停止了调试:

1   Method callbackMethod = null;
2   try {
3       //wait until the element goes stale
4       wait.until(ExpectedConditions.stalenessOf(webElement));
5       //init the async javascript callback script
6       String script = "var callback = arguments[arguments.length - 1];" +
7           "var classToCall = 'SeleniumTest.isPageReloaded';" +
8           "window.addEventListener('onload', callback(classToCall));";
9       //execute the script and wait till it returns (unless timeout 
10      //exceeded)
11      JavascriptExecutor js = (JavascriptExecutor) driver;
12      //execute the script and return the java classname to call if/when 
13      //the callback function returns normally
14      String classToCall = (String) js.executeAsyncScript(script);
15          clazz = Class.forName(classToCall);
16          callbackMethod = clazz.getMethod("JavascriptWorking");
17          callbackMethod.invoke(null,null);
18          //page reloaded
19          threadcase = 1;
20      }
21      //waiting until webElement becomes stale exceeded timeoutSeconds
22      catch (TimeoutException e) {
23          //page was static
24          threadcase = 2;
25      }
26      //waiting until webElement Reloaded the page exceeded 
27      //timeoutSeconds
28      catch (ScriptTimeoutException e) {
29          //the webElement became stale BUT didn't cause a page reload.
30          threadcase = 3;
31          //trying to get the class from javascript callback failed.
32      }

应该发生的事情是一个陈旧的 webelement 导致程序在第 4 行停止等待,程序继续进行,在第 6-11 行初始化 Javascript 回调,然后在第 14 行调用executeAsyncScript应该等到“onload”事件只有在页面重新加载时才会发生。现在它不这样做,或者我是盲人。我一定是混淆了程序流程,因为我有 99% 的把握在我操纵 DOM 以删除我单击的 web 元素时不会发生页面重新加载。

这是我正在尝试的 URL:

https://www.google.com/webhp?gws_rd=ssl

简单的google主页,我要删除的按钮是google apps按钮(右上角的黑色9格)

关于该元素的一些信息:

类="gb_8 gb_9c gb_R gb_g"

id="gbwa"

它是按钮本身和它创建的下拉菜单的一般容器元素。当我的程序在第 1 行遇到 STOP 时,我将删除它。然后我在调试器中检查我的程序。注意(您可能必须多次单击按钮上的检查元素才能专注于它)。我将尝试删除较低级别的元素而不是整个容器,看看这是否会改变任何东西,但这种行为仍然让我感到困惑。这里的目标是让程序流到 threadcase 3,因为那是我们正在测试的那个。应该没有页面重新加载,但是在我手动删除它之后,webelement 应该变得陈旧。当我看不到页面重新加载时,我不知道为什么 javascript 回调正在运行。如果您需要有关我在谷歌主页上删除的确切内容的更多信息,请告诉我,我

标签: javascriptjavaunit-testingselenium

解决方案


我认为您可以通过测试进行调试,在合适的点放置断点,然后使用浏览器开发工具手动更新 HTML。

显然,如果您希望这是一个可重复的过程,这不是一个选择,但如果您只是在调查,那么手动干预可能是合适的


推荐阅读