What parts of my models need testing?
According to the folks who take test driven development seriously, the only features that need testing are the features that need to work. Though this is obviously a bit facetious, it's fairly close to the truth.
To break it down into a few categories, you will definitely want to test the following components of your models:
- search functions
- model logic
- anything else that does something interesting
Entry model from Tasty has several components that fall into these categories:
class Entry < ActiveRecord::Base validates_uniqueness_of :url belongs_to :user has_many :taggings has_many :tags, :through => :taggings def created_date created_at.strftime("%Y.%m.%d") end def updated_date updated_at.strftime("%Y.%m.%d") end # Adds a tag with the given name, if it's not already present def tag_as(tagname) unless tagged_as?(tagname) tags << Tag.find_or_create_by_name(tagname) end end # True if tags include a Tag with the given name, False otherwise def tagged_as?(tagname) tag_names.include?(tagname) end # returns a list of tag names def tag_names tags.map(&:name) end protected def validate if short_description =~ /rube goldberg/i errors.add("short_description", "can't include references to Rube") end end end
We'll start with the validation tests, and then move on to some of the other functions in this model, showing several different tests and how they work.
Since the purpose of a validation is to maintain data integrity, it's very important to test that they work properly. If you think about it, one intuitive way of testing a validation is to attempt saving invalid data and then to ensure it is handled correctly. That's exactly what we'll do, so let's start by ensuring our unit tests know how to fail (proving that they're hooked up). We also won't be using fixtures for this set of tests, so you can remove that line too.
require File.dirname(__FILE__) + '/../test_helper' class EntryTest < Test::Unit::TestCase def test_validates_unique_url flunk "Test failed as expected" end end
If all goes well, running
rake test should give you something like this:
1) Failure: test_validates_unique_url(EntryTest) [./test/unit/entry_test.rb:5]: Test failed as expected.
This proves that
test_validates_unique_url is being called, which means we can replace it with a real test.
require File.dirname(__FILE__) + '/../test_helper' class EntryTest < Test::Unit::TestCase def test_validates_unique_url # Add an Entry to the DB so we have something to compare against base = Entry.create(:url => "http://rubyreports.org") assert_valid base e = Entry.new(:url => "http://rubyreports.org") # entry has an identical url, so we expect it to not be valid assert(!e.valid?, "Should not save entry unless url is unique") assert(e.errors.invalid?(:url), "Expected an error for duplicate url") end end
Running the tests again, you should see that they pass. If you're paranoid, go ahead and remove the
validates_uniqueness_of call from your model, and watch the tests fail.
Why no fixtures?
In the User tests for Tasty, I showed how to use fixtures just because its inevitable that you'll encounter them while working with Rails. However, it turns out that they've got a few sticky spots, and a lot of times, you simply don't need them.
By just explicitly calling
Making ugly assertions pretty via test_helper.rb
At the very top of your test, you see that rails requires the
For example, it would be nice to have an