Friday, August 11, 2017

Writing JUnit Test Cases in Java? Follow These Best Practices to Create Better Tests

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 another developer may help to guide other programs. 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 books which helped me a lot is Pragmatic Unit Testing in Java with JUnit by Andrew Hunt and Dave Thomas,  This book shares a lot of JUnit best practices which are worth reading and learning if you are serious about Unit testing using JUnit

Never undermine the importance of automated testing and test cases written by Developer who writes the code and that's the reason many companies are asking programmers to design, code and provide unit tests during their 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 are more important skill than tools like JUnit or TestNG.


Junior Best practices

Here is a 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) It's not practically possible to get 100% code coverage, so don't aim to write unit tests for each method and trivial operations, instead, write unit tests for a method which is likely to have bugs during maintenance. Always tests core method and core classes which are used heavily by different parts of a program. If you follow this best practice while writing test, you will be surprised with the quality of code, it often result in fewer bugs during the 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 a standard of building Java application. Always run test cases while building projects this not only verifies new code but also alert with any potential error which results due to recent changes. Sometimes while fixing a bug developer introduce another bug if you have JUnit test integrated with the build or following CI practices then you are better to 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 a 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 the 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 a few of test cases I can think of but the idea is to 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 a test for the non functional requirement as well, like while writing a Thread safe class, it's important to write tests which tries to break thread-safety.

6) If a function or method depends on upon the order of events then make sure your JUnit test covers ordering requirement and my take is to test both sides of the 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 the requirement while writing code as well as test. this just enforces you to write as many test case as defined by requirements.

JUnit best practices - testing guidelines8) Writing trivial JUnit tests like for getter and setter method is mostly a waste of time. remember that you don't have liberty to write an infinite number of unit tests either 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 adds on time and hide more useful case to run later.

9) Keep your Unit test independent of Environmental data like Database, File System etc.  The unit test depends on environmental data may work in some environment and may not work on other. It's a good idea to use a 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 on scenarios. I hope these JUnit and testing best practices will help you to write better code.

Further Learning
Unit Testing In Java With JUnit
JUnit and Mockito Crash Course
Learn Unit Testing with Junit & Mockito in 30 Steps


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