Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to group/categorize large number of JUnit tests

Tags:

java

junit

In our project, we currently have a large number of (junit) tests that are split into three categories: unit, integration, wicket.

I now want to group these tests so I can run only one (or two) of those categories. The only thing I found are junit test suites and categories as described here: http://www.wakaleo.com/component/content/article/267

My problem is, I don't want to declare every single test in the Test Suits with @SuiteClasses.

Is there a way to add the suite classes with wildcards / patterns?

like image 867
maze2k Avatar asked Mar 01 '11 09:03

maze2k


People also ask

Is it possible to group the test cases in JUnit?

JUnit test suites help to grouping and executing tests in bulk. Executing tests separately for all test classes is not desired in most cases. Test suites help in achieving this grouping. In JUnit, test suites can be created and executed with these annotations.

Which annotation is used for grouping multiple tests for a method in JUnit?

The @Test annotation is used to identify the actual test case. This is required as JUnit allows multiple tests to be grouped under a single test class.

How do you organize unit tests in Java?

The easiest way to organize your tests is to place them directly alongside your production code, in the same package and source tree. If you do this, all the code you need to compile is in one directory structure, simplifying your build process.

Which supports grouping of test cases?

TestNG Groups allow you to perform groupings of different test methods. Grouping of test methods is required when you want to access the test methods of different classes.


3 Answers

Assuming my understanding of the question is correct, it actually can be done using JUnit. The code below was used with JUnit 4.11 and allowed us to split all tests into 2 categories: "uncategorized" and Integration.

IntegrationTestSuite.java

/**
 * A custom JUnit runner that executes all tests from the classpath that
 * match the <code>ca.vtesc.portfolio.*Test</code> pattern 
 * and marked with <code>@Category(IntegrationTestCategory.class)</code>
 * annotation. 
 */
@RunWith(Categories.class)
@IncludeCategory(IntegrationTestCategory.class)
@Suite.SuiteClasses( { IntegrationTests.class })
public class IntegrationTestSuite {
}

@RunWith(ClasspathSuite.class)
@ClasspathSuite.ClassnameFilters({ "ca.vtesc.portfolio.*Test" })
class IntegrationTests {
}

UnitTestSuite.java

/**
  * A custom JUnit runner that executes all tests from the classpath that match
  * <code>ca.vtesc.portfolio.*Test</code> pattern.
  * <p>
  * Classes and methods that are annotated with the
  * <code>@Category(IntegrationTestCategory.class)</code> category are 
  * <strong>excluded</strong>.
  */

@RunWith(Categories.class)
@ExcludeCategory(IntegrationTestCategory.class)
@Suite.SuiteClasses( { UnitTests.class })
public class UnitTestSuite {
}

@RunWith(ClasspathSuite.class)
@ClasspathSuite.ClassnameFilters({ "ca.vtesc.portfolio.*Test" })
class UnitTests {
}

IntegrationTestCategory.java

/**
 * A marker interface for running integration tests.
 */
public interface IntegrationTestCategory {
}

The first sample test below is not annotated with any category so all its test methods will be included when running the UnitTestSuite and excluded when running IntegrationTestSuite.

public class OptionsServiceImplTest {
    @Test
    public void testOptionAssignment() {
        // actual test code
    }
}

Next sample is marked as Integration test on the class level which means both its test methods will be excluded when running the UnitTestSuite and included into IntegrationTestSuite:

@Category(IntegrationTestCategory.class)
public class PortfolioServiceImplTest {
    @Test
    public void testTransfer() {
        // actual test code
    }
    @Test
    public void testQuote() {
    }
}

And the third sample demos a test class with one method not annotated and the other marked with the Integration category.

public class MarginServiceImplTest {
    @Test
    public void testPayment() {
    }
    @Test
    @Category(IntegrationTestCategory.class)
    public void testCall() {
    }
}
like image 102
Vitali Tchalov Avatar answered Nov 15 '22 16:11

Vitali Tchalov


Try using ClasspathSuite

I also had the same problem where I had more then 5500 jUnit tests. I categorised then into 3 groups and created 3 suites using the above jUnit extension. Its great.

like image 30
Rikash Avatar answered Nov 15 '22 17:11

Rikash


You could put them in different packages. Most IDEs have a way to run all the tests in a given package. It's also pretty simple to find all the test classes in a package with a shell script for running tests as part of a build or whatever. I don't know if there's a way to do it with ant, but I would imagine so.

TestNG lets you tag tests as being in particular groups, then run those groups. That sound like exactly what you want, apart from the fact that it's not JUnit!

You could abuse JUnit's assumption mechanism to do what you want: have a system property for each group of tests, and then start each test by assuming that the appropriate property is set. Running all tests will run everything, but everything you don't want will be ignored.

like image 44
Tom Anderson Avatar answered Nov 15 '22 15:11

Tom Anderson