【问题标题】:RSpec/Capybara does not commit to DB within testRSpec/Capybara 在测试中不提交数据库
【发布时间】:2017-02-10 01:12:11
【问题描述】:

自从将我们的测试套件从 Minitest 迁移到 RSpec 后,我感到非常绝望。到目前为止,所有控制器和模型测试都运行良好,但是由于尝试移植(以前通过/工作)功能测试,如下所示,我遇到了麻烦......

feature 'Create place' do
  scenario 'create valid place as user' do
    login_as_user
    visit '/places/new'
    fill_in_valid_place_information
    click_button('Create Place')
    visit '/places'
    expect(page).to have_content('Any place', count: 1)
  end

  ...

  def fill_in_valid_place_information
      fill_in('place_name', with: 'Any place')
      fill_in('place_street', with: 'Magdalenenstr.')
      fill_in('place_house_number', with: '19')
      fill_in('place_postal_code', with: '10963')
      fill_in('place_city', with: 'Berlin')
      fill_in('place_email', with: 'schnipp@schnapp.com')
      fill_in('place_homepage', with: 'http://schnapp.com')
      fill_in('place_phone', with: '03081763253')
  end
end

不幸的是,这不会导致导致测试失败的数据库提交。如果我 pry 进入测试并手动创建请求的位置,它不会失败。我尝试了不同的方法来触发按钮,但到目前为止没有任何效果。

这就是我的rails_helper.rb 的样子:

ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
abort("The Rails environment is running in production mode!") if Rails.env.production?
require 'spec_helper'
require 'rspec/rails'
require 'capybara/rspec'
require 'capybara/rails'
require 'capybara/poltergeist'
require 'pry'

def validate_captcha
  fill_in 'captcha', with: SimpleCaptcha::SimpleCaptchaData.first.value
end

def login_as_user
  user = create :user, email: 'user@example.com'
  visit 'login/'
  fill_in 'sessions_email', with: 'user@example.com'
  fill_in 'sessions_password', with: 'secret'
  click_on 'Login'
end

Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }

ActiveRecord::Migration.maintain_test_schema!

Capybara.register_driver :poltergeist do |app|
    Capybara::Poltergeist::Driver.new(app, phantomjs_options: ['--ignore-ssl-errors=true'])
end

Capybara.javascript_driver = :poltergeist

RSpec.configure do |config|
  config.use_transactional_fixtures = false

  config.before(:suite) do
    DatabaseCleaner.clean
  end

  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  config.before(:each, no_transaction: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  config.before(:each) do
    DatabaseCleaner.start
  end

  config.after(:each) do
    DatabaseCleaner.clean
  end

  config.include Capybara::DSL
  config.include Rails.application.routes.url_helpers
  config.fixture_path = "#{::Rails.root}/spec/fixtures"
  config.infer_spec_type_from_file_location!
  config.filter_rails_from_backtrace!
end

有人知道可能的原因吗?宝石版本:

  • 水豚2.12.0
  • rspec 3.5.0
  • 导轨 4.2.7.1

最好的,谢谢, 安迪

--- 更新

我添加了fill_in_valid_place_information方法

无论是否启用 Capybara JS 驱动程序,这都是测试失败的原因(在此测试的情况下应该无关紧要,因为该功能不使用任何 JS)。不幸的是,它没有给出任何真正的提示......

1) Create place create valid place as user
     Failure/Error: expect(page).to have_content('Any place', count: 1)

       expected to find text "Any place" 1 time but found 0 times in "KIEZ KARTE Find places Here comes a list of all POIs currently available in our database. If you are looking for a specific location please enter parts of its descriptive features into the 'Search' field. Search: Name Postal code Categories No data available in table"

       Timeout reached while running a *waiting* Capybara finder...perhaps you wanted to return immediately? Use a non-waiting Capybara finder. More info: http://blog.codeship.com/faster-rails-tests?utm_source=gem_exception

--- 更新 2

我发现了与水豚无关的问题。实际上,我忘记为我们正在调用的 API 传输存根响应。感谢大家参与我的奋斗!

【问题讨论】:

  • 可以发一下fill_in_valid_place_information方法吗?
  • 嘿,谢谢。我更新了答案以包含方法和失败消息(没有太大帮助)

标签: ruby-on-rails rspec capybara


【解决方案1】:

您的测试中有许多潜在问题可能导致您看到的情况,如果您包含测试产生的实际错误消息,将来会更容易缩小范围。

  1. 您的场景/功能未使用 :js 元数据标记以使用 Capybara 驱动程序激活。您可能在某处指定了 Capybara.default_driver,但如果是这样,那么您的 DatabaseCleaner 配置是错误的

  2. 使用 https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example 中推荐的 DatabaseCleaner 配置。如果您已指定Capybara.default_driver(如 #1 中所述)以及 :js/:driver 元数据使用模式,则驱动程序名称检测将起作用。此外,append_after/after 差异对于减少测试片状现象很重要

  3. 您的login_as_user 方法需要在返回之前验证登录是否完成。这是因为click_on 'Login' 可以异步触发并在登录实际发生之前返回。这会导致您在中止登录后立即调用visit,阻止发送会话cookie,并在您希望用户登录时以未登录用户结束。要解决此问题,您需要类似

    def login_as_user
      ...
      click_on 'Login'
      expect(page).to have_text('You are now logged in!') #whatever message is shown on successful login, or use have_css with some element on the page that only exists when a user is logged in (user menu, etc)
    end
    

    click_button('Create Place')visit '/places'之间存在同样的问题,访问可以有效取消按钮点击的效果

【讨论】:

  • 嗨,Thomas,感谢您的全面回答。 1. 测试的特性不包含任何JS。无论如何,即使使用 :js 标签也会失败。 2. 我做到了,没有任何改变。 3. 登录完成,我验证了。即使没有登录,软件的逻辑也允许提交,所以这不是问题。另外:测试工作 - “概念上” - 在 Minitest -.-
  • @A.Neumann 您的代码是否依赖于after_commit 回调?
  • 确实如此,我有两个after_create 回调
  • @A.Neumann 另外,您能否在测试日志中显示您的创建操作和相关输出。注意 - 如果使用 JS 驱动程序,click_button('Create Place')visit '/places' 之间的问题与登录相同 - 访问可以有效地取消创建。如果您在 click_button('Create Place') 之后输出 page.html,它会显示任何错误吗?
  • @A.Neumann after_createafter_commit 不同 - after_create 应该没问题,但在事务模式下不会调用 after_commit
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-25
  • 2012-04-12
  • 1970-01-01
  • 2015-04-07
  • 1970-01-01
相关资源
最近更新 更多