Hermetic Testing with Rspec - Part 1
"Hermetic" testing means that the test code itself contains all of the setup information (and teardown actions) needed for the test to run. In other words, the test describes itself.
In Rails-Rspec, this means we use transactional fixtures and we don't use a truncation strategy.
In Rspec, each test is written in code with an "it" block.
What's important about transactional fixtures is that every test has its own data setup. Before each "it" block (a block of code that describes 1 test), your setup will run in a database transaction.
This makes the database behave as-if the data is 'frozen in place' without actually being committed to to the underlying database mechanism (Postgres, MySQL, etc).
The advantage to this style of testing (transactional fixtures) is that each test can rollback the transaction and reset the database to its original state, and it can do this very quickly.
The downside to this style of testing is that our hermetic tests often need a little trickery to DRY up your testing style. (Don't-Repeat Yourself). Alternatively, your Rspec tests come out with repetitive setup code.
Either way, the primary tools this tutorial will teach you are:
• Factory Bot
Rspec is the primary way that tests, called "specs," are written. Factory Bot is used to define a basic sample of data for our objects. These object will map to ActiveRecord objects.
1/ Install Rspec + Factory Bot
Add to Gemfile in a group marked :development and :test. Be sure to add it to a group for both :development and :test (do not add it to only a :test group).
then run bundle install
Run the rspec installer with
rails generate rspec:install
Now, notice that these files are created
create .rspec create spec create spec/spec_helper.rb create spec/rails_helper.rb
Now delete your
test/ folder with
rm -rf test/
(This removes the default folder for Minitest, which is the alternative to Rspec that we are not covering in this tutorial.)
Check-in this code using Git and give it a commit message of something like "installs Rspec"
2/ Meet spec_helper and rails_helper
For historical reasons, Rails-Rspec apps come with two default files: spec_helper and rails_helper.
All Rspec specs must begin with this exact line:
When you run any rspec test, it runs as-if the working directory is the
spec/ folder itself, even when you are running a spec nested several folders deep. So all Rspec specs you write, including ones nested several folders deep, must begin with this exact line:
Both files contain Rspec configuration, but rails_helper contains configuration specific to Rails. Let's take a look a the default spec/rails_helper.rb file now.
First take note this is where RAILS_ENV is set to test. The ||= Ruby operator is called null coalescence and it means that if the RAILS_ENV is not set in the environment (
ENV global variable), then set it here.
Then we explicitly load any settings specific to the test environment itself. (These are found in config/environment/test.rb)
Pay attention to what this comment says: Rspec looks for any file inside of the the
spec/ directory that ends with
_spec.rb. Those files will automatically be seen as spec files, but other files will not. If you can't figure out why your spec isn't running, make sure the file is named correctly.
Take a look for the top of the line that begins
RSpec.configure do |config|
A few lines down, you should see
config.use_transactional_fixtures = true
Here is the important line that defines our use of transactional fixtures, as discussed in the introduction to this lesson. If you set this to false, you will switch Rspec into truncation strategy.
Towards the bottom of the
RSpec.configure do |config| you will see another important config:
infer_spec_type_from_file_location! setting. When enabled (which is just done by calling it with the bang method like you see here), specs will have added behaviors depending on what folder they are located in.
Those are the most important parts of the rails_helper configuration, and in this tutorial, I will go over the default Rspec configuration only. Once you've finished the tutorial, feel free to explore the various settings.
Now that we have a Rspec installed, it is time to write your first spec. Exciting no?