mgamer
mgamer

Reputation: 14050

jUnit ignore @Test methods from base class

Let's say I have a test class called testFixtureA with several methods testA, testB, testC, etc, each with @Test annotation.

Let's now say I subclass testFixtureA into class called testFixtureAB and I don't overwrite anything. testFixtureAB is empty as for now.

When I run tests from testFixtureAB, methods testA, testB and testC are executed by test runner because test runner doesn't distinguish between test methods from class and baseclass.

How can I force test runner to leave out tests from baseclass?

Upvotes: 27

Views: 20036

Answers (11)

John Gilmer
John Gilmer

Reputation: 874

I ran into a similar issue where I had a generic abstract base class TestBase and 2 subclasses TestA, TestB that extended the base class. I wanted all tests from TestBase to run for TestA but to skip some for TestB. You can use the JUnit annotations Nested and Disabled to group tests in the base class into categories and then enable a full disable of that entire category of tests.

public class TestB extends TestBase {

  // disable entire suite of inherited tests
  // from the nested class declared on the parent
  @Nested
  @Disabled
  public class ComponentCTests {}

}

public abstract class TestBase {

  @Nested
  public class ComponentCTests {
     @Test
     public void testSomething() {
      // test something
      }
  }
}

Upvotes: 0

York
York

Reputation: 523

In Junit 5, you can make base class as abstract and extends it with a concrete class.

When you run the abstract in your IDE, your subclass will get executed instead.

Upvotes: 3

Ermal
Ermal

Reputation: 461

If for any reason you need two JUnit classes for same functionality, the best approach for me is:

  • put the common code in a parent class TestFixture with only constants and mocked services.
  • create two subclasses: TestFixtureA and TestFixtureB

This way you will not have duplicated code, nor double runs.

Upvotes: 0

Matthew Flynn
Matthew Flynn

Reputation: 2238

and I don't overwrite anything. testFixtureAB is empty as for now

There's your answer. If you want to not run testB from the main class, overrride it:

public class testFixtureAB extends testFixtureA {
   @Override
   public void testB() {}
}

Upvotes: 29

Mark Mosher
Mark Mosher

Reputation: 1

In the base test class' @Test methods:

assumeTrue(getClass().equals(BaseClassTest.class));

It will ignore those in the subclass tests but not completely leave them out.

Upvotes: 0

user1607938
user1607938

Reputation: 121

It's quite easy to achieve implementing some few classes:

  • Create your own TestRunner
  • Create an annotation like @IgnoreInheritedTests
  • Create a class that extends org.junit.runner.manipulation.Filter

On the filter class:

public class InheritedTestsFilter extends Filter {

    @Override
    public boolean shouldRun(Description description) {
        Class<?> clazz = description.getTestClass();
        String methodName = description.getMethodName();
        if (clazz.isAnnotationPresent(IgnoreInheritedTests.class)) {
            try {
                return clazz.getDeclaredMethod(methodName) != null;
            } catch (Exception e) {
                return false;
            }
        }
        return true;
    }

    @Override
    public String describe() {
        // TODO Auto-generated method stub
        return null;
    }

}

on your custom runner:

 /**
 * @param klass
 * @throws InitializationError
 * @since
 */
public CustomBaseRunner(Class<?> klass) throws InitializationError {
    super(klass);
    try {
        this.filter(new InheritedTestsFilter());
    } catch (NoTestsRemainException e) {
        throw new IllegalStateException("class should contain at least one runnable test", e);
    }
}

Upvotes: 10

martosoler
martosoler

Reputation: 433

What if you want to execute the same test for different configurations of the same test suite?

For example, let's say you have Class A with test1, test2 and test3 methods that hit an embedded database then you want to create separated "setUp" and "tearDown" for every embedded vendor (H2, HyperSQL, etc) but runs the same testing for each one.

I would like to extend a class that contain those test methods and configure it in a subclass. My problem is that the super class SHOULD NOT be considered as eligible for the test runner. The problem arises when the test runner executes the super class and given that don't found the corresponding setup and teardown methods, it crashs :(

Upvotes: 1

topchef
topchef

Reputation: 19783

I know, it's not the answer...

Consider the reason why you extend concrete test classes. You do duplicate test methods that way.

If you share code between tests then consider writing base test classes with helper and fixture setup methods or test helper class.

If for running tests then try organizing tests with suites and categories.

Upvotes: 1

Yishai
Yishai

Reputation: 91871

In the latest JUnit you can use the @Rule annotation on the subclass to inspect the test name and intercept the test run to ignore the test dynamically. But I would suggest that @Bozho's idea is the better one - the fact that you need to do this indicates a bigger problem that probably shows inheritance is not the right solution here.

Upvotes: 1

Bozho
Bozho

Reputation: 597046

Restructure your test classes.

  • If you don't want to use the tests from the baseclass, then don't extend it
  • If you need other functionality from the base class, split that class in two - the tests, and the other functionality

Upvotes: 24

dfa
dfa

Reputation: 116324

ignoring the whole base class:

@Ignore
class BaseClass {
   // ...
}

check out this example

Upvotes: 12

Related Questions