Java – How to disable entire tests (including inherited methods) in TestNG

How to disable entire tests (including inherited methods) in TestNG… here is a solution to the problem.

How to disable entire tests (including inherited methods) in TestNG

I’m using the TestNG framework, and many test classes extend the Base abstract Test to provide some additional information.

I want to set @Test (enabled = false) on the entire test class, which is problematic in TestNG because any @Test comment on the method overwrites the first. This means that all methods will still run even if the class is disabled.

I found a workaround provided by the framework author in the pull request #816 – Add listener if defined class has @Test (enabled = false) , modify the @Test comment on the method:

public class TestClassDisabler implements IAnnotationTransformer {

@Override
  public void transform(ITestAnnotation annotation, Class testClass, Constructor testConstructor,
                        Method testMethod) {
    if (testMethod != null) {
      Test test = testMethod.getDeclaringClass().getAnnotation(Test.class);
      if (test != null && !test.enabled()) {
        annotation.setEnabled(false);
      }
    }
  }
}

It’s like a charm, but only for tests that don’t use inheritance. For this case, testMethod.getDeclaringClass() from the listener returns the original class from which the method was declared, not the class that started the object’s instance of the method.

@Test(enabled = false)
class SpecificTest extends BaseTest {

@Test
    public void testSomething() {}
}

abstract class BaseTest {

@Test
    public void veryGenericTest() {}
}

For this example, only testSomething is disabled and veryGenericTest still runs.

Solution

IAnnotationTransformer is not a good choice here. There is no easy way to get the original instance of the calling method, just based on the Method interface. We can only get the base class where the method is declared.

Other solutions are used with IMethodInterceptor, which allows methods to be filtered out and provides access to test class instances before the test suite starts.

public class TestMethodsDisabler implements IMethodInterceptor {

@Override
    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
        List<IMethodInstance> testsToRun = new ArrayList<>();

for (IMethodInstance method : methods) {
            Test testClass = method.getInstance()
                .getClass()
                .getAnnotation(Test.class);

if (testClass == null || testClass.enabled()) {
                testsToRun.add(method);
            }
        }

return testsToRun;
    }
}

In this way, when we set the @Test(enabled = false) annotation on the class, both standard and inherited methods are disabled.

You need to use this interceptor to create a test suite in testng.xml:

<suite name="ListenersSuite" parallel="false">
    <listeners>
        <listener class-name="your.package.support.TestMethodsDisabler"/>
    </listeners>

<test name="all-test" preserve-order="true" verbose="2">
        <packages>
            <package name="your.package.tests.*"/>
        </packages>
    </test>
</suite>

References

Related Problems and Solutions