Junit 4 Test Suites

JUnit 4 Test Suites

import org.junit.runners.Suite;
import org.junit.runner.RunWith;

@RunWith(Suite.class)
@Suite.SuiteClasses({TestClass1.class, TestClass2.class})
public class TestSuite {
//nothing
}

TestSuite Setup in jUnit 4

Here is what I have and it runs just fine.

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({ TestSuite1.class, TestSuite2.class })
public class CompleteTestSuite {

@BeforeClass
public static void setUpClass() {
System.out.println("Master setup");

}

@AfterClass public static void tearDownClass() {
System.out.println("Master tearDown");
}

}

Here is my test suite 1 (do the same for test suite 2).

import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(value = Suite.class)
@SuiteClasses(value = { TestCase1.class })
public class TestSuite1 {}

And here is my test class. Create both testcase1 and testcase2.

import static org.junit.Assert.assertEquals;

import org.junit.BeforeClass;
import org.junit.Test;

public class TestCase1 {

@BeforeClass
public static void setUpClass() {
System.out.println("TestCase1 setup");
}

@Test
public void test1() {
assertEquals(2 , 2);
}
}

you should have 5 classes
completesuite
suite1
suite2
test1
test2

and make sure you have Junit in your build path. This should run!

Here is the output

Master setup
TestCase1 setup
Master tearDown

How do you create nested TestSuites in JUnit 4.x?

The first problem is that Test3 uses @RunWith(Suite.class), but doesn't contain @Suite.SuiteClasses({Test3.class, .....}). This produces an IntializationError: class 'Test3' must have a SuiteClasses annotation. Since you aren't intending there to be any classes underneath Test3, this annotation should be removed.

The second problem of Exception: No runnable methods is almost always due to forgetting to add @Test to a test. You didn't put the tests in your sample, so I don't know if that's actually the case or not, but it's the most likely cause.

The following is a working version of your code that allows tests to be run from any class:

Test1.java

import org.junit.runner.*;
import org.junit.runners.*;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({Test2.class})
public class Test1 {

}

Test2.java

import org.junit.runner.*;
import org.junit.runners.*;
import org.junit.runners.Suite.SuiteClasses;

@RunWith(Suite.class)
@SuiteClasses({Test3.class})
public class Test2 {

}

Test3.java

import static org.junit.Assert.*;

import org.junit.*;

public class Test3 {

@Test
public void testTrue(){
assertTrue(true);
}
}

As for whether or not there is a better way than to organize things, I guess it just depends on how you decide to create the classes. Since you can add suites to suites, as this demonstrates, you can create smaller chunks of suites that depend on everything, like a tree. For instance, what I generally do is:

AllTestSuite
TextParsingSuite
GuiSuite
SwingSuite
JavaFXSuite
FileIOSuite

A test is added to the most relevant suite. In the end, I don't think I have any suite with more than 10 test classes/suites or so. If I do, it's time to make a new sub-suite. In other words, there is no "huge list somewhere", just a lot of smaller lists that are combined together into another list in order to effectively make one big list.

I suppose you could use some tool to dynamically find all of the Java classes containing tests, but JUnit itself doesn't support this behavior (it only runs the tests you tell it to, which I personally think is a good thing).

How to get a collection of tests in a JUnit 4 test suite

After a bit of experimentation, I discovered the following solution:

SuiteClasses suiteClassesAnnotation = AllTests.class.getAnnotation(SuiteClasses.class);
if (suiteClassesAnnotation == null)
throw new NullPointerException("This class isn't annotated with @SuiteClasses");
Class<?>[] classesInSuite = suiteClassesAnnotation.value();

Basically, it gets the classes the same way that JUnit itself gets them: by looking into the annotation and determining which values are included within it.

The category solution provided by dkatzel is also a good option if you're ultimately wanting to filter these classes, but if you need a list of classes in a suite for some other purpose such as code analysis, this is the simplest and most direct way to do it.

How can I build a configurable JUnit4 test suite?

In Junit you can use categories. For example this suite will execute al test from the AllTestSuite annotated as integration:

import org.junit.experimental.categories.Categories;
import org.junit.experimental.categories.Categories.IncludeCategory;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Categories.class)
@IncludeCategory(Integration.class)
@Suite.SuiteClasses ({AllTestsSuite.class} )
public class IntegrationTestSuite {}

You can also use @ExcludeCategory. This is usefull to remove slow tests. Categories classes are just plain old Java classes or interfaces. For example:

public interface Integration{}
public interface Performance{}
public interface Slow{}
public interface Database{}

You only need to anotate your tests acordingly:

@Category(Integration.class)
public class MyTest{

@Test
public void myTest__expectedResults(){
[...]

One test might have more than one category like this:

   @Category({Integration.class,Database.class})  
public class MyDAOTest{

For simplicity I usually create a Suite with all classes in the test folder using google toolbox:

import org.junit.runner.RunWith;

import com.googlecode.junittoolbox.ParallelSuite;
import com.googlecode.junittoolbox.SuiteClasses;

@RunWith(ParallelSuite.class)
@SuiteClasses({"**/**.class", //All classes
enter code here "!**/**Suite.class" }) //Excepts suites
public class AllTestsSuite {}

This works incluiding in AllTestSuite all classes in the same folder and subfolders even if they don't have the _Test sufix. But won't be able to see test that are not in the same folder or subfolders. junit-toolbox is available in Maven with:

<dependency>
<groupId>com.googlecode.junit-toolbox</groupId>
<artifactId>junit-toolbox</artifactId>
<version>2.2</version>
</dependency>

Now you only need to execute the Suite that suits your needs :)

UPDATE: In Spring there is the @IfProfileValue annotation that allows you to execute test conditionally like:

@IfProfileValue(name="test-groups", values={"unit-tests", "integration-tests"})
@Test
public void testProcessWhichRunsForUnitOrIntegrationTestGroups() {

For more information see Spring JUnit Testing Annotations

Running TestSuite in JUnit4 and Maven

I would assume that your test classes are not named based on the naming convention for test in relationship with maven-surefire-plugin

includes>
<include>**/*Test*.java</include>
<include>**/*Test.java</include>
<include>**/*TestCase.java</include>
</includes>

Apart from that you shouldn't use TestSuites, cause surefire-plugin will handle that already. So usually there is no need to suites to be defined separately.



Related Topics



Leave a reply



Submit