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在这里)将显示如下:
应该可以在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。