>I hear the following phrase from various developers from time to time.
I can’t write these automated tests.
This is usually followed by some form of:
It’s very difficult to describe how to use my class.
In many cases with software development, the tests that are there are really functional tests and not true unit tests. They are testing the functionality of a particular interface, and not testing the individual classes or methods themselves. A recent entry on lizkeogh.com may explain why you are finding it hard to test:
….Probably it’s quite a difficult class to use correctly, then. How did you think of that API? Did you think of the class first, then think about how to use it?
Instead, try thinking as if you were the consuming class. Think, “I need something that does this for me. This is how it should look. This is how I want to use it.” Then write some code that does exactly what you want.
Because you’ve thought about how your class is going to be used, it will be easier to describe how to use it in the examples. It will also be easier to understand. So when you do successfully write your tests, you’ll know that your code is easier to change.
Part of the way to help with making code testable is unlearning what we have learned. In the past we came up with the design first, and then tried to implement the design. Test Driven Development and more particularly Behavior Driven Development, approach it from the opposite direction. It mixes the design and implementation at the same time.
Try thinking of how your consuming classes want to use the interface or method. What do they need. This approach allows for you to design only what is needed now, not what might be needed. Half the problems we run into is because of the nice to haves or maybe we need this feature. Thinking from the consuming class and how that class is to be used can help in making the design cleaner and easier to test.
Modeling can help with this, especially if you implement your test code and then start your modeling. Develop the test for the behavior, and then generate just enough model to address that behavior. Rinse and repeat.
One last note, this same behavior driven design pattern can be successfully applied to XML design as well. Too often we in the XML world toss the kitchen sink into our designs, when maybe a wash pan would do.