Thursday, April 17, 2014

JACOCO as a coverage tool for Unit testing, Integration testing and Functional testing

JACOCO as a coverage tool for Unit testing, Integration testing and Functional testing
This article explains how to generate coverage reports for unit testing,integration testing and functional testing using JACOCO.
Instrumentation
Ability to alter byte code through classloaders for the purpose of gathering data such as profiling, coverage etc. is known as instrumentation. Instrumentation was introduced in 1.5.
JACOCO 
JACOCO is one of the most popular JAVA Coverage tool used in the industry. Using on the fly instrumentation, JACOCO will modify the byte code by inserting its hooks to record the coverage information making the integration with build tools, server simple. Through this feature, application code remains clean. Thanks to the instrumentation feature added in JDK 1.5!!!
 Technologies used
  1. Java 1.7
  2. Jboss AS 7.2
  3. Maven
  4. Spring 4.0.3
  5. JACOCO  0.6.4 
Overview of Classes
UserDao.java A simple DAO to save,read users from DB
UserService.java A simple service with an handle to DAO
UserController.java A simple REST interface

and the flow is given below


 Below is the code snippet from UserDao.java to save users

 @Override
    public void saveUsers(final List users) {
        getJdbcTemplate().batchUpdate(SQLConstants.SAVE_USERS.getValueAsString(), new BatchPreparedStatementSetter() {

            @Override
            public void setValues(PreparedStatement ps, int i) throws SQLException {
                IUser user = users.get(i);
                ps.setString(1, user.getUserName());
                ps.setString(2, user.getPassword());
                ps.setBoolean(3, user.isAcceptTerms());
                ps.setString(4, user.getFirstName());
                ps.setString(5, user.getLastName());
                ps.setString(6, user.getMiddleName());
                if(user.getRegisteredOn() == null){
                    user.setRegisteredOn(Calendar.getInstance());
                }
                ps.setTimestamp(7, new Timestamp(user.getRegisteredOn().getTimeInMillis()));
                ps.setInt(8, user.getAge());
            }

            @Override
            public int getBatchSize() {
                return users.size();
            }
        });
    }

Below the code snippet from UserDaoTest.java

 @Test
    @Rollback(true)
    public void testSaveUsers(){
       IUser user = new User();
       user.setUserName("ïtsvenkis");
       user.setPassword("itsvenkis");
       user.setAge(28);
       user.setRegisteredOn(Calendar.getInstance());
       user.setAcceptTerms(true);
       user.setFirstName("Venkat");
       user.setLastName("Nanda");
       List users = new ArrayList();
       users.add(user);
       getUserDao().saveUsers(users);
    }

Specify JACOCO Maven plugin in pom.xml 


                org.jacoco
                jacoco-maven-plugin
                0.7.0.201403182114
                
                    ${basedir}/target/coverage-reports/jacoco.exec
                    ${basedir}/target/coverage-reports/jacoco.exec
                    
                
                
                    
                        jacoco-initialize
                        
                            prepare-agent
                        
                    
                    
                        jacoco-site
                        package
                        
                            report
                        
                    
                
            
            

 
Now running the maven build with install and package will generate a nice coverage report as shown below for all the unit tests.
 


While this looks simple, it gets little tricky when we have a bunch of tests cases to verify the functionality of an application. In real world one may have their application deployed on a server and  functional test suites will run against the server. JACOCO agent can be added as an JVM option in the application server and on the fly instrumentation will kick in enabling coverage information. All the coverage information will be collected in exec file and reports can be generated from this file.


 

set "JAVA_OPTS=%JAVA_OPTS% -javaagent:c:\apps\jacoco\lib\jacocoagent.jar=destfile=c:\apps\reports\jacoco.exec,append=true,output=file"

Start the server and execute the test suites or execute some manual requests and stop the server once all the testing is done. JACOCO will dump the coverage information on JVM exit.
Below is the coverage report generated

Source Code github . Downlaod JACOCO-COVERAGE Project.