如何在JUnit 4中动态创建测试套件?

Tom*_*sky 51 java junit junit4

我想使用JUnit 4创建一个junit测试套件,其中要包含的测试类的名称在运行测试套件之前是未知的.

在JUnit 3中,我可以这样做:

public final class MasterTester extends TestCase
{
  /**
   * Used by junit to specify what TestCases to run.
   * 
   * @return a suite containing what TestCases to run
   */
  public static TestSuite suite() {
    TestSuite suite = new TestSuite();

    for(Class<?> klass : gatherTestClasses()) {
      suite.addTestSuite(klass);
    }

    return suite;
  }
}
Run Code Online (Sandbox Code Playgroud)

并让该gatherTestClasses()方法处理确定要运行的测试类.

在JUnit 4中,文档说使用注释:@SuiteClasses({TestClass1.class, TestClass2.class...})构建我的测试套件.有很多SO答案显示如何做到这一点.不幸的是,我看到的示例似乎不允许传递动态生成的TestClasses列表.

这个答案建议我必须继承BlockJUnit4ClassRunner我不想做的事情.

动态指定的测试套件似乎必须在某个地方的JUnit 4中.有谁知道在哪里?

Dan*_*hev 36

要创建动态测试套件,您需要使用@RunWith注释.有两种常用方法可供使用:

@RunWith(Suite.class)

这允许您指定构成相关测试套件的类.这相当于JUnit 3风格:

import junit.framework.TestSuite;
import junit.framework.TestCase;

public final class MasterTester extends TestCase {

  public static TestSuite suite() {
    TestSuite suite = new TestSuite();
    suite.addTestSuite(TestClass1.class);        
    suite.addTestSuite(TestClass2.class);
    // etc...
    return suite;
  }
}
Run Code Online (Sandbox Code Playgroud)

等效的JUnit 4类将是:

import org.junit.runners.Suite;

@RunWith(Suite.class)
@SuiteClasses({TestClass1.class, TestClass2.class})
public final class MasterTester {

}
Run Code Online (Sandbox Code Playgroud)

@RunWith(AllTests.class)

这允许您动态指定组成测试套件的测试.如果直到运行时才知道测试,则无法在注释中指定它们.您可以使用此构造.所以,如果JUnit 3代码是:

import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.framework.Test;

public final class MasterTester extends TestCase {

  public static TestSuite suite() {
    TestSuite suite = new TestSuite();
    for (Test test : findAllTestCasesRuntime()) {
      suite.addTest(test);
    }
    return suite;
  }
}
Run Code Online (Sandbox Code Playgroud)

等效的JUnit 4代码将是:

import org.junit.runners.AllTests;
import junit.framework.TestSuite;
import junit.framework.Test;

@RunWith(AllTests.class)
public final class MasterTester {

  public static TestSuite suite() {
    TestSuite suite = new TestSuite();
    for (Test test : findAllTestCasesRuntime()) {
      suite.addTest(test);
    }
    return suite;
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 如何实现findAllTestCasesRuntime()方法? (3认同)
  • @Danail Nachev:对不起,但这都没有意义(不是你的错).JUnit4自豪地用注释取代了继承,所以我没有任何`Test`,只是简单的旧类.因此,除非我全部编辑,否则您的解决方案对我不起作用. (2认同)
  • 但是“findAllTestCasesRuntime()”方法在哪里?如果没有这个,列表就不完整。 (2认同)

And*_*ejs 35

我已经尝试使用JUnit 4.8并且它可以工作:

@RunWith(AllTests.class)
public class SomeTests
{
    public static TestSuite suite()
    {
        TestSuite suite = new TestSuite();

        suite.addTest(new JUnit4TestAdapter(Test1.class));
        suite.addTest(new JUnit4TestAdapter(Test2.class));

        return suite;
     }
}
Run Code Online (Sandbox Code Playgroud)


Jav*_*cky 25

我发现Classpath套件在我的测试类上使用命名约定时非常有用.

https://github.com/takari/takari-cpsuite

这是一个例子:

import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.runner.RunWith;

@RunWith(ClasspathSuite.class)
@ClassnameFilters({".*UnitTest"})
public class MySuite {
}
Run Code Online (Sandbox Code Playgroud)

  • Andrejs的回答使Classpath变得多余,至少对于动态创建测试套件的任务而言. (6认同)
  • 很失望,这不是Junit的一部分. (2认同)

Bra*_*pit 6

我不确定gatherTestClasses()是做什么的,但是假设它在操作系统是Linux时会返回一些测试,而在操作系统是Windows时会返回不同的测试.您可以使用以下假设在JUnit 4.4中复制它:

@Test
public void onlyOnLinux() {
    assumeThat(getOS(), is(OperatingSystem.LINUX));
    // rest of test
}

@Test
public void onlyOnWindows() {
    assumeThat(getOS(), is(OperatingSystem.WINDOWS));
    // rest of test
}

@Test
public void anyOperatingSystem() {
    // just don't call assumeThat(..)
}
Run Code Online (Sandbox Code Playgroud)

实现getOS()OperatingSystem成为您的自定义代码.

  • 完美,正是我想要的.如果你正在使用apache commons-lang,你可以使用"assumeTrue(SystemUtils.IS_OS_WINDOWS);" (2认同)