JavaScript能与Selenium 2通信吗?

8 投票
4 回答
4046 浏览
提问于 2025-04-16 15:22

我知道我可以让Selenium 2的webdriver运行JavaScript并获取返回值,但因为有很多异步的事情发生,我希望JavaScript能主动和Selenium沟通,而不是反过来。我查了一些资料,但没有找到类似的解决方案。大家一般都是用implicitly_wait吗?这似乎不太靠谱,因为不可能把所有事情的时间都算得很准。一个很好的例子就是让Selenium知道一个XHR请求完成了,或者一个执行时间不确定的异步动画结束了。

这样做可能吗?我们在Saucelabs上使用的是Python的Selenium 2。

4 个回答

2

我直说了,如果你想让你的应用程序和测试工具对话,那你可能走错了方向。

如果你需要等一个XHR(也就是网络请求)完成,可以试着显示一个加载动画,然后测试一下这个动画消失了,来表示请求成功。

关于动画,当动画完成后,可能可以用一个回调函数来添加一个类,表示动画结束了,然后你就可以检查这个类是否存在。

3

理论上这是可能的,但我不建议这样做。

这个解决方案可能需要在网站上运行一些jQuery代码,当JavaScript处理完成后,它会把一个变量设置为真。

你可以让Selenium循环执行一个getEval,直到这个变量变为真,然后在Selenium中执行一些操作。

这样可以满足你的需求,但这真的是个坏主意。如果因为某种原因,你的jQuery没有把触发变量设置为真(或者你期望的状态),那么Selenium就会一直卡在那里,没完没了。你可以给它设置一个很长的超时时间,但那样的话,直接让Selenium执行getEval并等待某个特定元素出现又有什么区别呢?

听起来你是在过度设计你的解决方案,这样做将来会给你带来更多麻烦,而带来的好处却很少。

8

你应该看看execute_async_script()这个方法(在Java中是JavascriptExecutor.executeAsyncScript,在.NET中是IJavaScriptExecutor.ExecuteAsyncScript()),它可以让你等待一个回调函数。这个回调函数会自动加到你JavaScript函数里的arguments数组中。所以,假设你已经在页面上有一个JavaScript函数,它会等到你想要的条件成立,你可以像下面这样做(下面是Java代码,C#和Python的代码应该也差不多):

String script = "var callback = arguments[arguments.length - 1];"
    + "callback(myJavaScriptFunctionThatWaitsUntilReady());";

driver.manage().timeouts().setScriptTimeout(15, TimeUnit.SECONDS);
((JavascriptExecutor)driver).executeAsyncScript(script);

你甚至可以更聪明一点,直接把回调函数传给一个事件,这样就能返回正确的数据。你可以在项目的JavaDocs中找到关于executeAsyncScript()函数的更多信息,项目源代码树里也有示例代码。这里有一个很好的例子,展示了如何等待XHR完成,具体可以在这个文件中找到。

如果在可用于SauceLabs的Python绑定版本中还没有这个功能,我预计很快就会有。老实说,从某种意义上说,这把“轮询期望状态”的工作从你的测试用例转移到了JavaScript中,但这样会让你的测试更易读。

撰写回答