Rails - Minitest + Capybara + Selenium - 测试破坏动作

Rails - Minitest + Capybara + Selenium - Test destroy action

我是 Minitest/Capybara/Selenium 的新手。但我想测试我的 destroy Controller 动作。我尝试了以下但失败了

test "destroy" do
  companies_count = Company.count
  visit company_path(@company)
  click_on "Delete"
  page.driver.browser.switch_to.alert.accept
  assert_equal (companies_count - 1), Company.count
end

输出:

    test_destroy                                                    FAIL (2.17s)
    Expected: 6
      Actual: 7

这个方法也试过了

test "destroy" do
    assert_difference('Company.count', -1) do
      delete company_url(@company)
    end
end

输出:

Minitest::UnexpectedError:         NoMethodError: undefined method `delete' for #<CompaniesControllerTest:0x000056171e550038>

有人可以帮我测试我的销毁动作吗?

这很可能会发生,因为您在测试中直接执行的操作发生在事务中,而您的 Web 驱动程序正在触发发生在另一个事务上的操作。你可以在这里阅读更多关于它是如何发生的:https://edgeguides.rubyonrails.org/testing.html#testing-parallel-transactions

这是一个类似的问题:Rails integration test with selenium as webdriver - can't sign_in

正如 Rails 指南和类似问题中所述,您可能必须使用 http://rubygems.org/gems/database_cleaner

这样的解决方案

如果您不想这样做,您还有另一个选择是通过网络驱动程序验证您的操作是否成功,例如断言 table 中有 6 行你列出所有公司。

假设您使用的是 Rails (5.2/6) 的现代版本和标准系统测试配置(不是 运行 线程中的并行测试)那么 Gregório 的回答中的问题Kusowski 无关紧要,因为数据库连接在您的测试和应用程序之间共享,从而防止了测试无法看到您的应用程序更改的问题。

还假设您在这些系统测试中使用 Selenium,您要处理的主要问题是浏览器中的操作与您的测试异步发生,所以仅仅因为您已告诉您的测试接受对话框returns 框并不意味着删除公司的操作已完成。验证方法是在检查 count 中的变化之前先睡一会儿。虽然这会起作用,但它不是一个好的最终解决方案,因为它最终会浪费时间。相反,您应该在验证新计数

之前检查指示操作已完成的视觉变化
test "destroy" do
  companies_count = Company.count
  visit company_path(@company)
  accept_confirm do      
    click_on "Delete"
  end

  assert_text "Company Deleted!" # Check for whatever text is shown to indicate the action has successfully completed

  assert_equal (companies_count - 1), Company.count
end

之所以可行,是因为 Capybara 提供的断言具有 waiting/retrying 行为,允许应用程序在特定时间内赶上测试的预期。

注意:我已将 page.driver... 替换为 Capybaras 系统模式的正确用法 API - 如果您使用的是 page.driver...,这通常表示您做错了.