waitForElement 与 Cucumber +硒

发布于 2024-11-07 21:28:02 字数 731 浏览 0 评论 0原文

大家好,我正在尝试修复我的众多场景,这些场景使用高级 AJAX 测试页面,并通过 JQuery 构建客户端屏幕,但遇到了很多问题。

主要是,我无法知道某些 AJAX 请求何时完成。我尝试过延迟睡眠,但从长远来看这不是一个好主意。我还尝试了网上找到的几种方法来检查 AJAX 调用是否全部完成,但这些方法似乎不够稳定。

我开始更多地探索 Selenium 并发现了 waitForXXX 函数。我很兴奋,把它们扔进了我的黄瓜台阶里,但没有运气。我当前的测试用例是一个动态加载的网格,它通过 AJAX 获取其数据。 (Jquery 数据网格插件)。我正在通过查找第一个非标题行来查找数据,然后单击它。单击该元素的代码是:

page.all(:css, "#{arg1} tr")[1].click();

有时这有效,但通常不起作用,因为该行尚未加载。所以我在尝试:

waitForElementPresent("css=#{arg1} tr:nth-child(1)")

在单击该行之前,但是每当到达该行代码时,我都会从 ruby​​ 中收到一个奇妙的错误:

stack level too deep (SystemStackError)

我做错了什么,是否有更好的方法来编写这些步骤以确保它们确实有效等待 AJAX 调用完成?

请注意,应用程序本身运行良好 - 这只是为了让我的测试代码可靠地变绿。

Hey all, I'm trying to fix up my numerous scenarios that test out pages with advanced AJAX and client side screen building via JQuery and having a ton of issues.

Mainly, I'm having trouble knowing when certain AJAX requests are done. I've tried just putting in sleep delays but that's a bad idea long term. I've also tried a couple methods I found online to check to see if the AJAX calls are all done, but these methods don't seem stable enough.

I started exploring Selenium more and found the waitForXXX functions. Excited I threw them into my cucumber steps but no luck. My current test case is a dynamically loaded grid that gets its data over AJAX. (Jquery Datagrid plugin). I'm looking for data to be there by looking for the first non-header row, then I click it. The code to click the element is:

page.all(:css, "#{arg1} tr")[1].click();

Sometimes this works, often it doesn't because the row hasn't loaded yet. So I was trying:

waitForElementPresent("css=#{arg1} tr:nth-child(1)")

before clicking the row, but whenever it gets to that line of code I get a wonderful error from ruby:

stack level too deep (SystemStackError)

What am I doing wrong, and is there a better way to write these kinds of steps to make sure they really wait for the AJAX call to finish?

Note that the app itself works fine - this is just to get my testing code to go green reliably.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

愛上了 2024-11-14 21:28:02

我很幸运地完成了下面的步骤(这是我们从其他人那里获取的)。它最初是针对 culerity/celerity(我们使用过一段时间)的,但它对于普通黄瓜/水豚:

When /^I wait for the AJAX call to finish$/ do
  keep_looping = true
  while keep_looping do
    sleep 0.10
    begin
      count = page.evaluate_script('window.running_ajax_calls')
      keep_looping = false if count.respond_to?(:to_i) && count.to_i == 0
    rescue => e
      raise e
    end
  end
  sleep 0.20
end

您可能需要调整循环睡眠和睡眠后。这些值非常适合同时运行 12 个核心测试的 Mac Pro。在极少数情况下,我们会额外增加 1 秒的等待时间。

I've had very good luck with the step below (which we pulled from someone else). It was originally geared towards culerity/celerity (which we used for a time), but it's been quite good for plain cucumber/capybara:

When /^I wait for the AJAX call to finish$/ do
  keep_looping = true
  while keep_looping do
    sleep 0.10
    begin
      count = page.evaluate_script('window.running_ajax_calls')
      keep_looping = false if count.respond_to?(:to_i) && count.to_i == 0
    rescue => e
      raise e
    end
  end
  sleep 0.20
end

You may have to tweak the looping sleep and after sleep. These values work great for a Mac Pro that runs 12 cores of tests at the same time. In a very small number of circumstances, we've added an additional 1 second wait.

行雁书 2024-11-14 21:28:02

我倾向于在尝试与元素交互之前调用 has_css? 方法,例如

page.should have_css("#{arg1} tr")

Capybara 将重试,直到(可配置的)默认等待时间到期。一旦通过此步骤,您应该能够按预期单击该元素 - 或者,如果该元素在等待时间到期之前没有出现,则该步骤将失败。

I tend to call the has_css? method before attempting to interact with the element e.g.

page.should have_css("#{arg1} tr")

Capybara will retry until the (configurable) default wait time has expired. Once this step has passed, you should then be able to click the element as expected - alternatively the step will fail if the element does not appear before the wait time expires.

ぽ尐不点ル 2024-11-14 21:28:02

感谢 Alistar 关于 page.should have_css 的提示,我编写了一个通用示例。如果同时进行多个 AJAX,这可能不起作用,但对我来说它相当轻量。

在我的 application.html.erb 中,我包含了一个简单的空白 div:

<div id="ready"/>

然后在应用程序启动时加载的 javascript 文件中,我添加了这一行以在进行 AJAX 调用时隐藏 div。

$('#ready').ajaxStart(function(){$(this).hide();}).ajaxStop(function(){$(this).show();});

然后,在 Cucumber 的常见步骤中,我有一个非常简单的“等待 AJAX”步骤定义:

When /^I wait for AJAX$/ do
page.should have_css("#ready")

end

在第一次测试中,这似乎有效。这是给猫剥皮的另一种方法,所以它可能不会一直有效,但在我的情况下,它对我来说很好而且很轻。

Thanks to Alistar's hint about page.should have_css, I worked up a generic example. This probably won't work if there are multiple AJAX going on at once, but its pretty lightweight for me.

In my application.html.erb I included a simple blank div:

<div id="ready"/>

Then in my javascript file that's loaded when the app starts, I added this line to hide the div when there is an AJAX call going on.

$('#ready').ajaxStart(function(){$(this).hide();}).ajaxStop(function(){$(this).show();});

Then in my common steps for Cucumber, I have a very simple "Wait for AJAX" step definition:

When /^I wait for AJAX$/ do
page.should have_css("#ready")

end

At first test, this seems to work. Its yet another way to skin the cat, so it may not work all the time, but it is nice and lightweight for me in my situation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文