I write tests using Minitest and routinely reference EvilMartians System of a Test blog post for best practices for system tests. In this blog post, they also have an opinionated way of setting up System Tests.
EvilSystems offers 3 distinct advantages over the setup provided by
EvilMartians System of a Test:
1.) The blog post was built with RSpec in mind, but we use Minitest here!
2.) Constantly copying 5 files over into every new Rails app is annoying. Lets make that easier!
3.) File changes can end up out of sync, a gem makes sure updates can be pushed to all users.
EvilSystems is a quick, easy, reusable way to apply the SoaT concepts and settings
to projects for system tests using Minitest.
Full API documentation can be found here:
# Gemfile group :test do gem 'evil_system_tests', '~> 0.0.3' end
Make sure the following 3 gems are in your
Gemfile as well:
# Gemfile gem 'capybara' gem 'selenium-webdriver' # Still required when using Cuprite as of Rails 6.1 gem 'cuprite' # Optional
And then execute:
test/application_system_test_case.rb in your Rails app.
Setup your file like so:
# test/application_system_test_case.rb require 'test_helper' # 'capybara' and 'capybara/cuprite' need to be defined for EvilSystems to work properly. require 'capybara' require 'capybara/cuprite' require 'evil_systems' EvilSystems.initial_setup class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by :cuprite include EvilSystems::Helpers end
Maybe in the future?
EvilSystems.initial_setup takes two keyword arguments,
Both arguments have to do with precompiling assets.
:silent by default is set to
true and will only tell you when assets
are compiling, and how long the compilation took.
:task defaults to
assets:precompile, System of a test uses
EvilSystems.initial_setup(task: "webpacker:compile", silent: false)
- Automatically registers a
- Automatically sets
app_host will first use
ENV["APP_HOST"] then falls back to the systems
hostname if the
APP_HOST ENV var is not defined.
If neither are defined, it will then default to
Capybara.server_host = "0.0.0.0"Make server listening on all hosts
Capybara.default_max_wait_time = 2Dont spend forever waiting for matchers
Capybara.default_normalize_ws = truenormalizes whitespace in
has_text?and similar matchers.
- Sets the
ENV["CAPYBARA_ARTIFACTS"]and falls back to
- Sets a
REMOTE_CHROMEinstance if a
- Prepends a
last_used_sessionattribute accessor to Capybara.
ActionView::RecordIdentifier if Rails is
# The full path to be prepended to a screen shot absolute_image_path # The relative path to be prepended to a screenshot message to make it clickable image_path # Make failure screenshots compatible with multi-session setup take_screenshot # Prepends a '#' to the +dom_id+ method provided by Rails dom_id(*args)
# Small wrapper around Capybara.using_session thats easy to call from an instance within_session(name_or_session, &block) # Remove all cookie banners mark_all_banners_as_read!
# pauses the page pause # Opens a Pry or IRB repl. Will use Pry if Pry is defined, fallsback # to debugging with IRB debug
ENV variables used by this gem.
ENV["APP_HOST"] # used for Capybara.app_host ENV["CAPYBARA_ARTIFACTS"] # used for Capybara.save_path ENV["CHROME_URL"] # used for setting a remote chrome instance for Cuprite
I don't want to use Cuprite.
Thats fine! I totally get it. Selenium is battle tested. Simply remove
require "capybara/cuprite" line and
EvilSystems will detect that
Cuprite is not defined and not setup a driver for you and not include
Omissions and differences
webpacker:compilebefore systems tests (configurable)
Does not set the
Rails.application.default_url_options[:host]due to parallelization issues found while testing the dummy app.
The gem is available as open source under the terms of the MIT License.