Capybara/RSpec系统测试中数据库数据不显示的问题解决
Rails Capybara/RSpec系统测试:测试数据未在页面显示的问题
我在运行Rails项目的Capybara/RSpec系统测试时,遇到创建的测试数据库数据无法在页面显示的问题。以下是我的spec/system/group_index_spec.rb测试文件:
require_relative '../rails_helper' RSpec.describe 'Group Index', type: :system do let(:user) { User.create(name: 'First User', email: 'test@user.com', password: 'password') } before do # driven_by(:rack_test) puts 'Creating test data...' 5.times do |i| group = Group.create(name: "Group #{i}", author: user) group.icon.attach(io: File.open(Rails.root.join('spec', 'models', 'files', 'test.jpg')), filename: 'test.jpg', content_type: 'image/jpeg') 5.times do |j| Entity.create(name: "Entity #{j}", amount: 100, author: user) end end Group.all.each do |group| group.entities << Entity.all.sample(rand(1..3)) end Entity.all.each do |entity| entity.groups << Group.all.sample(rand(1..3)) end puts 'Logging in...' visit new_user_session_path fill_in 'user_email', with: 'test@user.com' fill_in 'user_password', with: 'password' click_button 'Log in' end it 'displays all groups', js: true do visit groups_path expect(page).to have_content('Group 0') expect(page).to have_content('Group 1') expect(page).to have_content('Group 2') expect(page).to have_content('Group 3') expect(page).to have_content('Group 4') end end
运行测试后出现如下错误:
Creating test data... Logging in... F Failures: 1) Group Index displays all groups Failure/Error: expect(page).to have_content('Group 0') expected to find text "Group 0" in "CATEGORIES\nNew" [Screenshot Image]: /home/shasherazi/programming/microverse/budget-app/tmp/capybara/failures_r_spec_example_groups_g roup_index_displays_all_groups_713.png # ./spec/system/group_index_spec.rb:36:in `block (2 levels) in <top (required)>' Finished in 8.22 seconds (files took 1.64 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/system/group_index_spec.rb:34 # Group Index displays all groups
以下是我参考网上建议修改后的rails_helper.rb文件:
# This file is copied to spec/ when you run 'rails generate rspec:install' require 'spec_helper' ENV['RAILS_ENV'] ||= 'test' require_relative '../config/environment' # Prevent database truncation if the environment is production abort('The Rails environment is running in production mode!') if Rails.env.production? require 'rspec/rails' require 'capybara/rspec' require 'database_cleaner' # Add additional requires below this line. Rails is not loaded until this point! # Requires supporting ruby files with custom matchers and macros, etc, in # spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are # run as spec files by default. This means that files in spec/support that end # in _spec.rb will both be required and run as specs, causing the specs to be # run twice. It is recommended that you do not name files matching this glob to # end with _spec.rb. You can configure this pattern with the --pattern # option on the command line or in ~/.rspec, .rspec or `.rspec-local`. # # The following line is provided for convenience purposes. It has the downside # of increasing the boot-up time by auto-requiring all files in the support # directory. Alternatively, in the individual `*_spec.rb` files, manually # require only the support files necessary. # # Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f } # Checks for pending migrations and applies them before tests are run. # If you are not using ActiveRecord, you can remove these lines. begin ActiveRecord::Migration.maintain_test_schema! rescue ActiveRecord::PendingMigrationError => e abort e.to_s.strip end RSpec.configure do |config| # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures config.fixture_path = "#{Rails.root}/spec/fixtures" # If you're not using ActiveRecord, or you'd prefer not to run each of your # examples within a transaction, remove the following line or assign false # instead of true. config.use_transactional_fixtures = false config.before(:suite) do DatabaseCleaner.strategy = :truncation DatabaseCleaner.clean_with(:truncation) end config.before(:each) do DatabaseCleaner.start end config.after(:each) do DatabaseCleaner.clean end # You can uncomment this line to turn off ActiveRecord support entirely. # config.use_active_record = false # RSpec Rails can automatically mix in different behaviours to your tests # based on their file location, for example enabling you to call `get` and # `post` in specs under `spec/controllers`. # # You can disable this behaviour by removing the line below, and instead # explicitly tag your specs with their type, e.g.: # # RSpec.describe UsersController, type: :controller do # # ... # end # # The different available types are documented in the features, such as in # https://rspec.info/features/6-0/rspec-rails config.infer_spec_type_from_file_location! # Filter lines from Rails gems in backtraces. config.filter_rails_from_backtrace! # arbitrary gems may also be filtered via: # config.filter_gems_from_backtrace("gem name") Capybara.run_server = true Capybara.server_port = 7000 Capybara.app_host = "http://localhost:#{Capybara.server_port}" end
开发环境中用faker以类似方式生成示例数据一切正常,但测试环境始终无法显示数据,折腾了一整天没找到解决方案,希望能得到帮助。
解决方案
问题根源是:创建模型实例并添加附件(如group.icon.attach)后,需要手动调用.save方法才能将变更持久化到数据库。以下是修正后的测试文件:
require_relative '../rails_helper' RSpec.describe 'Groups', type: :system do let(:user) { User.create(name: 'First User', email: 'test@user.com', password: 'password') } before do # 注释下面一行可在浏览器中运行测试 driven_by(:rack_test) puts "\nCreating test data..." 5.times do |i| group = Group.create(name: "Group #{i}", author: user) group.icon.attach(io: File.open(Rails.root.join('spec', 'models', 'files', 'test.jpg')), filename: 'test.jpg', content_type: 'image/jpeg') group.save 5.times do |j| entity = Entity.create(name: "Entity #{j}", amount: 100, author: user) entity.save end end Group.all.each do |group| group.entities << Entity.all.sample(rand(1..3)) end Entity.all.each do |entity| entity.groups << Group.all.sample(rand(1..3)) end puts 'Logging in...' visit new_user_session_path fill_in 'user_email', with: 'test@user.com' fill_in 'user_password', with: 'password' click_button 'Log in' end after(:all) do puts "\nCleaning up..." Group.destroy_all Entity.destroy_all User.destroy_all end it 'displays all groups, their names, and icons', js: true do visit groups_path user.groups.each do |group| expect(page).to have_content(group.name) expect(page).to have_css("img[src*='#{group.icon.blob.filename}']") end end end
内容的提问来源于stack exchange,提问作者shasherazi
相关产品推荐
相关产品推荐

