RSpec and the joy of testing 2

Posted by Matt on January 29, 2008

rspec89 database tables, 93 fully RESTed objects, 4740 successful tests. Life is grand.I’ve spent years working in web development with PHP (as I’ve describe ad naseum), and I’d hate to admit it, but I’ve never written a test. Ever. My stuff works, but soon after every launch, small cracks start to appear. The worst part is that these small cracks are always found by my users. This is not only embarrassing, but it leads to me furiously debugging a live system with active users, trying to quickly recreate the conditions that caused the error. I like my hair and I’ve losing it fast enough, thank you.Enter RSpec and Behavior Driven Development (BDD). RSpec makes writing tests a joy. Yes, I know, I know, but testing can be a real joy. It’s like working out; it always seems super difficult to start, and you stall and think of a billion other things to do, but once you actually start you feel really good and alive.BDD makes testing second nature, and RSpec makes writing these tests intuative. You know those meetings you have with your clients and you try to distill what they truly need from what they tell you they need? BDD gives you a language that both you and your clients can speak; you simply describe how an object should behave:A Car not only has a color, it also should not be driveable with one tire and it should only be driveable by a licensed driver.

describe "A Car" dobefore(:each) do@car = mock_model(Car)@driver = mock_model(Driver)endit "should have a color" do@car.color = nil@car.should_not be_validendit "should not be driveable with one tire" do@car.tires = 1@car.is_driveable?.should_not be_trueendit "should be driveable with four tires" do@car.tires = 4@car.is_driveable?.should be_trueendit "should not be driveable by an unlicensed driver" do@driver.stub!(:license_active?).and_return(false)@car.stub!(:driver).and_return(@driver)@car.is_driveable?.should be_falseendit "should be driveable by a licensed driver" do@driver.stub!(:license_active?).and_return(true)@car.stub!(:driver).and_return(@driver)@car.is_driveable?.should be_trueendend
See? Simple. As with most Ruby code, RSpec features English like statements that are immediately comprehensible to anyone—even clients. You know what the best thing is about RSpec though? It not only tests your code, it documents your code. Just look:
A Carshould have a colorshould not be driveable with one tireshould be driveable with four tiresshould not be driveable by an unlicensed drivershould be driveable by a licensed driver
Imagine testing and documenting your code at the same time! Two things that many programmers skip altogether! That alone makes the Ruby on Rails framework and mindset the most attractive choice today.