运行 JUnit @Test 方法的子集

2022-09-03 09:46:41

我们使用 JUnit 4 进行测试:我们有一些类不是 的子类,并且它们具有用 注释的公共方法。我们有一个包含多种方法的文件。如果能够从命令行通过 Ant 运行其中的子集,那就太好了,就像 JUnit 3 的配方一样:TestCase@Test@Test

ant runtest -Dtest=MyTest -Dtests=testFoo,testBar

http://today.java.net/pub/a/today/2003/09/12/individual-test-cases.html

我一直在努力想办法通过Java反射等来实现这一目标。由于似乎没有任何方法可以在运行时“隐藏”方法或删除其注释,因此唯一的选择似乎是使用ClassLoader的方法,这似乎非常困难。@TestdefineClass

附言:在这种情况下,正确的做法是拆分文件,但是有其他选择吗?

感谢您抽出宝贵时间接受采访。


答案 1

从 JUnit 4.12 开始,我们有@Category注释来解决这个问题。


答案 2

guerda的解决方案很好。以下是我最终所做的(这是我之前链接的Luke Francl的食谱以及我在网上看到的其他一些东西的混合):

import org.junit.runner.manipulation.Filter;
import org.junit.runner.Description;

public final class AntCLFilter extends Filter {
    private static final String TEST_CASES = "tests";
    private static final String ANT_PROPERTY = "${tests}";
    private static final String DELIMITER = "\\,";
    private String[] testCaseNames;

    public AntCLFilter() {
        super();
        if (hasTestCases()) testCaseNames = getTestCaseNames();
    }

    public String describe() {
        return "Filters out all tests not explicitly named in a comma-delimited list in the system property 'tests'.";
    }

    public boolean shouldRun(Description d) {
        String displayName = d.getDisplayName();
        // cut off the method name:
        String testName = displayName.substring(0, displayName.indexOf('('));
        if (testCaseNames == null) return true;

        for (int i = 0; i < testCaseNames.length; i++)
            if (testName.equals(testCaseNames[i]))
                return true;
        return false;
    }

    /**
     * Check to see if the test cases property is set. Ignores Ant's
     * default setting for the property (or null to be on the safe side).
     **/
    public static boolean hasTestCases() {
        return
            System.getProperty( TEST_CASES ) == null ||
            System.getProperty( TEST_CASES ).equals( ANT_PROPERTY ) ?
            false : true;
    }

    /**
     * Create a List of String names of test cases specified in the
     * JVM property in comma-separated format.
     *
     * @return a List of String test case names
     *
     * @throws NullPointerException if the TEST_CASES property
     * isn't set
     **/
    private static String[] getTestCaseNames() {

        if ( System.getProperty( TEST_CASES ) == null ) {
            throw new NullPointerException( "Test case property is not set" );
        }

        String testCases = System.getProperty( TEST_CASES );
        String[] cases = testCases.split(DELIMITER);

        return cases;
    }
}

import org.junit.internal.runners.*;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.NoTestsRemainException;

public class FilteredRunner extends TestClassRunner {

    public FilteredRunner(Class<?> clazz) throws InitializationError {
        super(clazz);
        Filter f = new AntCLFilter();
        try {
            f.apply(this);
        } catch (NoTestsRemainException ex) {
            throw new RuntimeException(ex);
        }
    }
}

然后,我用以下语言注释了我的测试类:

@RunWith(FilteredRunner.class)
public class MyTest {

并将以下内容放在我的蚂蚁构建文件中:

<target name="runtest"
        description="Runs the test you specify on the command line with -Dtest="
        depends="compile, ensure-test-name">
    <junit printsummary="withOutAndErr" fork="yes">
        <sysproperty key="tests" value="${tests}" />
        <classpath refid="classpath" />
        <formatter type="plain" usefile="false" />
        <batchtest>
            <fileset dir="${src}">
                <include name="**/${test}.java" />
            </fileset>
        </batchtest>
    </junit>
</target>

关键行是系统属性标签。

现在我可以跑步了

ant runtest -Dtest=MyTest -Dtests=testFoo,testBar

根据需要。这适用于4.4中的JUnit 4.1---,JUnit4ClassRunner的子类,以及4.5及更高版本的BlockJUnit4ClassRunner子类。


推荐