TestNG Showcase – Unit Test Dependencies

A nice feature of TestNG that JUnit 4 is missing is the fact that it’s possible to specify unit tests that rely on other unit tests to complete first.

An example:

package com.dimitrisli.testng.dependents;

import org.testng.annotations.Test;

public class DependentMethodTesting {

	@Test(dependsOnMethods={"method1"})
	public void method2(){
		System.out.println("hi I am method2 and I depend on method1");
	}
	
	@Test
	public void method1(){
		System.out.println("hi I am method1");
	}
}

that produces the output:

hi I am method1
hi I am method2 and I depend on method1

The code can be found in this Github repository.

Advertisements

TestNG Showcase – Parameterized Testing

The parameterized functionality is very helpful when it comes to group repetitive code for different input data.

We can do the following if we wanted to inject a parameter from a config file:

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="My parameterized test suite">
  <test name="parameterised injection testing">
 
    <parameter name="i" value="13"/> 	
 
    <classes>
       <class name="com.dimitrisli.testng.parameterized.ParameterizedInjectionTest" />
    </classes>
  </test>
</suite>

to a unit test:

package com.dimitrisli.testng.parameterized;

import org.testng.annotations.Parameters;
import org.testng.annotations.Test;

public class ParameterizedInjectionTest {

	@Test
	@Parameters(value="i")
	public void method1(int i){
		System.out.println("inside method1() of parameterized example injected i = "+i);
	}
}

@DataProvider is similar to JUnit 4’s @Parameters to inject values en masses, a trivial example would look like so:

package com.dimitrisli.testng.parameterized;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class DataProviderTesting {

	@DataProvider(name="dataProviderMethod")
	public Object[][] parameterMethod(){
		return new Object[][]{{"one",1},{"two",2}};
	}
	
	@Test(dataProvider="dataProviderMethod")
	public void testMethod(String str, int val){
		System.out.println("str="+str+", val="+val);
	}
}

A nice variation is to pass proper Java beans around:

package com.dimitrisli.testng.parameterized;

import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class AdvancedParameterizedTesting {

	public static class Bean{
		private String val;
		private int i;
		
		public Bean(String val, int i){
			this.val=val;
			this.i=i;
		}
		
		public String getStr(){
			return this.val;
		}
		
		public int getInt(){
			return this.i;
		}
		
	}
	
	@DataProvider(name = "advancedParameterizedMethod")
	public Object[][] advancedParameterizedMethod(){
		return new Object[][]{{new Bean("hi I am the bean",111)}};
	}
	
	@Test(dataProvider="advancedParameterizedMethod")
	public void testMethod(Bean myBean){
		System.out.println(myBean.getStr()+" "+myBean.getInt());
	}
}

The source code could be found in this Github repository.

TestNG Showcase – Groups

Groups is a very nice versatile functionality that JUnit 4 is still missing. TestNG gives you the flexibility through specified groups to gather up and run buckets of unit tests grouped in their own separate scenarios. Someone could group for instance integration tests, database related tests, framework tests, the possibilities are endless.

In our example we would need a TestNG XML config file first, making all the necessary introductions:

<!DOCTYPE suite SYSTEM "http://beust.com/testng/testng-1.0.dtd" >
<suite name="Groups Suite">
  <test name="groups suite test">
  	<groups>
      <run>
        <include name="group2"/>
        <include name="group3"/>
      </run>
    </groups>
    <classes>
       <class name="com.dimitrisli.testng.groups.TestNGGroupsTesting" />
    </classes>
  </test>
</suite>

The referenced TestNG Class looks like this:

package com.dimitrisli.testng.groups;

import org.testng.annotations.Test;

public class TestNGGroupsTesting {

	@Test(groups="group3")
	public void method1(){
		System.out.println("inside method1 of group 3");
	}
	
	@Test(groups="group1")
	public void method2(){
		System.out.println("inside method2 of group 1");
	}
	
	@Test(groups="group2")
	public void method3(){
		System.out.println("inside method3 of group 2");
	}
	
	@Test(groups="group2")
	public void method4(){
		System.out.println("inside method4 of group 2");
	}
	
	@Test(groups="group1")
	public void method5(){
		System.out.println("inside method5 of group 1");
	}
}

Running just that class as a TestNG test would yield:

inside method1 of group 3
inside method2 of group 1
inside method3 of group 2
inside method4 of group 2
inside method5 of group 1
PASSED: method1
PASSED: method2
PASSED: method3
PASSED: method4
PASSED: method5

which are all the unit tests in order of appearance. This is because we didn’t take yet the xml config file into consideration. Since we are using Maven as a building tool specifying the config file takes place in the maven Surefire TestNG-enabled plugin that looks like this:

<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-surefire-plugin</artifactId>
  			<version>2.11</version>
  			<configuration>
  				<suiteXmlFiles>
  					
  					<suiteXmlFile>testngGroups.xml</suiteXmlFile>
  					
  				</suiteXmlFiles>
  			</configuration>
  		</plugin>

We’ve just shaped the testing phase of Maven to consider the TestNG groups in this special manner. Running mvn package produces the following among the output:

inside method1 of group 3
inside method3 of group 2
inside method4 of group 2

which is the grouping in the order we desired and have specified in the config file.

An interesting alternative or override is the Surefire plugins configuration to assist group references within the POM:

<plugin>
  			<groupId>org.apache.maven.plugins</groupId>
  			<artifactId>maven-surefire-plugin</artifactId>
  			<version>2.11</version>
  			<configuration>
  				<suiteXmlFiles>
  					
  					<suiteXmlFile>testngGroups.xml</suiteXmlFile>
  					
  				</suiteXmlFiles>
<groups>group2</groups>
  			</configuration>
  		</plugin>

If we do so, then we override the grouping specified in the config file having as output this time:

inside method3 of group 2
inside method4 of group 2

You can find this code in this Github repository.

JIT compiler log JVM option

If you want to see the log the JIT compiler is producing when running java and starting up the JVM in either client or server mode, you would need the -XX:+LogCompilation JVM flag option. In order to pass this flag we also need -XX:+UnlockDiagnosticVMOptions as well as -XX:LogFile= to store the XML log output that is produced.

In short for c1 JIT compiler or in other words JVM in client mode:

java -d32 -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:LogFile=output.xml Main

less ./output.xml | grep C1

for c2 JIT compiler or in other words JVM in server mode (Mac OS X JVM default mode):

java -XX:+UnlockDiagnosticVMOptions -XX:+LogCompilation -XX:LogFile=output.xml Main

less ./output.xml | grep C2

For further reading: LogCompilation Overview

Spring Maven integration

Here is the absolute minimal code to kickstart a Spring-enabled project using Maven.

Since it is impossible not to use the ApplicationContext interface in our Spring example we would need to include the spring-context Maven dependency and Maven should take it on from there bringing all the dependent jars based on the dependency hierarchy. In that case the POM should look like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dimitrisli</groupId>
  <artifactId>helloSpring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
    	<version>3.0.6.RELEASE</version>
    </dependency>
  </dependencies>
</project>

Based on the dependency hierarchy, spring-context is depending on spring-aop, spring-beans, spring-core, spring-expression,and spring-asm. Spring-core is also depending on commons-logging which constitutes our absolute minimal jars we need to have:

  • spring-core
  • spring-asm
  • commons-logging
  • spring-context
  • spring-aop
  • spring-beans
  • spring-expression

The power of Maven dealing with the dependency hierarchy tree behind the scenes saves us from the hustle of dealing/defining explicitly these jars but in case we wanted to explicitly include all the spring related jars our POM would look like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.dimitrisli</groupId>
  <artifactId>helloSpring</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <properties>
  	<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</artifactId>
      <version>3.0.6.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-context</artifactId>
    	<version>3.0.6.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-expression</artifactId>
    	<version>3.0.6.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-aop</artifactId>
    	<version>3.0.6.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-asm</artifactId>
    	<version>3.0.6.RELEASE</version>
    </dependency>
    <dependency>
    	<groupId>org.springframework</groupId>
    	<artifactId>spring-beans</artifactId>
    	<version>3.0.6.RELEASE</version>
    </dependency>
  </dependencies>
</project>

We define the spring-beans.xml configuration file under /src/main/rousources and it looks like so:

<!--?xml version="1.0" encoding="UTF-8"?-->
<beans	xmlns="http://www.springframework.org/schema/beans" 
		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
		xsi:schemaLocation="http://www.springframework.org/schema/beans 
							http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
		
<bean id="myBeanTuple" class="com.dimitrisli.springFirstExample.MyBean" />

</beans>

This file creates for us a 1-to-1 mapping between the class MyBean (full namespace needed here) and the Spring bean called myBeanTuple.

MyBean is a trivial test class (not even a java bean) with its sole purpose in life to System.out.print a message within its only one method:

package com.dimitrisli.springFirstExample;

public class MyBean {

	public void printMyBean(){
		System.out.println("Inside My Bean");
	}
}

Everything is linked together in our BeanContainer that is loading the spring config file during runtime creating our application context and then claiming the bean from the context based on the name before calling the sole method to print our test string:

package com.dimitrisli.springFirstExample;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;


public class BeanContainer {

	public static void main(String[] args) {
		ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/resources/spring-beans.xml");
		MyBean myBean = (MyBean) context.getBean("myBeanTuple");
		myBean.printMyBean();
	}
}

You can find the code in this github repository