When I started the application I was very new to both Ruby and Rails. The tests I wrote were OK. They worked, they tested the code, but they weren’t very good. All of the tests ended up being request specs using RSpec and Capybara. They were very slow; fifty tests ran at around 200 seconds. In the last few months I have learned a lot about Rails. The application itself has been updated incrementally to reflect what I have learned, but the tests were neglected. It was time for a change.
My development setup was just as cumbersome as the tests. I used Guard and Spork to run the appropriate tests automatically after a file was saved. This was nice for a while, but eventually it became annoying to have thirty seconds of tests running each time I updated some comments or reformatted some ugly code. If I wanted to run some tests again, but didn’t change a file associated with those tests I would have to open the file containing the specs and save it to trigger Guard. With the way I had Guard and Spork configured I couldn’t run the tests outside of that environment (with the rspec command). I had no way of opting out of the automatic testing under that system. Like the tests, the system worked but it was far from ideal.
Since all of the tests were request specs they weren’t easy to maintain. I had separate files for different units of code, but they were not well isolated. The request specs tested the code by simulating a user interacting with the application. This did ensure that the features being tested worked, but the code wasn’t explicitly tested. Finding bugs using this style of testing was difficult. I would know where the bug was in general, but they were only vague clues pointing to the root of the problem. If the code was being tested without trying to act like a user it would have been much easier to find and repair problems.
Here’s What I Did
I deleted everything in the spec folder but factories.rb (for FactoryGirl) and regenerated spec_helper.rb by running
rails g rspec:install. This completely removed the old tests letting me start from scratch, this time using plain old RSpec. I can focus on writing proper, well isolated unit tests. I’m almost done rewriting the tests and it has only taken a few hours. That time was well worth it to regain control of my tests.