Notes on Let's Make Testing Fun Again
The talk
Let's Make Testing Fun Again at WindyCityRails 2012 | Lanyrd
Communication
Tests give you about the code. This happens over time, where you find that tests have become hard to write, the tests are becoming complicated and bogged down.
Rather than use it as an opportunity to blame the test or to blame testing, you should use it as an opportunity to learn something about your code, that there is a dependency that could potentially be simplified, or something you could be doing better.
Keep relevant setup close
This is something that "relative good"(in terms of "absolute good"). It's generally good to keep the setup of your tests close to the tests where it is.
What you want to avoid is the case where some sort of
before
setup way at the top of the file and you have stuff, and more stuff, and more stuff, and eventually in the end, what's the@user.name
? I don't remember.
An Example
describe User do
before do
@user = Factory.build(:user)
end
# and more stuff
# and more stuff
it "uses the user" do
@user.name.should == # i don't remember
end
end
This is where you see sometimes people say "You should never have setup outside your original test".
What to do about duplications and complicate shared setups
I think a lot of times if you need a complicated setup to test code, that often means your code is too complicated you need to start working out to move your dependencies. I tend to have a higher tolerance for duplication in my tests than I do in my regular code, specifically because I'm more interested in having the communication close, and less interested in maybe being clever about extracting setups in my tests. Sometimes I do if there's a piece of stuff that's really tightly coupled, and I can give it a descriptive enough name that I still feel like I have the benefit of keeping the setup close in the actual test.
Test Simple Values
By using literal in check, when the spec fails, the error message is much easier to understand.
Spy, don't mock
A jasmine
test example.
var cheeseburger = {
cheeses: function() {
// Ajax call to cheese server
}
};
it('spies on the cheese server', function() {
spyOn(cheeseburger, 'cheeses');
cheeseburger.cheeses();
expect(cheeseburger.cheeses).toHaveBeenCalled();
});
- Readability advantage
- Easy to find where actually fails
BTW, if in spec, we need write like this:
it 'spies on the cheese server' do
# in the reversed order
cheeseburger.should_receive(:cheeses)
cheeseburger.cheeses
end
More about Spy on Ruby and Rails
thoughtbot/bourne gem can let you have the rspec-like test spies syntax.
Spy vs spy, good explanation on what is test spy the benefit of it.
What Do We Love?
These are quite frank and interesting questions.
- Do we still love writing tests?
- Or do we just love having written tests?
- Or do we just love saying that we've written tests?