Saturday, September 24, 2011

My experience with unit testing in software development

I am not a fan of software engineering which is taught in school. Waterfall model, spiral model,  many blah blah phases ,diagrams and documents. I usually thought of those as useless works or not worth to do.  I thought that software development should be simple. Get requirement -> Draft design -> Go coding! ->  Debug -> Someone test it manually -> Debug -> Test again (until it's acceptable) -> OK, Finished

Documentation should exist only if it is essential and the source code is one of the documentation. This methodology works fine because I usually develop alone or in a small team and the software does not have many modules.

Unit testing is one of those which I thought it's not worth to do. I agree that's it's useful for regression test of the code but I thought I know what I've done with my code and know what are affected. 

Around two years ago, I and my colleagues started a new project. One of them wanted to try a kind of Agile development model (I don't know the name. I've said I'm not a fan of these models) and we tried.

He encouraged me to write the unit test for each class and a few acceptance tests for overall project behaviors. I did it because I wanted to give it a try too.

Then I know I was wrong about testing. I usually see some bugs because the tests fail. In addition, I feels great when all the tests go green. The tests guarantee that the software still work as it should. However, I see some disadvantages or difficulties in writing test.

First, White box testing in the unit test for each class are painful to maintain. When I change the code or the behaviors, It always breaks. Most of the causes are silly for example, syntax errors, missing mock and over verification. I also have to write the new white box tests for the new code which I definitely know that it will pass.

Furthermore, it usually be the acceptance tests which show the bugs. Unit tests don't.

The problem is the unit test granularity. As a result of these, I recently try to write unit test in black box way, testing only method effects to others (including return result) and I think about how small unit test I will write. If I write tests for every classes, as one-to-one, it will be the same as white box testing above. Then I decide to write only a unit test for a module or a group of classes. The group is grouped by top-most functional. The dependencies of the group which directly involves the file system or network are cut off to their own tests and replaced by mocks. They will be like smaller acceptance tests. 

Lastly, I don't feel constructive while I'm writing the tests. I love programming because I want to create something or have computer to do something but, for writing test, I don't get that feeling. I feel like a QA engineer who plans the tests and tests the software but instead of manually test, I write the code to test it. I have to mock various possible inputs, tests various output conditions and prepare many possible scenarios by writing lifeless code to do them. 

Yes, you got it. I want someone else do this task for me. LOL

BTW, I'm learning and I am thinking of how to destroy these difficulties and will update what I found in this blog in the future.