Adventures in code and computation.

Taskelot Journal: Unit Testing Drama

Taskelot dev journal and notes for Thursday, 21 May, 2015.

12:07 PM – Focus

Really digging in my heels to focus on my current side project: Taskelot. So far I’ve gotten the basic testing infrastructure set up for Taskelot. Trying to work out the best way to test an implementation of the interface class I created. I need to also get linters hooked into the testing workflow.

Other things on my agenda for Taskelot today include:

12:38 PM – Vim, Tmux, & Testing

Yesterday night I spent some time re-figuring out how to integrate Vim and tmux in a simple way to make it dead simple to run my test suite from within Vim. I can now type <Leader>s from within normal mode and that sends make test to the appropriate pane in tmux so that the command runs and outputs there. I’m not using a plugin, just a simple mapping (which I can remap from within Vim anytime I need). Works great for my needs right now.

Vim + tmux + unittest == FTW

05:46 PM – Testing Classes; Challenges Keeping Implementation Private

What am I even trying to do here? I’m attempting to write tests for things as I go, as much as possible writing the test first. I have an object model concept something like this:

So I have written some tests making sure the core methods of TaskelotInterface return a NotImplementedError; that means if one of the methods get called when they should have been overridden by a subclass: BOOM! So far so good (though the tests feel pretty rote and meaningless, I stick with it to try to get at least some progress, even if I end up needing to redo it, assuming I find a better way).

But then I try to write a test for TaskelotInMemory. The first test I think to write is testing that it can be instantiated. This is pretty much like a hello world program sort of test– we’re not really testing anything except that we have a class definition. But then what? Do I write a test for the implemented save() method? The unit test should be testing the behaviour of the externally accessible methods right? If so, how do I verify save() actually does anything? I can’t using only external aspects of the API without broadening the scope of my test, making it less a unit test. The other option is to introspect the actual implementation of the instance of the class to make sure the save() method did what I expect, but then I’m not testing the external interface but rather the internal implementation details. I want the internal implementation details to be loosely coupled with the external interface such that the implementation could change without breaking the interface. So that’s my current conundrum.

Another issue confronting me is that Task will be associated to some TaskelotPersistenceDriver (which will implement TaskelotInterface), which itself will import Task to create instances of it in response to at least the all() and get() methods. That smells funny to me. Funny like a circular dependency or at least reference. This is likely a sign that my design is wrong and in need of serious revision. If that turns out to be the case it’s alight; that’s the point of trying, I might discover I have the wrong approach and be able to try something else which ends up far better– that’s the goal.

Taking a break for today. If I get any more done on Taskelot tonight worth sharing I’ll update this post, otherwise stay tuned for future updates in an upcoming post.