Testing is a Remarkable thing!
I never knew testing could really change the way I code. I know I’m a good programmer because I love implementing standards and doing the “right things” the “first time”.. and yet testing has made me realize something..
I never got to know how to properly test my own code. I’ve only used a lot of selenium, trying to dig into making it work for simple end user testing and usability of the application, but framework testing that involves the unit tests, integration tests and even performance tests are now putting themselves in the limelight for my programming career.
Looking at a huge challenge of writing tests for an old yet immature application (that I know of), I felt that this would be a very beautiful yet painstaking challenge. It can help me grow as a programmer and still save the project and the sanity of my colleagues. I have closely inspected the use of certain frameworks.
The following have been my choices: RSpec, Shoulda, Cucumber, Rails Unit Test. I have asked around and most of my network responded with their love of RSpec. I know that RSpec is already gained widespread use and popularity amongst Rails developers, but as I was also looking into using Shoulda, I found that there truly were things that I did not like from RSpec that I very much found in Shoulda. Some of these are:
- I am having difficulty of testing nested resources in RSpec.
- RSpec’s it-something-blank syntax doesn’t really amuse me (on a personal note, thought it fascinated me way back at the time I discovered it).
- I don’t like the way messages are displayed by RSpec when a test case fails.
Now, what I was missing in between was using the strength of RSpec in all other areas, and the readability and macros of Shoulda. Here is when I stumbled across Remarkable; and truly I must agree it is remarkable!
I have immediately jumped into writing a simple test for one of my models as follows:
class Feedback > ActiveRecord::Base
acts_as_audited
validates_presence_of :name, :message => "..hey you can't be anonymous!", :on => :create
validates_presence_of :email, :message => "..I need your contact details.", :on => :create
validates_presence_of :topic, :message => "..what are you writing to me about?", :on => :create
validates_presence_of :message, :message => "..so you were saying?", :on => :create
validates_format_of :email, :with => /^([^@\s]{1}+)@((?:[-a-z0-9]+\.)+[a-z]{2,})$/i, :message => "..it should look something like yourname@something.com", :on => :create
validates_length_of :message, :minimum => 5, :message => "..uhm, can you be more specific?"
validates_length_of :name, :minimum => 3, :message => "..uhm, can you be more specific?"
validates_length_of :topic, :minimum => 5, :message => "..uhm, can you be more specific?"
end
I know there are only few resources in the net that show you the exact counterpart of code being tested and test codes, but here’s mine. Maybe this can help.
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe Feedback, 'A Feedback instance' do
VALID = {
:name => "firstname lastname",
:email => "email.email@email.com",
:topic => "some topic",
:message => "some message"
}
it 'should accept VALID attributes' do
assert f = Feedback.new(VALID)
assert f.valid?
end
should_require_attributes(:name, :message => "..hey you can't be anonymous!")
should_require_attributes(:email, :message => "..I need your contact details.")
should_require_attributes(:topic, :message => "..what are you writing to me about?")
should_require_attributes(:message, :message => "..so you were saying?")
should_ensure_length_at_least(:name, 3, :short_message => "..uhm, can you be more specific?")
should_ensure_length_at_least(:message, 5, :short_message => "..uhm, can you be more specific?")
should_ensure_length_at_least(:topic, 5, :short_message => "..uhm, can you be more specific?")
should_allow_values_for(:name, "maricris", "ace", "greg", "john paul", "mary jesus joseph")
should_not_allow_values_for(:name, "aa", "at", "jp", "1", "s", :message => "..uhm, can you be more specific?")
should_allow_values_for(:email, "email.email@email.com", "email_email@yahoo.com", "123@yahoo.com")
should_not_allow_values_for(:email, "123@.com", "testing!@!yahoocom", "3@11234.#8com", :message => "..it should look something like yourname@something.com")
end
There. I know its not the best and the prettiest, but its a work in progress. Writing these wee lines of code to test a small, almost bare model was truly a worthwhile experience. What I really liked about doing this was the fact that at some point, while I was working backward (not the usual TDD), when I arbitrarily took that my model was initially written meekly but completely, I was wrong.
In the process of enumerating the cases where the validation should fail, I really had to go back to my model and change something. Writing tests can make you more precise, and even make you feel that you can bring out your code to production and feel confident.
I can now see why Gregg said he learned to love testing too. Its not like I am forcing you to, but you should have a taste of this cake and be your own judge. Will you like it or not? ..its totally up to you. This will bring me not just sanity, but also confidence and a lot more freedom to rewrite and refactor in the future. Just great!