Testing Rails Apps at the Rails Edge Reston

Stu Halloway is speaking about testing. Mike Clark is pairing.

assert_raise plus a block helps you verify that code will fail – which is hard to do in languages *cough* Java *cough* without blocks.

assert_respond_to allows you to verify duck typing.

Think about if your collections are ordered or unordered. Unordered will let you use assert_equal. You can write an assert_collection_equal for ordered collections.

We should probably write an assert_belongs_to, an assert_has_one, an assert_has_many as a community.

BTW unrelated to tests, but a tidbit from yesterday – to see all the routes in your Rails app, type in script/console

puts ActionController::Routing::Routes.routes

Test everything in sight, at least at first.

Ruby is more information dense than Java. Stu has measured and seen that some of his Ruby code is 10x more dense the equivalent in Java.

Fixtures should be valid objects, because they will get used by other tests. I had to correct some people fixtures in client code recently because they had invalid email addresses.

assert_select is new in 1.2 and deprecates (mostly) assert_tag and assert_dom. Don’t get too crazy going into the DOM or else you can make really brittle tests.

Stu shared some of his special mojo: Witch. (Someone asked when they saw something flash by on the screen yesterday.)

Try to make your test suites fast enough so you can run your entire suite, instead of using rake recent.

Using transactional fixtures is a good practice.

How can Rails testing improve?

Naked tests i.e real unit testing, without the database. This can make your test suite go faster but more importantly isolates your model behavior from database side effects.

System tests and continuous integration are also missing. Rails integration tests are like poor man system tests.

What can help fill in those 3 areas? (Unit tests, system tests, and continuous integration.)

Flexmock (a gem) by Jim Weirich can help you do unit tests by isolating your models with the help of mock objects. Flexstub (another gem) helps when you want an object very similar to another one but is slightly different. Martin Fowler defines in his bliki article Mock’s Aren’t Stubs the terms: Dummy (a placeholder), Stub (an object that returns a canned response), Fake (an object that returns non-production-quality data), and Mock (an object which returns canned responses and verifies what you did to it.) Mocha can also help here, its like Flexstub.

Selenium helps you drive a browser to write a real system test. There’s a plugin and gem called SeleniumOnRails. You could use Watir, which only runs in IE. Watch this space.

rcov can help tell you when you’re done testing. But 100% doesn’t mean that its a well-tested app esp since it strictly looks at lines of code. I’d add the same thing is true about rake stats, just because you have a 1:1 Code to Test Ratio doesn’t mean your app is well-tested. Nevertheless, like the inaccurate body fat monitoring scales on the market, I think they’re good rules of thumb to let you know if you’re on the right track to a well tested Rails app with 100% code coverage and a balanced code to test ratio. As Stu says, its not an absolute metric, its a trending indicator.

All the sample code from the presentation is available in Rails for Java Developers.