Reputation: 14050
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
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
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
Reputation: 461
If for any reason you need two JUnit classes for same functionality, the best approach for me is:
TestFixture
with only constants and mocked services.TestFixtureA
and TestFixtureB
This way you will not have duplicated code, nor double runs.
Upvotes: 0
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
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
Reputation: 121
It's quite easy to achieve implementing some few classes:
TestRunner
@IgnoreInheritedTests
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
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
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
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
Reputation: 597046
Restructure your test classes.
Upvotes: 24