【发布时间】:2019-03-06 13:09:59
【问题描述】:
我在做什么
我一直在试验 Selenium,并制作了一个简单的程序来让我的 Selenium 测试生活更轻松。其中一部分是测试 web 元素并找出哪些方法(单击提交等)使它们重新加载页面、保持静态或变得陈旧无需重新加载页面。在这个问题中,我对第三种情况特别感兴趣,因为前两种情况我已经实现了。
我遇到的问题
我遇到的问题是找到一个过时且不会导致页面重新加载的 Web 元素。我想不出一种搜索的好方法,我没有 HTML 和 javascript 技能来制作一个(但无论如何),除非我实际测试它,否则我无法验证我的代码是否有效。
我做过/尝试过的事情
我首先想到的是一个弹出窗口,但它们实际上并不是网页的一部分,而且它们也很不可靠。我想要一些行为一致的东西,否则测试将无法正常工作。我认为动态Webelements,那些在采取行动时会改变其定位器的元素将适合我的需求,但我没有找到它们的好方法。 “自删除 webelement 示例” 或 “Webelement 过时不会导致页面重新加载示例” 或类似的任何 google 结果,只会给我这样一个关于 stackoverflow 的问题而不是我想要的——具体的例子。我正在运行的代码只是在 javascript 中等待 staleReferenceException 和 onload 事件。如果staleReferenceException 发生但onload 事件没有发生,那么我知道我找到了一个自删除/动态网络元素(至少我认为这是检测这种情况的正确方法)。这是我正在运行的代码:
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;
正如您在上面看到的,此代码中有一个名为threadcase 的int 变量。从 1 开始的三个“案例”(0 是代表程序流程错误的起始值)代表了该测试的三个(非错误)可能结果:
- 页面重新加载
- 页面保持静态,webelement 不变
- 页面保持静态,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 }
应该发生的事情是一个陈旧的 web 元素导致程序在第 4 行停止等待,程序继续进行,在第 6-11 行初始化 Javascript 回调,然后在第 14 行调用 executeAsyncScript 应该等待直到只有在页面重新加载时才会发生的“onload”事件。现在它不这样做,或者我是盲人。我一定是混淆了程序流程,因为我有 99% 的把握在我操作 DOM 以删除我单击的 web 元素时不会发生页面重新加载。
这是我正在尝试的 URL:
https://www.google.com/webhp?gws_rd=ssl
简单的谷歌主页,我要删除的按钮是谷歌应用按钮(右上角的黑色9格)
关于该元素的一些信息:
class="gb_8 gb_9c gb_R gb_g"
id="gbwa"
它是按钮本身和它创建的下拉菜单的通用容器元素。当我的程序在第 1 行遇到 STOP 时,我将删除它。然后我在调试器中检查我的程序。注意(您可能必须多次单击按钮上的检查元素才能专注于它)。我将尝试删除较低级别的元素而不是整个容器,看看这是否会改变任何东西,但这种行为仍然让我感到困惑。这里的目标是让程序流到 threadcase 3,因为那是我们正在测试的那个。应该没有页面重新加载,但是在我手动删除它之后,webelement 应该变得陈旧。当我看不到页面重新加载时,我不知道为什么 javascript 回调正在运行。如果您需要有关我在 Google 主页上删除的具体内容的更多信息,请告诉我,我会尝试发送图片(当然还有可选的手绘圆圈)。
【问题讨论】:
-
试试this example。这是一系列下拉菜单。您也可以尝试一些您选择品牌的汽车网站,该网站会填充模型下拉列表。根据它们的创建方式,您可能会找到您正在寻找的示例。
标签: javascript java unit-testing selenium