大家好,我正在尝试修复我的许多场景,这些场景使用高级 AJAX 测试页面并通过 JQuery 构建客户端屏幕,并遇到了大量问题。
主要是,我无法知道某些 AJAX 请求何时完成。 我试过只是延迟睡眠,但从长远来看这是一个坏主意。 我还尝试了几种我在网上找到的方法,以查看 AJAX 调用是否全部完成,但这些方法似乎不够稳定。
我开始更多地探索Selenium,并发现了waitForXXX功能。 兴奋的我把它们扔进了我的黄瓜台阶,但没有运气。 我当前的测试用例是一个动态加载的网格,它通过 AJAX 获取其数据。(Jquery Datagrid 插件)。 我正在通过查找第一个非标题行来查找数据,然后单击它。 单击该元素的代码为:
page.all(:css, "#{arg1} tr")[1].click();
有时这有效,通常不起作用,因为行尚未加载。 所以我在尝试:
waitForElementPresent("css=#{arg1} tr:nth-child(1)")
在单击该行之前,但是每当它到达该行代码时,我都会从 ruby 那里得到一个很棒的错误:
stack level too deep (SystemStackError)
我做错了什么,有没有更好的方法来编写这些步骤以确保它们真的等待 AJAX 调用完成?
请注意,应用程序本身运行良好 - 这只是为了让我的测试代码可靠地绿色运行。
下面的步骤中运气很好(我们从其他人那里拉出来的)。它最初是针对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 秒等待时间。
我倾向于在尝试与元素交互之前调用has_css?
方法,例如
page.should have_css("#{arg1} tr")
Capybara 将重试,直到(可配置的)默认等待时间到期。完成此步骤后,您应该能够按预期单击该元素 - 或者,如果该元素在等待时间到期之前未出现,则该步骤将失败。
感谢Alistar关于page.should have_css的提示,我做了一个通用的例子。 如果同时有多个 AJAX 运行,这可能不起作用,但它对我来说非常轻量级。
在我的应用程序.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")
结束
在第一次测试中,这似乎有效。 这是另一种给猫剥皮的方法,所以它可能不会一直有效,但在我的情况下,它对我来说既好又轻。