Joshua Fox
Joshua Fox

Reputation: 19695

How do I disable a test from running in a subclass in TestNG?

(Update: After I reported this, the TestNG team confirmed the bug.)

Normally, ignoring a class can be done with @Ignore or enabled=false

This does not work on a subclass where test methods are defined in its superclass (and where the subclass defines its specific functionality in hook methods). See ChildClassTest below.

Note that @Ignore is specific to JUnit whereas TestNG uses enabled.

Base class

import org.testng.annotations.Test;

public class ParentClassTest {
    @Test
    public void test1() {
        hook();
    }

    protected void hook() {};
}

Child class

import org.testng.Reporter;
import org.testng.annotations.Ignore;

@Ignore
public class ChildClassTest extends ParentClassTest {
    @Override
    protected void hook() {
        Reporter.log("ChildClassTest#hook()");
    }
}

Upvotes: 3

Views: 968

Answers (1)

Morfic
Morfic

Reputation: 15528

Been doing some brainstorming out of curiosity, and came up with the workarounds below tested with v6.14.2. I personally prefer the first one, being cleaner, more elegant, flexible and easier to maintain and extend.

context

import org.testng.annotations.Test;

import static org.testng.Assert.assertTrue;

public class MyTest {
    @Test
    public void shouldRun() {
        assertTrue(true);
    }

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

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

1) Using listeners - create a TestListenerAdapter & annotation to skip methods with certain names: flexible, clear, easy to reuse and identify for removal. The only downside is that you have to pay attention to method names for typos.

Annotation

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SkipMethods {
    String[] value() default {};
}

TestListenerAdapter

import org.testng.ITestResult;
import org.testng.SkipException;
import org.testng.TestListenerAdapter;

public class TestSkippingListener extends TestListenerAdapter {
    @Override
    public void onTestStart(ITestResult result) {
        // get the skip annotation
        SkipMethods skipAnnotation = result.getMethod().getInstance().getClass().getAnnotation(SkipMethods.class);

        // if the annotation exists
        if (skipAnnotation != null) {
            for (String skippableMethod : skipAnnotation.value()) {

                // and defines the current method as skippable
                if (skippableMethod.equals(result.getMethod().getMethodName())) {

                    // skip it
                    throw new SkipException("Method [" + skippableMethod + "] marked for skipping");
                }
            }
        }
    }
}

Test Subclass

import org.testng.annotations.Listeners;

// use listener
@Listeners(TestSkippingListener.class)

// define what methods to skip
@SkipMethods({"shouldNotRun", "shouldNotRunEither"})
public class MyTestSkippingInheritedMethods extends MyTest {

}

Result

skip by listener


2) Override methods from superclass and throw SkipException: pretty clear, no possibility of typo, but not reusable, not easily maintainable & introduces useless code:

import org.testng.SkipException;

public class MyTestSkippingInheritedMethods extends MyTest {

    @Override
    public void shouldNotRun() {
        throw new SkipException("Skipped");
    }

    @Override
    public void shouldNotRunEither() {
        throw new SkipException("Skipped");
    }
}

Result

skip by override

Upvotes: 2

Related Questions