A Real-Life Contract Test - The Code Whisperer

For years I’ve written about contract tests, and most notably have never had any clear examples of them to share with you. I’d like to change that today.


This is a companion discussion topic for the original entry at http://blog.thecodewhisperer.com/permalink/a-real-life-contract-test

If I've understood your "Integrated Tests are a Scam" talk correctly, there would be a collaboration test between the Atom Plugin you are building (or something within the plugin who is the client) and the `word count` collaborator. In this case, how did you verify that the client was respecting the contract? i.e. that the client called `countWords` with an arity of one and not some other method with a different signature.

I didn't write collaboration tests between Atom and my plugin, because I don't control instantiating parts of Atom, and Atom doesn't appear designed to make that easy. From what I can tell, I simply export an object that has functions activate(state) and deactivate(). I have no earthly idea how Atom invokes them, and I haven't yet had the energy to find out. Instead, I did the next best thing: I started with logging statements and manual tests to gain enough confidence in my understanding of the contract between Atom and my entry point. console.log() ain't pretty, but I found it effective in this case.

Same for registering commands in Atom. I first registered a command with a handler that sent "Hello" to the console. Once I saw that that worked, I felt confident in using any 0-argument function there. Not great, but since I'm not contributing to Atom core, I decided that that would do.

I do this dance with every framework: figure out the minimum I need to know with manual tests, then get to test-driving something as soon as I can. In this case, I found the contract between Atom and the entry point so simple that I didn't feel the need to do anything more complicated than that. I hope that doesn't backfire on me.

In this case, I test-drove from the bottom up towards the entry point. I have a View that verifies that that the Atom command triggers my plugin to "toggle". jQuery already knows how to toggle, so that's easy.

To answer your question at the end, I have a collaboration test showing that my Model uses countWords() correctly. I'm missing tests for my View's updateStats() function. By that point I wasn't in the mood to figure out how to write good collaboration tests with Atom and jQuery. If I have to enhance the plugin, then I'll spend more time to figure that out.

You can look through the rest of the specs here: https://github.com/jbrains/...