As part of a red-green-refactor cycle, I appreciate a smooth, fast feedback loop. The slower the loop; the more my attention gets to another shiny object and my concentration gets broken. This tutorial aims to help you achieve a smooth red-green-refactor loop.
By the end you should be able to:
- Setup testing frameworks:
- RSpec, Shoulda-Matchers, Database Cleaner, Capybara, Factory_girl_rails, Faker
- Write a Model test
- Improve TDD Feedback loop using Guard and Spring
- Setup Notifications
Setup App
Setup Testing Frameworks
Update the Gemfile Include the following gems in your Gemfile:
group :development, :test doendgroup :test doend
Run bundle install
Note: If you have any problems installing gems, primarily NokoGiri, run the following commands:
Setup RSpec
rails generate rspec:install
The install will generate a spec directory and some skeleton files, including a .rspec file, which will be used later.
Shoulda-Matchers
Shoulda-Matchers provide one line matchers for RSpec. We need to configure shoulda-matchers to work with RSpec by modifying the spec/rails_helper.rb file to include the following code snippet:
Setup Database Cleaner
To setup database_cleaner, make the following modifications to spec/rails_helper.rb. Once complete, database_cleaner will clean the database between each unit test and each test suite.
Make a new directory called support inside of your spec directory:
Inside the new support directory, create a new file called database_cleaner.rb and paste in the following:
Allow Rails to run this support file in it's setup. In rails_helper.rb, un-comment the following line:
Setup Capybara
Since we've already got the Capybara gem installed, just add the following line to the top of spec_helper.rb file:
Setup Faker and Factory Girl
Faker gem generates random data for testing. We will use this with factory_girl_rails in making a factory. To integrate FactoryGirl with RSpec, add the following line in rails_helper.rb within the RSpec.configure block:
Create a factory
Create a directory named factories in your spec folder. In the factories directory, create a file named after your model. Ex. ideas.rb
This factory allows you to generate fake data based on data generated by Faker to be used by FactoryGirl in running our tests.
Let's write a test!
Now that we have our testing frameworks in place, let's write our first Model spec!
Create a file in your model/spec folder for your model:
Let's run the test from the terminal:
This test will fail because we don't have an idea model. Let's create it!
This will want to overwrite the idea_spec.rb file and the spec/factories/ideas.rb file. Don't allow it, just enter 'n' for both. Then run:
Once the database has been migrated, lets run our test again.
Green!
That feedback was good but it was a bit slow. Let's speed it up and gain more convenient feedback.
Improve TDD Feedback loop
Add the the following gems to your Gemfile:
group :development doend
Guard Setup
Guard is a neat gem that works with RSpec that watches your file system for changes and runs your test suite automatically. We need to initialize it, then we can run it
Spring Setup
Spring is new to Rails 5. This will setup our configuration once and then run tests repeatedly without having all the extra configuration overhead between each run. If you change rails configuration, you will need to restart the Spring.
For just one single test, this shaved a solid 5 seconds off of each test run!
Now, let's notify Guard to use Spring when running specs. In the Guardfile, modify the following line from:
to:
Then run guard:
There should be a line in the output that says "Running via Spring preloader in process..." From your idea_spec.rb file, trigger a save. You'll see in the terminal that it will automatically run the tests and not have to preload rails.
Ah, much faster feedback but keeping the terminal window open is kind of a drag. Let's fix that!
Notifications
Let's provide notification pop ups whenever tests are run. This will allow us to keep the terminal window in the background and not have to even look at it unless we have test failures! Keeping our focus in the code requires less context switching and it's easy to setup!
I'm going to assume that you have a Mac and have brew installed. Install terminal-notifier
Then, in your Gemfile, add the following gem:
The last step is integrate terminal_notifier with guard. In your Guardfile, add the following line at the end of the file:
Restart Guard if you had it running. After Guard runs your tests, you should receive a notification in the upper right hand corner saying all your tests passed!
Congrats! This TDD flow has helped me stay focus on the problem at hand and not worry about constantly checking the terminal, waiting for tests to run.