Java 如何在JUnit4中动态创建测试套件?
我想使用JUnit4创建一个junit测试套件,其中要包含的测试类的名称在测试套件运行之前是未知的 在JUnit 3中,我可以这样做:Java 如何在JUnit4中动态创建测试套件?,java,junit,junit4,Java,Junit,Junit4,我想使用JUnit4创建一个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 */ publ
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;
}
}
公共最终类MasterTester扩展了测试用例
{
/**
*junit用于指定要运行的测试用例。
*
*@返回包含要运行的测试用例的套件
*/
公共静态测试套件(){
TestSuite=新的TestSuite();
对于(类klass:gatherTestClasses()){
suite.addTestSuite(klass);
}
返回套房;
}
}
然后让gatherTestClasses()
方法计算要运行的测试类
在JUnit4中,声明使用注释:@SuiteClasses({TestClass1.class,TestClass2.class…})
来构建我的测试套件。这里有一些演示如何做到这一点。不幸的是,我看到的示例似乎不允许传递动态生成的TestClass列表
这意味着我必须对BlockJUnit4ClassRunner
进行子类化,我不想这样做
动态指定的测试套件似乎必须在JUnit4中的某个地方。有人知道在哪里吗?我不确定gatherTestClasses()做什么,但假设它在操作系统为Linux时返回一些测试,在操作系统为Windows时返回不同的测试。您可以在JUnit 4.4中通过以下方式复制:
getOS()
和OperatingSystem
的实现是您的自定义代码。我发现类路径套件与测试类的命名约定一起使用时非常有用
以下是一个例子:
import org.junit.extensions.cpsuite.ClasspathSuite;
import org.junit.runner.RunWith;
@RunWith(ClasspathSuite.class)
@ClassnameFilters({".*UnitTest"})
public class MySuite {
}
要创建动态测试套件,需要使用
@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;
}
}
我已经使用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;
}
}
下面是一个完整的示例,说明如何实现这一点。它由两个测试用例类和一个套件组成
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 {
}
}
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 {
}
}
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;
}
}
@RunWith(JUnit4.class)
而不是默认的@RunWith(AndroidJUnit4.class)
{
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;
}
}
@凌驾
公共无效运行测试(){
//在这里定义断言完美,正是我想要的。如果你使用的是apache commons lang,你可以使用“assumeTrue(SystemUtils.IS_OS_WINDOWS)”,这个for循环中的操作似乎是错误的。你的意思是做suite.addTest(test);?@Danail Nachev:对不起,这完全没有意义(不是你的错).JUnit4自豪地将继承替换为注释,因此我没有任何
测试
,只有普通的旧类。因此,除非我全部编辑它们,否则您的解决方案对我不起作用。如何实现findAllTestCasesRuntime()方法?您可以使用junit.framework.JUnit4TestAdapter
构造一个合适的对象来表示您的测试类。但是方法findAllTestCasesRuntime()在哪里
?如果没有这一点,列表是不完整的。Andrejs的回答使类路径变得多余,至少对于动态创建测试套件的任务来说是如此。看起来它不再被维护,并且与本机库有很多问题,我用这个方法该怎么办?我希望该套件成为我父套件的子套件我尝试过,但是如果我添加@BeforeClass
注释它,则@BeforeClass
中的代码不起作用。知道吗?JUnit4TestAdapter
做什么?@Arik所有测试
运行者不喜欢@BeforeClass
。使用
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;
}
}