【问题标题】:Invoke Coffeescript during Capybara tests在 Capybara 测试期间调用 Coffeescript
【发布时间】:2018-05-31 08:19:08
【问题描述】:

我的应用程序有很多不同的地方,当用户单击按钮/链接/div 时,我通过调用 ajax 函数来更新数据库。我需要在我的测试中包含这些功能,但我对 Capybara 的了解还不够。

下面是我想要测试的一个 div、关联的 ajax 调用以及我想要通过的测试的示例。我应该补充一点,我正在通过 Cloud9 IDE 构建,以防万一。

查看

<% @seminar.students.order(:last_name).in_groups_of(6).each do |group| %>
    <div class="row">
        <% group.each do |student| %>
            <% if student %>
               <% this_ss = @seminar.seminar_students.find_by(:user => student) %>
                  <% if this_ss.present %>
                       <% thisClass = "col-md-2 seat clickySeat" %>
                       <% thisText = "Present" %>
                  <% else %>
                       <% thisClass = "col-md-2 seat clickySeat absent" %>
                       <% thisText = "Absent" %>
                  <% end %>
                  <div class = "<%= thisClass %>" id="<%= this_ss.id %>" name="ss_<%= this_ss.id %>">
                      <%= student.first_plus_init %><br/>
                      <p class="presentTag"><%= thisText %></p>
                  </div>
               <% end %>
         <% end %>
    </div>
<% end %>

咖啡脚本

if $('.clickySeat').length > 0
    $('.clickySeat').on "click", ->
        this_tag = $(this).find(".presentTag")
        seminar_student_id = $(this).attr('id')
        url = '/seminar_students/'+seminar_student_id
        if this_tag.text() == "Absent"
            attendance = true
            $(this).removeClass("absent")
            this_tab.text("Present")
        else
            attendance = false
            $(this).addClass("absent")
            this_tab.text("Absent")
        $.ajax
            type: "PUT",
            url: url,
            dataType: "json"
            data:
                seminar_student:
                    present: attendance

测试

test "attendance with click" do
    @ss = @student_3.seminar_students.find_by(:seminar => @seminar)
    assert @ss.present

    capybara_login(@teacher_1)
    click_on("desk_consult_#{@seminar.id}")
    click_on("#{new_consultancy_button_text}")
    find("##{@ss.id}").click

    assert_not @ss.present
    click_on("Create Desk Consultants Groups")
end

在开发和生产中,div 和 ajax 正在努力切换学生在数据库中被标记为缺席/在场。但在测试中,行 assert_not @ss.present 失败。这是我试图在所有地方修复的模式:我的水豚测试都没有调用任何 javascript。

我已经阅读了一些类似的问题和相关文章。我已经尝试了到目前为止我读过的所有建议,例如添加 selenium-webkit gem,以便我可以使用 Capybara.javascript-driver = :selenium 行。到目前为止,我遇到的任何解决方案都没有为我工作。

提前感谢您提供任何见解。

【问题讨论】:

  • 你没有告诉我们你想通过的测试到底是什么失败了。此外,当您设置 Capybara.javascript_driver 时,它仅用于您指定使用支持 javascript 的驱动程序的测试。见-github.com/teamcapybara/capybara#selecting-the-driver。您应该能够判断它是否使用 selenium,因为它通常会打开 Firefox 或 Chrome 的实例(取决于您的配置)。
  • 啊哈。好点子。测试在 assert_not @ss.present 行上失败。在开发和生产中,单击 div 会更新数据库以在学生在缺席和在场之间切换。在测试中,没有任何反应。
  • 这是我试图到处修复的模式:我的水豚测试都没有调用任何 javascript。

标签: ruby-on-rails ajax coffeescript capybara


【解决方案1】:

您可以尝试Poltergeist 驱动程序并更改配置以使用它。不要忘记在您的路径上安装 PhantomJS(您可以使用以下命令安装它:npm install -g phantomjs

您应该在测试的某些部分添加js: true,我只是不记得在哪里。但是,您可以搜索它。 =]

祝你好运。

【讨论】:

  • js: true 仅在使用 RSpec 时有效——OP 似乎正在使用 minitest。
  • 如果我能弄清楚如何安装 phantomjs,它可以与 Minitest 一起使用吗?使用 Cloud9 IDE 有什么不同吗?
【解决方案2】:

您运行 JS 的测试通常都不是两个问题之一,然后您的测试还有两个问题可能会导致失败。

对于 JS 问题,第一个原因可能是您的一个 JS 资产中存在错误,导致它们在连接在一起时无法处理。由于您声明它在生产模式下工作(也发生连接),我们应该能够排除这种情况。第二个原因是您没有使用支持 JS 的驱动程序运行。确保您已遵循自述文件中的说明 - https://github.com/teamcapybara/capybara#using-capybara-with-minitest - 正在从 ActionDispatch::IntegrationTest 派生测试类,并且该部分的最后一部分(其中 Capybara.current_driver = Capybara.javascript_driver)在任何测试之前运行需要 JS。 (如果您希望所有测试都在 JS 支持下运行,您可以在设置 Capybara.javascript_driver 后设置 Capybara.default_driver = Capybara.javascript_driver)。如果使用 Rails https://github.com/teamcapybara/capybara#transactions-and-database-setup

这应该让你的测试使用支持 JS 的驱动程序运行——除此之外—— 第一:当您调用find(...).click 时,不能保证等待由点击引起的任何动作完成。这意味着您需要为单击触发的可见更改设置一个断言(Capybara 提供的断言之一,因为它们具有等待/重试行为),以确保它在尝试访问数据库中的元素之前已完成。
第二:由于您已经加载了@ss,因此在您重新加载对象之前,它不会反映数据库状态的变化。

这意味着您的测试将需要按照以下方式进行更改

test "attendance with click" do
  @ss = @student_3.seminar_students.find_by(:seminar => @seminar)
  assert @ss.present

  capybara_login(@teacher_1)
  click_on("desk_consult_#{@seminar.id}")
  click_on("#{new_consultancy_button_text}")
  find("##{@ss.id}").click
  assert_text("You are marked as absent") # An assertion for whatever visible change occurs due to the previous click which will delay the next statement until the app has completed processing
  assert_not @ss.reload.present # Need to reload the object to see any DB changes
  click_on("Create Desk Consultants Groups") 
end

始终需要重新加载对象是对 DB 对象进行断言通常不受欢迎的部分原因,您应该主要只是测试 UI 行为/更改(在功能测试中)

【讨论】:

  • 我认为我已经实现了您的所有建议。现在看来测试文件中的代码无法访问夹具。如果我将“调试器”放在测试文件中,User.count 返回零。 (这是因为 database_cleaner 已经“清除”了所有数据吗?)为了解决这个问题,我尝试在测试开始时创建一个新教师。不幸的是,这个新创建的老师无法登录。当“调试器”放置在我的 session_controller 中时,User.count 从灯具返回所有 124 个用户。但它不包括我在测试中创建的老师。
  • 当我在没有清洁器的情况下尝试它时,我收到此错误:ActiveRecord::StatementInvalid: SQLite3::BusyException: database is locked:
  • @JeffZivkovic 您还没有说明您使用的是什么版本的 Rails,但是如果使用
  • 太棒了!是的。 database_cleaner 策略是关键。虽然,所需的策略与您的建议相反。使我的测试绿色的唯一策略是“交易”。但这种策略似乎已经消除了在测试中创建新教师的需要。感谢您在过去几天中不断提供的帮助。祝您假期愉快!
猜你喜欢
  • 2012-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-09
  • 2019-07-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多