2012-09-23 15 views
12

我有一个失败的Rails集成测试,我不明白为什么。我使用硒水银作为司机。异步JavaScript的水豚一体化测试

在AJAX调用发生后,测试检查页面内容已被删除。相关的操作是单击一个按钮,并且该按钮单击会导致页面的一部分通过jQuery remove()调用被删除。以下是集成测试代码的近似值:

click_button("Remove stuff") 
assert has_no_link?("This should be removed") 

断言失败,意味着链接仍然存在。

我一直在读水豚,我知道你可以延长默认的等待时间。我已经将它扩展到一个荒谬的价值(20秒),并且仍然断言失败。

当我手动按照测试过程我自己,在源页面仍显示的内容,但DOM不(通过查看Firefox的DOM查看和寻找的元素)。这是问题吗?我甚至尝试检查DOM ,而测试在Firefox中运行,以检查内容是否存在,并且看起来不是这样。

我不知道Capybara是如何找到这个不再存在于DOM中的链接的。 Capybara检查源代码而不是DOM并在那里找到链接?如果是这样,我不知道如何解决这个测试,以确保测试通过。刷新页面将解决问题,但这不完全是一个用户会做什么,所以我犹豫改变页面只是为了使测试通过...

会爱如何解决这个问题的任何建议。

谢谢!

+1

你终于找到了解决问题的办法吗?我有一个类似的,我想知道你是否可以对我有任何帮助。 –

+1

不幸的是,不幸的是没有。我花了太多时间让单个测试工作,所以我最终只是评论它而不是修复它。对不起,我无法提供更多的帮助......我已经花了很多时间,没有精力去深入探索!随意回答这个问题,如果你想出来,我会很乐意给你信用! – aardvarkk

+0

您是否记得在您的rspec中包含'js:true'? – RubeOnRails

回答

0

有一个简单的方法来检查ajax请求是否完成,我从this article了解到。可以使用ajax $.active函数(这是not in the actual API but is exposed,以便您可以使用它)而不是wait$.active告诉你的活动连接数的服务器,所以当它下降到零,你知道Ajax请求完成:

wait_until do 
    page.evaluate_script('$.active') == 0 
end 

如果不工作,那么问题是在其他地方(从判断你写的东西似乎很可能)。如果更改只发生在DOM中,那么您必须确保为您的测试/规范启用了javascript。例如,在rspec中,您设置了:js => true来执行此操作;在Cucumber中,您在@javascript之上添加一行。我不使用rails的默认测试,但是必须有一个设置来执行相同的操作。

+0

嗯...我使用的是Capybara下的Selenium驱动,它默认支持JavaScript测试(请参阅https://github.com/jnicklas/capybara#drivers)。我试着添加你的等待代码,但没有解决它。好主意虽然!只是还没有解决... – aardvarkk

+0

你使用水豚的任何其他测试涉及JavaScript? –

+0

是的,但这是唯一寻找*删除*信息的人。所有其他的东西似乎工作...例如,检查AJAX查询导致新的按钮或更改内容。但是关于jQuery'remove()'的东西似乎并没有坐好。如果我检查'page.html',它仍然显示那里的内容,所以这里肯定有问题。 – aardvarkk

0

你是第一次用链接测试别的东西,然后测试它被删除了吗?

换句话说,就是你的测试是这样的:

has_no_link = $('#id_for_link') 
//.... some test 
click_button("Remove stuff") 
assert has_no_link?("This should be removed") 

如果是这样的话,那么has_no_link仍将指向的链接。 remove()会将它从DOM中移除,但是你的变量仍然指向它的内存。

您应该再次在DOM中查询链接以查看您是否得到结果。

0

我不得不重写wait_until进行测试,其中包含等待通过将YouTube视频流式传输到特定点触发的回调。下面是我用什么:

# in spec_helper.rb 
require "timeout" 
def wait_until time=0.1 
    Timeout.timeout(Capybara.default_wait_time) do 
     sleep(time) until value = yield 
     value 
    end 
end 
+1

有关更多最新版本的水豚,请注意'default_wait_time'已被弃用。现在使用'default_max_wait_time'。 – Sia

0

夫妇的办法我认为是:

1:检查你的水豚版本,并期待与您的版本的任何错误

2:也许尝试在做一个查找按钮后链接被点击

click_button( “删除的东西”) 发现。(:XPath中, '//一个[文本()=' 链接应该删除')应该be_false

3:使用has_link?而不是has_no_link?

click_button( “删除的东西”) page.has_link?( “链接应删除”)。应be_false

0

你总是可以手动执行此操作。使用@ shioyama的想法:

def wait_for_ajax 
    timer_end = Time.now + 5.seconds 
    while page.evaluate_script('$.active') != 0  
     if Time.now > timer_end 
     fail "Page took more than 5 seconds to load via ajax" 
     end 
     sleep 0.1 
    end 
    end 
3

Thoughtbot对等待AJAX​​,但它是基于Rspec的,你可以阅读here,一个伟大的博客文章,它看起来像你正在使用TestUnit。

它适用于水豚不够长时间等待的情况,但不会增加不必要的长时间停顿。我在Rspec的工作大多了,但我认为你可以通过这样修改:

# Create this file in test/support/wait_for_ajax.rb 
module WaitForAjax 
    def wait_for_ajax 
    Timeout.timeout(Capybara.default_max_wait_time) do 
     loop until finished_all_ajax_requests? 
    end 
    end 

    def finished_all_ajax_requests? 
    page.evaluate_script('jQuery.active').zero? 
    end 
end 

您可以包括它需要在各个测试文件时,或者使用this SO post自动包括所提供的策略之一它每一次。

然后,只要你有一个测试,没有正确等待AJAX​​完成,只需插入行wait_for_ajax。以你的代码为例:

click_button("Remove stuff") 
wait_for_ajax 
assert has_no_link?("This should be removed")