TDD, time wasting and Psuedo-Tests
I’m probably going to be shot, stabbed, burned drowned and buried because I’m writing this but I hope that I reach out to enough people before I go out!
My friends, watch out! TDD can be a really huge timewaster.
When did you know exactly how you expected your application/component to behave? Probably you didn’t until you tried a few things out, then sketched on some paper then thought some more then tried some other stuff again and then got back to paper etc. After that you had a perhaps clearer idea of what it was that you want to create. This is prototyping and it should be the first stage in any new/enhanced application. Once this has been done and you know the properties of your system then you can commence TDD.
If you didn’t do prototyping and you naively started writing your unit-tests then you have just wasted your time. I really don’t understand how people can argue that they should write tests first before they implement anything. If you write a test and expect it to mysteriously define your application then you are better off just using water-fall. I don’t feel very “agile” when I’m sitting there writing unit tests for something I will develop just to realize that I need to re-write the tests every 10 minutes. ALL the tests that I write before I write code I need to constantly rewrite… This is a black hole for time.
Instead I propose psuedo-tests.
Before I continue some people are probably going to argue that I “didn’t do it right” or that “it works for me you must be doing something wrong” well I don’t really care because you probably wasted your time and you didn’t know about it. I tried the whole lot and it is such an annoying thing that I don’t understand how it has become so popular. TDD should have a big IF in front of it like this: “IF you are going to do TDD, then make sure that you KNOW what it is you are going to develop”.
So what are psuedo-tests?
A psuedo-test is a test that doesn’t test anything it is just used to conceptually affect the design of your code. It is like psuedo-code but instead describes how the tests will run (instead of how your algorithm or code will run). This has the following benefit on your development
- Psuedo-code is _very_ easy to change. You don’t have to care about the actual interfaces or compilation or running or changing details everytime your code change.
- Your code takes testing into consideration. Things like get/set functions and various introspection function are taken into account, you seldom have to add these later. In Erlang e.g. it is usual to have a start/0 function instead of start_link/0 for testing purposes.
- The tests become simpler and smaller and easier to understand. Why? Well because you don’t have to rewrite your tests 600 times, you rewrite less often. Many people forget that tests are code as well and re-writing something and building on top of things in a very fast pace creates bulky code.
- If you write enough psuedo-tests then the step to property-based testing is not far (using tools like QuickCheck etc).
Example: We want to create a supervisor, then one test could be:
test_sup() -> Start supervisor Start a child under the supervisor Check that the supervisor has 1 child Check that the child of that supervisor is alive Kill the child Check that the supervisor has 1 child Check that the child of that supervisor is alive Stop supervisor
Then during implementation you realize that it would be a good idea to kill the children if the supervisor was stopped so instead of implementing it in your test code immediately you simply update your psuedo-test first adding
test_sup() -> ... Stop supervisor Check that the child is dead
This is much faster and you don’t have to care about implementation details… you can get on with your coding. The test is your specification and your guide without wasting your time and as you can see… this isn’t very far from a property if you define it well enough. Then just abstract this test to handle N children and you are good to go for a property test. When you have something substantial to test then implement your tests and run it!
I am NOT saying that you shouldn’t test! That is not at all what I’m saying… you should always properly test your code. I’m just saying don’t spend all your time writing silly tests just because you are doing “TDD” or whatever… have the tests make sense! Test something substantial that make sense!
Just a thought… Now I’m going to bed…