How to set up test_helper.rb when using Minitest, Capybara, Factorybot, and Database Cleaner

1.7k Views Asked by At

I've seen a lot of examples of how to set up Capybara, Database Cleaner, and Factorybot with Rspec, but none with the Minitest setup that comes out of the box with Rails.

I'm struggling with Capybara::ElementNotFound errors when I run my test suite as a whole, but all of the tests that fail pass when run in isolation.

So, this leads me to believe that I need to use database_cleaner, but I can't figure out a setup that gets the test suite passing. What should my test_helper.rb look like if I'd like to use Minitest, Capybara, Factorybot, and Database Cleaner?

Here's my current test_helper.rb:

ENV['RAILS_ENV'] ||= 'test'
Minitest::Reporters.use!
require File.expand_path('../../config/environment', __FILE__)
require 'rails/test_help'
require 'minitest/reporters'
require 'capybara/rails'
require 'capybara/minitest'
require 'database_cleaner'

DatabaseCleaner.strategy = :truncation

class ActiveSupport::TestCase
  include FactoryBot::Syntax::Methods
end

class ActionDispatch::IntegrationTest
  include Capybara::DSL
  include Capybara::Minitest::Assertions # Make `assert_*` methods behave like Minitest assertions

  Capybara.server = :puma
  Capybara.server_port = 3001
  Capybara.app_host = 'http://localhost:3001'

  Capybara.register_driver :selenium do |app|
    Capybara::Selenium::Driver.new(app, browser: :chrome)
  end

  Capybara.javascript_driver = :chrome

  Capybara.configure do |config|
    config.default_max_wait_time = 10 # seconds
    config.default_driver        = :selenium
  end

  def teardown
    Capybara.reset_sessions!
    Capybara.use_default_driver
    DatabaseCleaner.clean
  end
end

Gemfile:

group :test do
  gem 'capybara'
  gem 'webdrivers'
  gem 'capybara-selenium'
  gem 'capybara-email'
  gem 'faker'
  gem 'database_cleaner'
  gem 'rails-controller-testing'
  gem 'minitest'
  gem 'minitest-reporters'
  gem 'guard'
  gem 'guard-minitest'
end

The I call DatabaseCleaner.start in the setup for any test using Factorybot like this:

require 'test_helper'

class AccountTenancyTest < ActionDispatch::IntegrationTest
  setup do
    DatabaseCleaner.start
    @acme_widgets_owner         = create(:acme_widgets_owner)
    @generic_gadgets_owner      = create(:generic_gadgets_owner)
  end

  test "Account owners can't access someone else's account" do
    # test goes here
  end
end

What am I doing wrong with this setup that is causing the Capybara::ElementNotFound: errors when I run rails test if the tests are passing in isolation?

1

There are 1 best solutions below

1
Thomas Walpole On

Since you're running Rails >= 5.1 you don't need DatabaseCleaner (Rails 5.1+ shares the DB connection between the app and the tests and uses transactions to isolate each test from others). Remove all references to database cleaner. Then change your integration tests to System Tests which is what you should be writing for Capybara tests in Rails 5.1+. That will then automatically set up all the before and teardown blocks necessary for basic Capybara tests.

I'm guessing your email tests are failing because the url being put in the emails isn't including the port number the test is being run on. Switching to system tests may fix that, if not you can specify Capybara.always_include_port = true to ensure the port gets added into the URL from the email.