如何使用工厂创建要用 Rspec 和 Capybara 进行测试的测试数据

How to use factories to create test data to be tested with Rspec and Capybara

我正在尝试使用 rspec/capybara 测试我的分页功能。我使用 FactoryBot 创建了文章,但遇到了两个问题。如果我创建数据:

  1. before 块中,数据保存到数据库中,不会在套件运行后擦除。
  2. 在场景块中并使用save_and_open_page查看数据是否显示在屏幕上,它没有显示。所以,我认为数据没有足够的时间保存。

宝石文件:

source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '3.0.3'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
gem 'rails', '~> 6.1.4', '>= 6.1.4.4'

gem 'react-rails'

# Use postgresql as the database for Active Record
gem 'pg', '~> 1.1'
# Use Puma as the app server
gem 'puma', '~> 5.0'
# Use SCSS for stylesheets
gem 'sass-rails', '>= 6'
# Transpile app-like JavaScript. Read more: https://github.com/rails/webpacker
gem 'webpacker', '~> 5.0'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.7'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use Active Model has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use Active Storage variant
# gem 'image_processing', '~> 1.2'

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.4.4', require: false

gem "aws-sdk-s3", require: false

group :development, :test do
  gem 'rspec-rails', '~> 5.0.0'
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

  gem 'factory_bot_rails'

  gem 'lorem_ipsum_amet'

  gem 'dotenv-rails'
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 4.1.0'
  # Display performance information such as SQL time and flame graphs for each request in your browser.
  # Can be configured to work on production as well see: https://github.com/MiniProfiler/rack-mini-profiler/blob/master/README.md
  gem 'rack-mini-profiler', '~> 2.0'
  gem 'listen', '~> 3.3'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
end

group :test do
  gem 'simplecov', require: false
  gem 'codecov', require: false
  gem 'capybara'
  gem 'webdrivers', '~> 5.0'
  gem 'launchy', '~> 2.5'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

这是工厂:

FactoryBot.define do
  factory :article do
    sequence(:title) {|i| "Article #{i}"}
    body {"This is the test body of the article."}
  end
end

这是我的测试套件。我只展示了一个例子,因为其余的概念是相同的:

RSpec.feature "Paginations", type: :feature do

  before(:all) do
    ActionController::Base.allow_forgery_protection = true

    # FactoryBot.create_list(:article, 100)
  end

  before(:each) do
    visit articles_path
  end

  after(:all) do
    ActionController::Base.allow_forgery_protection = false
  end

  scenario "user visits articles home page to see only 10 articles", js: true do
    FactoryBot.create_list(:article, 10)

    save_and_open_page

    expect(page).to have_css "div.item-container-sizing.item-container-padding.flex-row-space-between", count: 10
  end
end

这里的主要问题是 out-of-order 执行。您在创建测试所需的对象之前访问页面,因此对象在呈现的页面上不可见(呈现页面时它们不存在)。对于大多数测试,您不希望在 before 块中调用 visit ,除非您有一系列测试都需要相同的测试数据并访问相同的页面。在这种情况下,只需将 visit 移动到场景中即可。此外,不要 over-specify 您要查找的元素的选择器,因为这会使您的测试变得脆弱。您没有显示 html 的样子,但假设此页面仅显示一个文章列表,那么只检查您的 类 中的一篇可能就足够了,或者将您的期望范围限定在一个页面区域,然后使用更通用的 CSS 选择器

scenario "user visits articles home page to see only 10 articles", js: true do
    FactoryBot.create_list(:article, 10)
    visit articles_path

    # save_and_open_page

    expect(page).to have_css "div.item-container-sizing.item-container-padding.flex-row-space-between", count: 10
  end