Despite I’m not new to TDD process and try to implement its principles during my own projects, lately I have came across interesting issue.
Within our system, there is a component which controls “workflow”, subsequently triggers objects to make database queries or executes an sql INSERT, UPDATE, DELETE actions.
The problem I’ve had was not with testing itself, but with the complexity of such tests. At one moment to test a behavior of a complete system I needed to prepare whole set of description objects and use them as the parameters with our assert functions.
Of course it’s feasible, but it costs a lot of hassle to prepare correct objects and calling them in order, to check the main component’s flow (SUT – system under test).
Another problem I’ve run across was with preparing correct SQL queries and comparing them with SUT calls. Combining those two elements in variety of scenarios made my unit tests very complex and while refactoring it’s sometimes not a easy thing not to get lost in correct call order.
This all made me wonder if the tests I prepared are correct. Not from the technical point of view, but from unit test “sematic”. When I’ve finished working on another part of my projects and had a little bit more time to think it over, I made some interesting notices.
First of all, as you may notices, I made my tests over complex. Being at frenzy of writing code at one moment I’ve forgot about testing one functionality at a time, and very fast my tests seems to became redundant. Even if one elements has been already tested, I implicitly check results in other tests as well. Especially when comparing database calls to see if operations has been executed in right order and on correct objects.
It would be more pragmatic to split my tests to layers. At one point checking the sql syntax, at another the database calls made by objects and at the final to assert the order calls. At each level tests would only access and check objects SUT interact with. However this could mean creating unnecessary “getters” for those objects or creating fake objects to interact with main objects and be able to retrieve the state and behavior.
Nobody want to make their tests primary field of application development. At the end, there is always a client and even the most effective tests could not be delivery alone. As stressed, i feel it’s very important to split your test into separate layers, but also not at the cost of your man days.
When in comes to testing behavior of your objects it could be useful to take into account mock object. “Mocks aren’t Stubs” by Martin Fowler describes in details difference between different fake types which could be use within test.
In the past I’ve tried to write my own mock objects. At first I used them as a way to verify state. Now after Fowler’s article I wonder if it would be more cleared to split mock for behavioral and stub for state tests. While stubs are relative easy, mock are not. Because on my daily basis I’m programming in C++, CppUnit as test library feels as very natural choice. Sadly this library seems not to have any support for mock. Checking possible solutions I very fast learnt that there is very compelling test suite from Google.
Google Test and Google Mock have anything C++ agile programmer could dream of. They are not over complex and with they help you are able to start writing your tests in couple minutes. To be honesty I’m new to those tools and still feel more flexible while using CppUnit. Although as it lacks any mock capabilities, Google Mock could be great addition to my test tools.
I hope this would give you some example of possible pitfalls you may end in. If you are not re-thinking your tests correctly and solutions how you may solve them with better understanding of what you want to accomplish. With small or non-complex projects it might not be so important, but with other you may very fast end up with maintaining your tests instead of moving your application further.
Think before type, it costs less of your time and money.
If you think I missed something or make a untrue statement please don’t hesitate to contact me. In the meantime take a look at those links below and remeber.