Once again I’m about to do the wrong thing – forgo my assumption that stumbling steps are enlightening and not writing this post. I’ve just completed writing a unit test for a foo():Void haXe function with no flow control to its name. More about this another time.
Bear in mind, this article isn’t about what is or isn’t worth testing. My first step into TFD consists in having a fair go at writing tests before I write the code, without breaking my usual design flow – correcting my design flow is OK, if that’s what it amounts to. Correcting, yes – breaking, no.
Can we test the main() method? Do we want to?
I’m taking over a colleague’s work, now I’m sniffing the Main class and thinking hell, what shall I do with it. Test? Well yea, I should test it first. Since there are not unit tests for this project yet, I might as well consider it to be legacy code.
My colleague did something that I tend not to do – they just use Main.main() to instantiate a singleton. I guess it should really be a singleton but the point is, they escaped the static logic behind main. So I’ll follow in their steps and instead of testing main(), I should probably test whatever gets instantiated by main.
Unfortunately, as a good initializer does, mine mostly invokes other initializers. Essentially a constructor is a static function. So yea I could pass an array of classes and instantiate them by reflection, but I don’t want to do that. Too much trouble.
I had the neat idea to just call the constructor to make sure it works, but that’s not a unit test – that’s actually testing the whole f*** thing. Too integrated.
Why I don’t feel like testing main() and constructors anyway?
I’d like to test how my code changes the software system I’m building. Although I’ll come back to this later and discuss, a function that doesn’t return value isn’t making local changes, so from this point of view there’s nothing to test inside the unit.
So what shall I do?
Flowing with TFD?
Here’s my problem with test first development right now. I need a method that flows. If it flows slowly, fine, but right now my flow is frozen. Let’s get flowing and try this…
- I’ll always write a test for each function. That’s easier than asking everytime whether to write a test.
- If I can’t test the function, at least, I’ll document the test function with my design intention for the non-test function – that’s because I need somewhere to write my design intention. Then I’ll past this doc in the function’s code body so I can use it to write the actual code (that’s because my STM is very limited)
I’d like to still call these functions to make sure they don’t fail. That wouldn’t be a unit test, however. Oh my…
Working notes
No time for a conclusion today – just a few ideas
- In absolute, I’d really like to write my tests first. This is why I’d prefer to write an ‘untestedConstructor’ function rather than no function at all in the test class. untestedConstructor() may seem horribly pedant, but I like it. This way you know I haven’t tested this by looking at the tests. Also, I can move design comments to the test class – if the tests are gonna stand for documentation, I think that’s alright.
- So far, I only note I find it difficult to test root initializers. The type dependencies involved make it appear so difficult as to be counter productive. However, even with a statically typed language such as C++, doing this is likely not impossible (just map another .c file to the same .h file?).
- One view about testing is that only state transitions matter. ‘unit’ testing consists in testing a class. Applying this, we could say that a method that causes no local change needn’t be tested.
- Surely, a controller doesn’t manipulate it’s own state. A controller should hold no state. Does it mean a controller shouldn’t be tested? Oh my, controllers are were the case logic of a program resides… Maybe a productive idea – how about if we extract the case logic, so that the case decision can be returned from a function as a value. My counter-intuitive bet is that such functions should then be private – unfortunately, I heard over and over that a good unit test focuses on the public interface of a class. More contradiction. Or maybe we should just distinguish ‘do’ classes from ‘case’ classes; then we’ll have a good reason to make ‘case logic’ methods public.
- Another view about testing might be that it is the behaviour of a class we are trying to test. Even if a class doesn’t manipulate its own state, we still want to assert whether the changes it makes to the outside world are as intended. TDD programmers that use mock objects liberally seem to be on this side.
Enough musings for today.


Comments