Archiv für den Monat: Mai 2012

Enhance JUnit 4 – grouping tests

As mentioned in my initial blog postsJUnit has some disadvantages compared to TestNG. In the previous blog post I introduced parametrized test method. In this post I am going to describe how to introduce grouping of tests.

In my current project we have several different kinds of tests. There are unit tests, database, component, and user interface tests. Every time somebody makes changes to SCM the unit test will be executed. Component, database and user interface tests will be performed during the nightly build. So, how to do this with JUnit?

One way would be to organize the tests in test suites but that is very time-consuming and error prone. Another way would be to organize the tests by using a prefix or a postfix for the test class names. In TestNG it’s just an attribute of the annotation @Test. You can add a whole class or each method to one or more groups of tests.

I found the solution to this problem in the German magazine Javamagazin issue November 2011. There was an article about the tool or framework PatternTesting. With this framework it is possible to group JUnit tests by activating or deactivating tests using properties.

So how does it work? TestPattern provides two possible solutions. Both use annotations.

1. You can specify in which case the test should be skipped or
2. you can specify in which case the test should be executed

I start with @SkipTestOn. One attribute of this annotation is called “property”. Here you specify the name or names of the properties that should make the test skip as a String array. If more than one property is specified then only one of the property need to exist to skip the test.

@RunWith(SmokeRunner.class)
public class PatternTestingSampleTest {

	@Test
	@SkipTestOn(property = { "UNITTEST", "COMPONENT" })
	public void testTimeConsumingAction() {
		// This test will not run if either the property
		// UNITTEST or COMPONENT is set
	}
}

At the annotation @RunTestOn you also specify the properties as a String array in the same way as in @SkipTestOn. The important difference is that if you specify more than one property all properties need to be set to run the annotated test.
So in @SkipTestOn the properties are connect with OR and in @RunTestOn with AND.

@RunWith(SmokeRunner.class)
public class PatternTestingSampleTest {

	@Test
	@RunTestOn(property = "GUI")
	public void testGUI() {
		// This test will only run if the property GUI is set
	}
}

The properties need to be set using the –D option of the JVM. To activate the attribute with the value “UNITTEST” you have to set the property using –DUNITTEST in the command line.

Another important step to do is to use the SmokeRunner or the ParallelRunner class as JUnit runner class. This is done using the annotation @RunWith(SmokeRunner.class) or @RunWith(ParallelRunner.class) at the top of the class definition. Both classes are shipped with the framework.

There are also other attributes for @RunTestOn and @SkipTestOn like:

  • „host“ for IP addresses
  • „javaVendor“ to specify Apple, Oracle, IBM or other
  • „javaVersion“
  • „osArch“ for operating system architecture
  • „osName“ for operating system name like Windows or Linux
  • „osVersion“
  • „user“ to specify user names

All these attributes are very well documented with sample values.

In conclusion, this framework provides a nice interface to enhance JUnit 4 to group tests. Unfortunately, if you want to use this framework together with ParamUnittest framework from the previous blog post, that is not possible because both have their own JUnit runner class and only one can be specified. You have to make a decision which framework you want to use.