54

我想使用 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;
  }
}

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

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

这个SO 答案表明我必须继承BlockJUnit4ClassRunner我不想做的子类。

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

4

6 回答 6

38

要创建动态测试套件,您需要使用@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;
  }
}

等效的 JUnit 4 类将是:

import org.junit.runners.Suite;

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

}

@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;
  }
}

等效的 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;
  }
}
于 2011-09-13T15:47:16.687 回答
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;
     }
}
于 2012-08-13T10:08:13.870 回答
26

我发现 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 {
}
于 2010-07-20T12:18:57.687 回答
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(..)
}

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

于 2010-07-15T16:35:15.153 回答
0

这是一个如何实现它的完整示例。它结合了两个 testCase 类和一个套件。

  1. 示例仪器测试:

    import android.support.test.rule.ActivityTestRule;
    
    import org.junit.Rule;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.JUnit4;
    
    @RunWith(JUnit4.class)
    public class ExampleInstrumentedTest {
    
    
        @Rule
        public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
    
        @Test
        public void checkInputs() throws Exception {
    
        }
    }
    
  2. ExampleInstrumentedTest2:

    import android.support.test.rule.ActivityTestRule;
    
    import org.junit.Rule;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.junit.runners.JUnit4;
    
    @RunWith(JUnit4.class)
    public class ExampleInstrumentedTest2 {
    
    
        @Rule
        public ActivityTestRule<MainActivity> mActivityTestRule = new ActivityTestRule<>(MainActivity.class);
    
        @Test
        public void checkInputs() throws Exception {
    
        }
    }
    
  3. ExampleInstrumentedSuite:

    import junit.framework.TestSuite;
    
    import org.junit.runner.RunWith;
    import org.junit.runners.AllTests;
    
    @RunWith(AllTests.class)
    public class ExampleInstrumentedSuite {
    
        public static TestSuite suite() {
            TestSuite suite = new TestSuite();
            suite.addTest(new junit.framework.JUnit4TestAdapter(ExampleInstrumentedTest.class));
            suite.addTest(new junit.framework.JUnit4TestAdapter(ExampleInstrumentedTest2.class));
            return suite;
        }
    }
    

请注意,您应该在 testCase 类中使用@RunWith(JUnit4.class)而不是默认值@RunWith(AndroidJUnit4.class)

于 2017-02-23T18:21:30.570 回答
0
public class MyTestCase extends TestCase {
    @Override
    public void runTest() {
        // define assertion here  <===
        assertEquals("yes", "yes");
    }
}

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

        // dynamically create your test case here  <====
        suite.addTest(new MyTestCase());

        return suite;
    }
}
于 2021-03-13T11:18:02.077 回答