使用Cucumber + Selenium的waitForElement

时间:2011-05-18 15:21:14

标签: ruby-on-rails-3 testing selenium cucumber

嘿所有,我正在尝试修复我的众多场景,通过JQuery测试高级AJAX和客户端屏幕构建的页面,并且遇到大量问题。

主要是,我很难知道某些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​​调用完成?

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

3 个答案:

答案 0 :(得分:1)

我在下面的步骤(我们从其他人那里取得)中获得了很好的运气。它是originally geared对于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秒等待。

答案 1 :(得分:1)

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

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

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

答案 2 :(得分:0)

感谢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")

首次测试时,这似乎有效。它是另一种皮肤猫的方式,所以它可能不会一直起作用,但在我的情况下它对我来说很好而且轻巧。