Rails 4.0 Whirlwind Tour
Back-End Full-Stack WebRails 4.0 has yet to be released, but since it might be here by Christmas, it’s time to start getting ready.
One of the more complicated Ruby/Rails projects we work with at Highgroove has many points where it interacts directly with the filesystem.
Writing tests for an application whose code requires reading from or writing to the filesystem presents challenges, especially if done naively.
While it’s tempting to simply use the real filesystem during unit tests, this presents a few problems:
So what’s the solution? Fake the filesystem during unit tests.
More after the break.
Consider the following (contrived) piece of code:
Now, what’s the best way to test it? The tests can’t touch /etc/passwd due to permissions, and even if they could, writing to /etc/passwd would be destructive to the system.
How about mocking File.read
?
Assuming we’re using RSpec and mocha for mocking:
This works, but tightly couples the test code. What if someone comes along and refactors the production code, making use of File.readlines
instead of File.read.split
?
The code still works, but the test breaks because File.read
is stubbed, not File.readlines
. In fact, it’s now reading from the real system’s /etc/passwd. The code still works, but the test broke. Ugh!
A better solution is to stub the entire filesystem at a higher level, giving a blank slate each time a new test runs. Nothing is ever actually written to the filesystem.
Enter the fakefs gem.
It’s trivial to get up and running. If using bundler, I recommend adding it to the :test
group:
Next, configure RSpec to include the fakefs helpers to automatically activate and deactivate fakefs whenever a test is tagged with fakefs: true
:
And finally, write tests that are tagged with fakefs: true
. But this time, test code can manipulate any part of the filesystem, knowing it’s completely emphemeral and isolated:
Voila! While there is a bit more test code, the test is verifying behavior, not the specific implementation. Do you have any other tips for testing code that interacts with the filesystem?
Rails 4.0 has yet to be released, but since it might be here by Christmas, it’s time to start getting ready.