Sandarenu Chaturika is currently working as a Software Engineer at hSenid Mobile (beyondM) Pvt Ltd. She is a graduate of the University of Moratuwa obtaining a BSc in Information Technology (Hons) from the Faculty of IT. She has interests in JSE/JEE related technologies and is currently working on telco middleware applications at hSenid. She is very keen at learning new technologies and sharing what she knows with others.
 

How to Write Better Code – Unit Testing

04/27/2009 7:50 am By Sandarenu Chathurika | Articles: 6

This is the fourth article or my article series on writing better code.  During my previous articles we discussed about the importance of following naming conventions, choosing good names for programming elements, how to use comments affectively and how to write better methods. If you haven’t had chance to read those articles, have a look at them. You can find those articles in Digit’s archive.  This month I’m going to discuss about yet another very important aspect of programming; Unit Testing.

Unit testing is very important aspect in Extreme programming/Test driven development. Before going in to how unit tests fits in to TDD or XP lets first understand what a unit test is? Simply, it is small piece of code written to test the functionality of some production code. More formally according to Wikipedia, “Unit Testing is a software design and development method where the programmer gains confidence that individual units of source code are fit for use”.

Well that tells the whole story, isn’t it? Unit test are there to help ourselves to be confident that our code actually works, and it does what exactly we intended to do. How many times you have done some changes to your code and later found out that it had broken another part of your program. It could be really embracing if some of your colleagues found out that you have broken their code. Once you did the change you know that you have to do some proper testing to confirm that your change has not broke someone else’s code. But it is not easy to go through all possible paths and test all the sub-modules of the system, it is boring and time consuming. So what we do is we check whether the program is compiling and building correctly and do some testing at very high level and hope for the best.   Most of the time it is just a matter of time till someone else found out that our small change has broken large part of the system. How to avoid these kinds of problems? Answer is simple. Have comprehensive set of Unit Tests. So every time you do a change to the system, you can run your test cases and check whether you had broken any other code. If all the tests are passing, then you can be confident.

Even though this sounds simple, actually it is not that simple. Most of the times we think that writing unit test is a waste of time. Especially if we are stuck in a tight time schedule we simply ignore writing unit test, even though we know all the advantages which the unit test can offer. But trust me reality is exactly the opposite. In a tight deadline you don’t have much time for testing, when you do some change or done some bug fixes you don’t have much time to test all possible scenarios manually. So only way to be confident that you have done your job correct is to have proper set of unit tests.

 

Getting started with Unit Testing



Select your Test Framework

First step is to download some good unit testing framework for your language of choice. Today there are lots of Unit Testing frameworks freely available.  Some common such frameworks are JUnit for Java and NUnit for .Net.  You can find a comprehensive list of unit testing frameworks at Wikipedia.

Since this is not a programming how to tutorial I’m not going to discuss in details how to use those unit testing frameworks. You can easily find out simple tutorial by searching the web. I’ll give some tips on how to write better test cases.

 

Separate production and test classes

When you are starting, it is better to separate your production code from test cases. Best way is to have separate source folder for test cases and production code. As usual, have some common naming convention for naming test cases and test methods.

Production element name

Test element name

ProductionClass

ProductionClassTester

magicCalculator

testMagicCalculator

 

It is better to have same package structure as production classes in the test classes as well.  E.g. If org.samplepackage.ProductionClass is the production class then its test class should be something like org.samplepackage. ProductionClassTester.

 

Figure 1: Folder Structure with separate production and test source folders

 

Test behavior, not methods

In a class behavior is defined by its methods, more specifically by public methods. So you should be able to test the complete behavior of the class by testing its public methods.  Since those public methods will call private methods inside the production class we can indirectly test them. But if you really want to test individual private methods, you’ll have to make them protected or to use some reflection mechanism to test them.

 

Keep your test cases clean

There can be no double standards for production code and test cases. So make sure you follow all good techniques we discussed in our previous articles when writing test cases as well. Refactor your test cases time to time and maintain them clean.

 

Test Driven Development

Test Driven Development or TDD is a development philosophy; it is not a method of testing software. TDD is related to the Test First Development principle of Extreme Programming. TDD has easy to follow three simple laws.

1. You may not write production code until you have written a failing unit test

2. You may not write more of a unit test than is sufficient to fail, and not compiling is failing

3. You may not write more production code than is sufficient to pass the currently failing test.

Even though these sounds like bit complex, they are actually not.  In simple terms these three laws describe the follows. You first start with the test case, you don’t write any production code.  Code will fail to compile since you are trying to test a class which is not excising.  So create the production class. Don’t put any code inside, just create the class (see rule #3). Now add more code to you test, may be to call some method; then create that method inside production class. Write more tests; add more production code and this process goes for many iterations until you completed both test case and the production code.

If you really can follow these laws, it can reduce lot to time wasting bugs in the long run. When I first start following TDD, my initial thought was that it is a waste of time. But after some time I found out the real value of TDD.  When you do some code change or refactoring, you can run your test cases and find out whether you have broke anything very easily.  When you follow TDD you can be sure that you have near 100% test coverage, since you right test cases along side with your production code, rather than writing some ad-hoc test cases.

To get the maximum advantage of TDD you have to be much disciplined. If you try to break the process since dead line is near then there is no point. Even though it takes bit more time, you can be sure that your code is 100% working and reduce lot of debugging time, and unexpected issues which will actually delay your project.

I’ve only discussed very few things related to unit testing and TDD. There are many books written on this title. I highly encourage you to go and have look at on them and improve your knowledge. And as always just by reading you can be an expert, practice it.

 

Previous Article

Share/Save
No votes yet

thanks

>>If you really can follow these laws, it can reduce lot to time wasting bugs in the long run. When I first >>start following TDD, my initial thought was that it is a waste of time. But after some time I found out the >>real value of TDD.

agreed !

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Image CAPTCHA
Enter the characters shown in the image.