Junit best practices
In any SDLC (Software Development Life Cycle) testing plays a major role to make the end result defect free. Defect free is bit harsh to say from customers point of view so lets write it as end result with less defects. Not every software product that comes out today. is defect free and to over come this scenario test driven environment becomes inevitable. Unit testing (testing individual units of code) is very important irrespective of the programming language the application is being developed. When it comes to java,Junit is the widely used open source unit testing framework.

Junit stands out from other testing frameworks because of its outstanding features like facility to regression testing, easy integration with ANT, part of XUnit testing family and ofcourse for a cleaner and a better way of programmatically testing. But out of my personal experience most of the time Junit coding has been done without any standards. So I thought out penning down some standards which I am familiar of,
Write Simple Test cases:
Test cases must be simple. Validating multiple behaviors of a procedure must be avoided and those test cases must be divided appropriately. Don’t write test cases for testing different flows in the same Test Class. Also keep the class logically simple. If the test case has got dependencies and database calls then handle it accordingly using Mock objects or by other best known methodologies.
Use appropriate naming conventions:
Naming conventions must be meaningful so that it will help in maintainability.
For instance, the test method should not be named like
public void testMethod1() { // The name of this method doesn't tell what this test method is all about. }
instead it can be named
public void testAddForNegativeNumbers() { // An example for a meaningful name. }
Use comments wherever necessary and in complex testing scenarios.
Write Independent Unit Test cases:
If you want to test a method for multiple behaviors then one test method must be written for each scenario. This will make the unit test case focus on the particular behavior of the method with great clarity and maintainability.
Please see the self-explanatory following example in testing a method called divide()
public void testForNegativeValues() { // This method is used to test for negative values scenario. } public void testForDivideByZero() { // The name very well explains what is this test all about. }
All business methods must have separate test cases. See the above example instead of grouping the test scenarios I have divided and written it as two methods. Sounds meaningful doesn’t it?
Say No Java code:
No unit test case must not contain java conditional expressions to test some scenarios. Use assertion to handle the same.
public void testSomeMethod() { Student oStudent = obj.someMethod(); if(oStudent!=null) assertEquals("Sara", oStudent.getName()); }
The above one is a bad example and it must be rewritten as shown below,
public void testSomeMethod() { Student oStudent = obj.someMethod(); assertNotNull(oStudent); assertEquals("Sara", oStudent.getName()); //One can even divide the above two assertions into two. }
No java code must be written involving decisions.
Handling Assertions:
Assertions must be handled properly. Try to use one assertion per unit test case i.e one assertion per method to make your test cases extremely scalable and to make sure that each and every failure scenario has been tested. This may not be applicable for all scenarios but atleast it must be grouped accordingly.
Try to use constants in assertions,
public void testCalculateAge() { int age = obj.calculateAge(dob); assertEquals(age, calculateAge(dob)); // bad practice assertEquals(age, 25); // Best practice. Keep it simple }
Mock Objects:
In corporate test environments while testing business methods we can often encounter with database calls or any external service calls. Sometimes I can have seen people calling them as road blocks for testing. Use mock objects to handle such scenarios. Read more about Mock Objects and try to implement.
Exception Handling:
I have seen people for skipping exception handling scenarios while writing Junit test case. These scenarios can be handled either by using try-catch statements or by using Junit 4 annotations. I will try to give an example her for the former case and for later scenario refer it by yourselves in Junit 4 documentation.
try { String userId = "fake123"; Privilege oPrivilege = obj.getUserPrivileges(userId); fail("Test Failed! Exception not thrown"); // Exception must be thrown for this fake id which doesnt exist } catch (InvalidUserException iuEx) { // Pass scenario. Exception expected in this case. }
Make Re-usable Test data:
Write test cases scalable by keeping Test data reusable and don’t hard code or bind it up with test cases unless required. Try to have a configurable test data.
Junit test coverage:
We never know whether our test cases are extensive and all the business scenarios have been covered or not. Try to use code coverage frameworks like Cobertura along with ANT to make sure that your test cases are really good. I will try to write about Cobertura sometime later.

Junit test report:
Always try to generate Junit report for all the test cases you run against your business classes. These reports will be helpful for tracking any failure in the future and along with the code coverage report one can really convince the customer with the certainty of the application.
Related posts:












Pingback by Unit Test Best Practice: One Assert Per Test Case — January 12, 2011 @ 2:34 am