是否可以在不修补ActiveRecord的情况下使用Selenium/Capybara Webkit/Poltergeist?

Und*_*ion 5 selenium activerecord rspec ruby-on-rails capybara

根据Capybara 文档,有两种不同的策略来处理Selenium无法访问测试中生成的数据的问题:

  1. 猴子补丁ActiveRecord:

    class ActiveRecord :: Base @@ shared_connection = nil def self.connection @@ shared_connection || retrieve_connection end end ActiveRecord :: Base.shared_connection = ActiveRecord :: Base.connection

  2. 使用截断而不是事务

我已经设置了DatabaseCleaner由Avdi格林概述这里,虽然在看我的日志,我可以清楚地看到DatabaseCleaner使用截短,例如:

(7.4ms)TRUNCATE TABLE"画廊","照片","用户"RESTART IDENTITY CASCADE;

...当我运行我的功能时,我作为设置的一部分创建的任何模型都不可用于驱动程序.我可以看到场景中存在模型,但是如果我将它们打印到页面中,它们就不存在了.

我可以让驱动程序查看模型的唯一方法是使用上面的ActiveRecord monkey-patch,但这似乎会引发许多奇怪的次要问题 - 测试挂起等等.

为什么是它的驱动程序(硒或水豚-的Webkit)无法看到在测试中创建的模型,甚至当我使用DatabaseCleaner使用截断策略,我怎样才能得到水豚用JavaScript的司机工作?

注意:使用默认驱动程序,测试正常

我的DatabaseCleaner配置:

RSpec.configure do |config|

  # Clean DB completely
  config.before(:suite) do
    DatabaseCleaner.clean_with(:truncation)
  end

  # Set default strategy (non-js/Rack::Test)
  config.before(:each) do
    DatabaseCleaner.strategy = :transaction
  end

  # Set strategy for tests using JS (slower)
  config.before(:each, js: true) do
    DatabaseCleaner.strategy = :truncation
  end

  # Wrap DatabaseCleaner around each test (before & after)
  config.before(:each) do
    DatabaseCleaner.start
  end

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

end
Run Code Online (Sandbox Code Playgroud)

以下是我想使用JavaScript测试的功能示例:

feature "User deletes a photo" do

  before {
    as_signed_in_user
    @gallery = create(:gallery_with_photos)
  }

  scenario "successfully deletes a photo from a gallery", js: true do

    photo_title = @gallery.photos.first.title
    puts "GALLERY #{Gallery.find(1)}" # <Gallery:0x007f9b928fe8e8>
    visit gallery_path(@gallery) # JavaScript driver can't find gallery

    within '.photos-list' do
      click_link photo_title
    end
    click_link('Delete Photo')

    expect(current_path).to eq( gallery_path(@gallery) )
    expect(page).not_to have_link(photo_title)

  end

end
Run Code Online (Sandbox Code Playgroud)

使用JavaScript驱动程序时,此测试失败,并显示:

  1) User deletes a photo successfully deletes a photo from a gallery
     Failure/Error: Unable to find matching line from backtrace
     ActiveRecord::RecordNotFound:
       Couldn't find Gallery with 'id'=1
Run Code Online (Sandbox Code Playgroud)

正如Dave Schweisguth在评论中所建议的那样,我试图将其js:true移出到特征而不是场景,而不会产生任何影响.

Ben*_*enj 3

确保您使用的是最新版本的database-cleaner、capybara、selenium-webdriver。还要确保所有这些宝石都在测试组中并且是require: false

然后在您的spec_helper.rb 文件中,您可以通过在这些gem 之前要求rails 来控制加载顺序。RAILS_ENV确保和的设置正确use_transactional_fixtures

规范助手.rb

require 'rubygems'

ENV['RAILS_ENV'] ||= 'test'

# Load rails + environment
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'

# Load database cleaner
require 'database_cleaner'

# Load capybara and its dependencies
require 'capybara/rspec'
require 'capybara/rails'
require 'selenium-webdriver'

RSpec.configure do |config|
  # Do not use transactional, let database_cleaner do the work
  config.use_transactional_fixtures = false

  # Database cleaner config
  config.before(:suite) { DatabaseCleaner.clean_with :truncation }
  config.before(:each) { DatabaseCleaner.strategy = :transaction }
  config.before(:each, js: true) { DatabaseCleaner.strategy = :truncation }

  config.before(:each) { DatabaseCleaner.start }
  config.after(:each) { DatabaseCleaner.clean }
end
Run Code Online (Sandbox Code Playgroud)

功能规格

尝试使用describe ... type: :feature替代方法,然后移至js: true顶部,如下所示:

describe "User deletes a photo", type: :feature, js: :true do
  before { ... }
  scenario "successfully deletes a photo from a gallery" do
    ...
  end
end
Run Code Online (Sandbox Code Playgroud)

你的代码

puts "GALLERY #{Gallery.find(1)}"1-即使是为了快速调试也不要编写。在某些情况下,它可能会引发错误并导致混乱(即让您认为问题确实没有解决)。用这个代替puts "GALLERY #{Gallery.find(@gallery.id)}"

2-在 rspec 中使用实例变量也不是一个好的做法,所以不要这样:

before {
  as_signed_in_user
  @gallery = create(:gallery_with_photos)
}
Run Code Online (Sandbox Code Playgroud)

你应该写这个

before { as_signed_in_user }
let!(:gallery) { create(:gallery_with_photos) }
Run Code Online (Sandbox Code Playgroud)

请注意,我使用let!的是 bang,它相当于before. 因此,在规范的其余部分中,您必须替换@gallerygallery