JUnittesting与dynamic数量的testing

在我们的项目中,我有几个JUnittesting,例如从目录中获取每个文件并对其执行testing。 如果我在TestCase实现了testEveryFileInDirectory方法,那么只会显示一个可能失败或成功的testing。 但是我对每个文件的结果感兴趣。 我怎样才能编写一个TestCase / TestSuite ,使每个文件显示为一个单独的testing,例如在Eclipse的graphics化TestRunner中? (为每个文件编写明确的testing方法不是一种select。)

在Eclipse Testrunner中也将ParameterizedTest与一个名称相比较 。

看看JUnit 4中的参数化testing

其实我前几天做了这个。 我会尽力解释

首先正常地构build你的testing类,就像你只用一个input文件进行testing一样。 装饰你的课堂:

 @RunWith(Parameterized.class) 

构build一个构造函数,它接受每次testing调用都会改变的input(在这种情况下,它可能是文件本身)

然后,构build一个将返回数组的Collection的静态方法。 集合中的每个数组都将包含类构造函数(例如文件)的input参数。 装饰这个方法:

 @Parameters 

这是一个示例类。

 @RunWith(Parameterized.class) public class ParameterizedTest { private File file; public ParameterizedTest(File file) { this.file = file; } @Test public void test1() throws Exception { } @Test public void test2() throws Exception { } @Parameters public static Collection<Object[]> data() { // load the files as you want Object[] fileArg1 = new Object[] { new File("path1") }; Object[] fileArg2 = new Object[] { new File("path2") }; Collection<Object[]> data = new ArrayList<Object[]>(); data.add(fileArg1); data.add(fileArg2); return data; } } 

另外检查这个例子

JUnit 3

 public class XTest extends TestCase { public File file; public XTest(File file) { super(file.toString()); this.file = file; } public void testX() { fail("Failed: " + file); } } public class XTestSuite extends TestSuite { public static Test suite() { TestSuite suite = new TestSuite("XTestSuite"); File[] files = new File(".").listFiles(); for (File file : files) { suite.addTest(new XTest(file)); } return suite; } } 

JUnit 4

 import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; @RunWith(Parameterized.class) public class TestY { @Parameters public static Collection<Object[]> getFiles() { Collection<Object[]> params = new ArrayList<Object[]>(); for (File f : new File(".").listFiles()) { Object[] arr = new Object[] { f }; params.add(arr); } return params; } private File file; public TestY(File file) { this.file = file; } @Test public void testY() { fail(file.toString()); } } 

JUnit 5

JUnit 5支持通过静态方法dynamicTest@TestFactory生成的DynamicTest的概念。

 import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import static org.junit.jupiter.api.DynamicTest.dynamicTest; import java.util.stream.Stream; @TestFactory public Stream<DynamicTest> testFiles() { return Arrays.asList(new File(".").list()) .stream() .map((file) -> dynamicTest( "Test for file: " + file, () -> { /* Your test comes here */ })); } 

在IDE中运行的testing(IntelliJ在这里)将显示如下:

在IntelliJ输出

应该可以在JUnit 3中inheritanceTestSuite并覆盖tests()方法来列出文件,并为每个返回一个TestCase子类的一个实例,该实例将文件名作为构造参数,并且有一个testing方法来testing文件构造函数。

在JUnit 4中,它可能更容易。

你可以考虑使用JUnitParams库 ,所以你会有更多的(更干净的)选项:

 @org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class) public class ParameterizedTest { @org.junit.Test @junitparams.Parameters(method = "data") public void test1(File file) throws Exception { } @org.junit.Test @junitparams.Parameters(method = "data") public void test2(File file) throws Exception { } public static File[] data() { return new File[] { new File("path1"), new File("path2") }; } } 

 @org.junit.runner.RunWith(junitparams.JUnitParamsRunner.class) public class ParameterizedTest { @org.junit.Test @junitparams.Parameters(value = { "path1", "path2" }) public void test1(String path) throws Exception { File file = new File(path); } @org.junit.Test @junitparams.Parameters(value = { "path1", "path2" }) public void test2(String path) throws Exception { File file = new File(path); } } 

你可以在这里看到更多的使用示例 。

另外关于JUnitParams,为什么写入参数化testing更容易和更易读 :

JUnitParams项目为JUnit增加了一个新的运行器,并为JUnit> 4.6提供了更简单易读的参数化testing。

与标准JUnit的主要区别参数化的runner:

  • 更明确 – 参数在testing方法params,而不是类字段
  • 更less的代码 – 你不需要一个构造函数来设置参数
  • 你可以在一个类中混合参数化和非参数化的方法
  • 参数可以作为CSVstring或参数提供程序类传递
  • 参数提供者类可以提供尽可能多的参数提供方法,所以你可以分组不同的情况
  • 你可以有一个testing方法,提供参数(不再有外部类或静态)
  • 您可以在IDE中查看实际的参数值(在JUnit的“参数化”中,它只是连续的参数数量)

如果TestNG是一个选项,你可以使用DataProviders参数 。

每个单独文件的testing结果都会显示在基于文本的报告或Eclipse的TestNG插件UI中。 运行的总testing数将单独计算每个文件。

这种行为不同于JUnit 理论 ,其中所有结果都集中在一个“理论”条目下,只计为1个testing。 如果你想在JUnit中单独的结果报告,你可以尝试参数化testing 。

testing和input

 public class FileTest { @DataProvider(name="files") public File[][] getFiles(){ return new File[][] { { new File("file1") }, { new File("file2") } }; // or scan a directory } @Test(dataProvider="files") public void testFile(File file){ //run tests on file } } 

输出示例

 PASSED: testFile(file1) PASSED: testFile(file2) =============================================== Default test Tests run: 2, Failures: 0, Skips: 0 =============================================== 

我有一个类似的问题,并最终编写了一个简单的JUnit 4亚军,允许医学dynamic生成testing。

https://github.com/kimble/junit-test-factory