I get the feeling a lot of RSpec users don’t know about the advantages of Rails 5.1 changes as part of the introduction of system tests. RSpec has had feature tests for a long time? What’s the big deal?
For context, RSpec has supported high level testing through feature tests for many years. Like Cucumber, feature tests are designed to exercise application functionality through the user interface. There are many merits to feature tests as a way to document core business logic and catch regressions. There are drawbacks as well, including the fact that they can be very expensive, i.e., slow, to maintain and execute. I'm going to ignore this for now.
I'll also altogether ignore interesting alternatives for UI and fullstack testing, like cypress.io. This post is aimed at folks working on Rails apps that have accumulated month or years worth of RSpec feature tests.
For a long time, Rails has resisted first class support for this kind of testing, so much of RSpec's integration with Rails is bolted on. It has mostly worked well, though there have been some gotchas which I'll get to.
Last year, that all changed when Rails released Rails 5.1 with some key changes to support the introduction of system tests. On the surface, Rails system tests have pretty much the same usage and goals as RSpec feature tests, including integration with Capybara, the Ruby interface to interacting with numerous webdrivers like headless Chrome, Gecko for Firefox, PhantomJS, etc. So basically everything we've had in RSpec for ages. RSpec developers collectively yawned.
The real win with Rails 5.1 is what's happening under the surface. The Rails team made key changes to internals, stuff RSpec alone couldn’t provide.
Why transactional tests are better
Not to mention, having the Rails server run in a separate process makes it a lot harder to debug. If you like using a debugger like pry in your application code, good luck making it work with traditional RSpec acceptance tests.
The result: faster rollback, no multiprocess confusion, no need to manage the database with DatabaseCleaner, debugging the server in process is possible, etc. A better solution all around.
To my RSpec friends: upgrade to Rails 5.1, drop the DatabaseCleaner gem, and set
config.use_transactional_fixtures = true in the RSpec configuration. It should also be relatively straightforward to adopt system tests from existing feature tests, but either strategy will work with those changes. You’ll still need to fix those flaky scenarios yourself though.
This post has been edited to reflect Thomas Walpole's corrections in the comments.