Best Practices to write JUnit test cases in Java

JUnit best practices in Java
No doubt writing good JUnit test cases is a rare skill just like writing good Code. A good, well thought and well written JUnit test can prevent several production issues during initial development or later maintenance in Java application. Though one can only be perfect in writing JUnit test by practice and a level of business knowledge which is important to envision different scenarios on which a method gets called, some best practices or experience of other developer may help to guide other programmers. In this Java article I am sharing some JUnit tips and Junit best practices which I have learned and follow while writing unit tests using JUnit for Java programs. One of the book which helped me a lot is Pragmatic Unit Testing in Java with JUnit by Andrew Hunt and Dave Thomas,  This book shares lot of JUnit best practices which is worth reading and learning if you are serious about Unit testing using JUnit. Never undermine importance of automated testing and test cases written by Developer who writes the code and that's the reason many company are asking programmer to design, code and provide unit tests during there Java interviews. These JUnit best practices not just apply to JUnit but to any other testing framework as well like TestNG, they are more on testing and writing test cases which is more important skill than tool like JUnit or TestNG.


Junit Best practices

JUnit best practices - testing guidelines
Here is list of 10 JUnit best practices I have compiled , As I said these best practices are related to testing, thinking test cases and writing test cases rather than focusing on JUnit features like Testing Exception or Timeout.

 1) Its not practically possible to get 100% code coverage, so don't aim to write unit tests for each methods and trivial operations, instead write unit tests for method which is likely to have bugs during maintenance. Always tests core method and core classes which is used heavily by different parts of program. If you follow this best practice while writing test, you will be surprised with the quality of code, it often result in less bugs during formal testing cycle.

2) Integrate Junit tests with your build script so that with every compile your tests run automatically. Maven and ANT two most popular build technology for Java application provides support to run Junit tests. This is not just a best practice but an standard of building Java application. Always run test cases while building projects this not only verify new code but also alert with any potential error which results due to recent changes. some time while fixing a bug developer introduce another bug, if you have JUnit test integrated with build or following CI practices than you are better prepare to deal with them.

3) Develop test cases based on usage and boundary conditions, This is my favorite Junit test practice and mostly asked as interview question on JUnit as well.  For example if you are asked to write a function to replace all occurrence of a given character from String e.g.

public String replace(String text, char ch){ …}

How will you write test case for that? to my surprise many Java program start focusing on JUnit test syntax like setUp() and tearDown() even before thinking of actual test scenarios like :

1) Test for empty text or empty character?
2) Test for character which is not in String?
3) Test for characters which comes during start, end or middle of String?
4) Test to cover if text String contains just one character which is equal or not equal to the replaced one?
5) Test with String contains just contains one character multiple time?

These are just few of test cases I can think of but idea is focus on what to test and not how to test, most IDE like Eclipse and Netbeans will take care of that. Though you should have basic Idea of essential functionality of JUnit testing like how to test Exceptions, Timeout etc.

4) Make sure your Junit test are aligned with your business requirement specified in  BRD or Business Requirement document. 

5) Write test for non functional requirement as well, like while writing a Thread safe class, its important to write tests which tries to break thread-safety.

6) If a function or method is depends upon order of events than make sure your JUnit test covers ordering requirement and my take is to test both side of coin means with correct ordering method should produce correct result and with incorrect ordering it should throw Exception or confirms the alternative operation.another JUnit best practice which is worth remembering.

7) One Idea which helps me while writing unit test is to create dummy tests while working with requirements because that’s the best time you remember requirements and having a test case with a comment that describe intent of test let’s you to implement it later or just put @Ignore if you don’t have time to implement test and using Junit4 annotations. This helps me to cover most of requirement while writing code as well as test. this just enforce you to write as many test case as defined by requirements.

8) Writing trivial JUnit tests like for getter and setter method is mostly waste of time. remember that you don't have liberty to write infinite number of unit tests neither in terms of your development time nor while you are building your application. as unit tests run automatically  during build process, they are required to finish early and trivial unit test just add on time and hide more useful case to run later.

9) Keep your Unit test independent of Environmental data like Database, File System etc.  Unit test depends on environmental data may work on some environment and may not work on other. Its good idea to use carefully chosen set of data embedded in test cases as well as a placeholder method which can be plugged to database if required using configuration.

10) Use available tools like DBunit, XMLUnit and Spring test framework based upon your project and your need.

In Summary code review and Unit testing is as vital as writing good code and good comments. Think through requirement while writing test cases and focus of scenarios. I hope these JUnit and testing best practices will help you to write better code.


Roshni said...

Most of these JUnit Best practices can be asked as JUnit Interview question. They are very fundamental and anyone who claims to work on JUnit 3.8 and 4.0 should know answers of these question. Please share some more JUnit interview questions

Anonymous said...

One practice we use while writing JUnit test is to create an Abstract base class for all test. Responsibility of that class is to configure system for testing e.g. providing configuration data, setting up database and clearing it after end of test case. Its more like a system wide setUp() and tearDown() method.

Second best practice is to create meaningful assert method for your own use, for example you can create assertCustomer() method which further assertCustomerID(), assertCustomerName() or any other parameter, which needs to be asserted but not available via equals() method.

Anonymous said...

One thing I learn while following Test Driven development is that you can use default implementation to provide dependency in order to execute your JUnit test. For example, if your code needs a Sender which sends message over Socket, instead of using actual Sender object, you can create an implementation of Sender interface which just print "Sending message" instead of actually sending message. This would be enough to test that module, which has dependency on Sender.

Anonymous said...

If you are writing JUnit test for data access code, one of the best practices is to make sure you delete the data after test e.g.

insert data
delete data

By the way make sure, your data should deleted even after validation fails.

Saumya said...

One of the JUnit best practice is to design for test-ability. Your code should be written on interface than actual implementation. For example, if you have a method that is meant to output to a file, don't pass in a file-name, or even a FileWriter. Instead, pass in a Writer. That way you can pass in a StringWriter to capture the output for testing purposes. Then you can add a method (e.g. writeToFileNamed(String filename)) to encapsulate the FileWriter creation.

Post a Comment