Thursday, October 16, 2014

TDD : Test Data Preparation and Maintenance

While writing a test, we generally struggle with generating the test 
data for our test. A  major portion of our test code get covered with 
code for generating test data and sometimes those test data became 
very difficult to manage. This article is about how we can resolve 
such issues with a different approach.

For example, we want to test the save method of a java class EmployeeDAO  which takes an Employee object as parameter.

 public class EmployeeDAO {  
    boolean save(Employee employee) {  
    ....  
  }  
 }  

And Employee class has the following structure.

public class Employee{

  private String firstName;
  private String lastName;
  private int age;
  private String email;
  private Address address; 

  // getters & setters
}

public class Address {

  private String line1;
  private String line2;
  private String line3;
  private String line4;

  // getters & setters
}

So in our test code to test save method of EmployeeDAO, we need to build an Employee object (as test data) as below to pass it as parameter to the save method..

public EmployeeDAOTest {
  @Test  
  public void saveTest(){
    // Generate Test Data
    Employee employee = new Employee();
    employee.setFirstName("testFirstName");
    employee.setLastName("testLastName");
    employee.setAge(19);
    employee.setEmail("test@mail.com");
   
    Address address = new Address();
    address,setLine1("testLine1");
    address.setLine2("testLine2");
    address.setLine3("testLine3") ;
    address.setLine4("testLine4");

    employee.setAddress(address);

    // Create the object of class under test and invoke
    EmployeeDAO employeeDAO = new EMployeeDAO();
    boolean result = employeeDAO.save(employee); 

    // Code To Assert Result 

  }
}

Here we had to write around 11 lines of code in our test method to generate the test data Employee, which is more than 90% of the test code. And it will be worse when the test data is more complex. And it also makes the maintenance and readability of the test code and test data difficult.                    

So following is an example of  how we can generate and maintain test data in an easier way.

Step-1 : Instead of keeping the test data in our test code lets keep it outside in a file in json format.

employee.json

{
  "firstName" : "TestFirstName",
  "lastName" : "TestLastName",
  "age" : 19,
  "email" : "test@mail.com",
  "address" : {
      "line1" : "TestLine1",
      "line2" : "TestLine2",
      "line3" :  "TestLine3",
      "line4" : "TestLine4"
  }
}

Step 2 : Add any JSON API to your class path to create java object from JSON content. Here I used jackson.

    com.fasterxml.jackson.core
    jackson-databind
    2.3.2
    test

Step 3 : In your test method read the json file to generate test object using the API. 

public EmployeeDAOTest {
  @Test  
  public void saveTest(){
    // Generate Test Data
    Employee employee = new ObjectMapper()
       .readValue(getClass()
       .getResourceAsStream("/employee.json"), Employee.class);

    // Create the object of class under test and invoke
    EmployeeDAO employeeDAO = new EMployeeDAO();
    boolean result = employeeDAO.save(employee); 

    // Code To Assert Result 

  }
}

So with the second approach , just 1 line of code is required to generate the test object, instead of 11 lines of code, which make my test code cleaner and smaller. Cleaner and smaller code results in making the test code easy to read, understand and maintain. And keeping test data in a file in json format makes easier to read, visualize and maintain. 

Happy Testing !!!