Regression Tests, Rspec and Rails

This is a guest post by Erwin:
When i first started to work with Ruby on Rails the terms “Behaviour Driven Development” and “Test Driven Development” have been used in nearly every tutorial and screencast. Soon i realized that testing your code is mandatory to build reliable software. Until then, testing was just optional and as many of you know very tedious. Even the setup of your test suite can be hard to accomplish if your application has a complex structure (consider dataflow logic, modeling logic or even time-based logic). Luckily Rails has a bunch of easy-to-use libraries (gems) to test your application.

A popular gem for testing your Rails applications is rspec. Just add the rspec-rails gem to your Gemfile and run the provided installer and you are good to go to test your Rails application. As mentioned before testing can be very tedious due to the fact that a lot of test-scenarios are repeated with a slightly different parameter or environment and even with rspec and the DRY philosophy repetition of code cannot be eliminated completely.

To bring up an example let’s consider the following ActiveRecord model:

# == Schema Information
#
# Table name: foos
#
#  id               :integer          not null, primary key
#  title            :string(255)
#  bar_id           :integer
#  account_id       :integer
#  created_at       :datetime
#  updated_at       :datetime
#
class Foo < ActiveRecord::Base
    # === Relations ===
    belongs_to :bar
    # === Validations ===
    validates :title, presence: true, length: {maximum: 255}, allow_blank: false
    validates_presence_of  :bar
end

This model has only one relation to another model called :bar and two validation methods that ActiveRecord provides.
The question is do we need to test this model and if we do what would the test or spec look like?

Well, we could rely on ActiveRecord and assume that it executes properly and that ActiveRecord has its own tests to make sure that those validation methods and relations are not broken and in fact ActiveRecord has those tests. So what we don’t want is to test ActiveRecord again. We want to abstract from that and capture the behaviour of our model into a test or spec. This captured behaviour then can be used to inform us about changes to a model and how those changes can possibly afflict other models.

Consider a scenario where we would delete the Bar model and didn’t think about the Foo model that it has still a relation to it. The worst case of this scenario would be that your shipped software crashes and your client payed for a broken software. To avoid this case we could apply regression based testing. Regression testing is a type of software testing that seeks to uncover new software bugs, or regressions, in existing functional and non-functional areas of a system after changes such as enhancements, patches or configuration changes, have been made to them.

The intent of regression testing is to ensure that changes such as those mentioned above have not introduced new faults.

describe Foo do
    it { is_expected.to belong_to :bar }
end

As we can see our test sample is not very complicated and does not test a complex behaviour of our system but it can give us feedback about our structure and ensures us that the relation :bar exists. Such feedback can be very useful, if used in combination with continuous integration tools like jenkins or travisCI. A drawback of such tests would be that every test case needs to be written manually and depending on the model there would be a lot of test cases that are similar in their structure. So we are in need for an automated approach to somehow generate this test cases and update them when we apply changes to our model.
To solve this issue a rails generator was used to create specs based on relations, validations and their database counterpart. This generator then was put into a gem and published on github (https://github.com/ndea/regressor).

I enjoy your feedback and comments! Thanks.