数据库数据在Capyara/RSpec系统测试中未显示

huangapple go评论67阅读模式
英文:

Database data not appearing in Capyara/RSpec system tests

问题

这是您的spec/system/group_index_spec.rb文件,其中包含一些Ruby代码和测试。以下是其中的一部分内容:

RSpec.describe 'Group Index', type: :system do
  let(:user) { User.create(name: 'First User', email: 'test@user.com', password: 'password') }
  # ...(省略部分代码)...

  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

请注意,这是测试文件的一部分,用于测试网页应用程序中的组列表页面。如果您需要关于代码的其他翻译,请提供更多详细信息。

英文:

This is my spec/system/group_index_spec.rb file.

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

When I run this test, I get this error message.

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

Here is a short video showing the process.

Here is my rails_helper.rb file that I modified taking advice from the internet.

# 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

Everything works fine in my dev environment where I am using faker to create sample data in a similar way. I have spent almost all day today finding the solution to this problem but couldn't. I'll be very grateful to you if you help.

Solution

I needed to call .save manually to actually save the data. Here is the corrected test file.

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
    # comment the line below to run tests in browser
    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

答案1

得分: 1

你在这里非常关注数据库方面的事情,但这似乎不是你的问题。

我认为在你的测试中,在你的期望之前应该执行pp Group.all,只是为了确认(对自己来说)这不是一个数据库问题。

你收到的错误消息似乎表明你实际上在分类索引页面(或者出于某种原因,组索引页面正在使用分类索引视图):

预期在"CATEGORIES\nNew"中找到文本"Group 0"

可能保存在/home/shasherazi/programming/microverse/budget-app/tmp/capybara/failures_r_spec_example_groups_group_index_displays_all_groups_713.png的截图可以帮助你确认这一点,然后你可以开始排除故障。

英文:

You have so much focus here on the DB side of things, but that doesn't seem to be your issue.

I think you should pp Group.all in your test before your expectation, just to confirm (for yourself) that this is not a DB issue.

The error message you're getting seems to suggest that you're actually on the categories index page (or the groups index page is using the categories index view for some reason):

> expected to find text "Group 0" in "CATEGORIES\nNew"

Probably the screenshot being saved in /home/shasherazi/programming/microverse/budget-app/tmp/capybara/failures_r_spec_example_groups_g
roup_index_displays_all_groups_713.png
can help you confirm this and you can begin troubleshooting.

答案2

得分: 0

这里的问题很可能是您的用户实际上没有登录。这是因为操作是异步进行的,您没有等待登录成功。您的测试实际上是在运行以下代码:

    ...
visit new_user_session_path
fill_in 'user_email', with: 'test@user.com'
fill_in 'user_password', with: 'password'
click_button 'Log in'
visit groups_path
expect(page).to have_content('Group 0')
...

这将导致visit groups_path取消了click_button调用触发的任何请求,并以未经身份验证的用户身份访问组页面。您可以尝试在click_button之后添加sleep 5来查看是否可以解决问题。如果可以的话,您应该用实际查找页面变化的方式来替换sleep,大致如下:

    fill_in 'user_password', with: 'password'
click_button 'Log in'
expect(page).to have_content('Logged In')
英文:

The issue here is likely that your user isn't actually logged in. This is because actions happen asynchronously and you're not doing anything to wait for the login to succeed. Your test is effectively running

    ...
visit new_user_session_path
fill_in 'user_email', with: 'test@user.com'
fill_in 'user_password', with: 'password'
click_button 'Log in'
visit groups_path
expect(page).to have_content('Group 0')
...

Which will cause the visit groups_path to cancel any request triggered by the click_button call, and visit the groups page as an unauthenticated user. You can test that by just adding a sleep 5 after the click_button to see if it fixes your issue. If it does you'll want to replace the sleep with something that actually looks for a change in the page that indicates the login has completed, along the lines of

    fill_in 'user_password', with: 'password'
click_button 'Log in'
expect(page).to have_content('Logged In')

huangapple
  • 本文由 发表于 2023年7月6日 21:45:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76629527.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定