【问题标题】:Capybara doesn't wait to complete the submit action on click_button "Save"Capybara 不等待完成 click_button "Save" 上的提交操作
【发布时间】:2017-03-07 15:22:02
【问题描述】:

我有以下 rspec 片段:

   describe "Save should create a ClassificationScheme" do
      subject { lambda { click_button "Save"; sleep 1 } }
      it { should change(ClassificationScheme, :count).by(1) 
   end

如果没有“sleep 1”,水豚不会等待保存按钮触发的操作,并且规范会失败。用sleep 1就可以了,但是有没有更好的办法呢?

请注意,此测试使用 selenium webdriver 在 Firefox 中运行。

我的版本:

  • 导轨 4.1.12
  • rspec 2.99.0
  • 水豚2.4.4
  • selenium-webdriver 3.2.1
  • 火狐 51.0.1

【问题讨论】:

    标签: ruby-on-rails selenium-webdriver rspec capybara


    【解决方案1】:

    当您使用 Capybara 点击某物时,无法保证该点击触发的任何操作在该方法返回时已完成。这是因为 Capybara 除了点击屏幕上的一个元素外,对浏览器在做什么一无所知。您需要检查页面上的视觉变化以指示单击按钮触发的操作已完成,而不是休眠。这可能是一条消息,说明保存成功或元素消失等。类似于

    describe "Save should create a ClassificationScheme" do
      subject { lambda { click_button "Save"; page.should have_text('Classification Saved' } }
      it { should change(ClassificationScheme, :count).by(1) 
    end
    

    注意:您还应该更新 Capybara - 2.4.4 于 2014 年 10 月发布,从那时起有很多改进。

    【讨论】:

    • 我试过你的建议,似乎没问题,有点不可靠。有时测试失败并显示错误:Failure/Error: page.should have_text(I18n.t(:identification) + ':'), expected to find text "Identification:" in ""in "" 很可疑,不知怎么的中间状态被 capybara 捕获了,一个空的页面。
    • @TiborNagy 它应该像您将Capybara.default_max_wait_time 设置为对于您正在运行的硬件而言太短。增加它或将:wait 选项传递给have_text
    • 我也是这么想的,但是Capybara.default_max_wait_time已经是10了。
    • @TiborNagy 然后你需要检查你的测试日志,看看你的应用实际上在做什么。如果 default_max_wait_time 设置为 10,那么 Capybara 将重试最多 10 秒以显示该文本,这意味着您的应用程序没有返回任何内容,或者存在一些奇怪的测试交互。要尝试的另一件事是摆脱主题和 lambda 并更改匹配器,只需写出完整的测试 - 获取计数,单击按钮,拥有文本,再次获取计数并进行比较 - 以确保 RSpec 没有奇怪与主题、lambda 和更改匹配器交互。
    【解决方案2】:

    您没有包含提交操作的代码,但如果有任何异步操作(例如 Ajax 请求),提交操作本身将很快完成,而异步任务仍在处理请求。如果是这种情况,您可以使用这样的助手:

    # spec/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
    
    RSpec.configure do |config|
      config.include WaitForAjax, type: :feature
    end
    

    代码礼貌Thoughtbot

    注意,这仅包括功能规范中的助手;所以要么用type: :feature 标记你的规范,或者更改上面的config.include 行以将其包含在你正在使用的任何规范类型中。

    使用它:

    describe "Save should create a ClassificationScheme" do
        subject { lambda { click_button "Save"; wait_for_ajax } }
        it { should change(ClassificationScheme, :count).by(1) 
    end
    

    【讨论】:

    • wait_for_ajax 是一个应该很少使用的拐杖,尤其是当越来越多的库/框架转向纯 JS 而不是使用 JQuery 时。正确的解决方案是为页面上的视觉变化设定预期。
    • 我同意,但问题仅包括对服务器端更改的测试。理想情况下会有一个视觉指示器,这就是功能规范应该寻找的。记录更新等服务器端更改的测试属于请求规范。
    猜你喜欢
    • 2022-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-15
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 2020-05-15
    相关资源
    最近更新 更多