在Java中从循环创建多个单元测试

在Java中从循环创建多个单元测试,java,unit-testing,junit,junit4,Java,Unit Testing,Junit,Junit4,我正在为我的(小型)程序编写单元测试,测试用例在大约30个不同的文件中指定。 为了测试它,我只需要一个循环,它遍历所有文件,解析它们,并执行所需的操作 问题是,在这种情况下,我的所有测试都将被视为一个测试,因为它与@Test符号在同一个函数中。 是否可以以某种方式拆分它,而不必为每个测试文件使用单独的函数 所有测试都作为一个测试用例的问题是,我看不出哪个测试用例没有通过这个过程;如果一个失败了,其余的都失败了(我会得到一个测试失败,而不是5/30失败) 我目前正在使用JUnit(4.12),但我

我正在为我的(小型)程序编写单元测试,测试用例在大约30个不同的文件中指定。
为了测试它,我只需要一个循环,它遍历所有文件,解析它们,并执行所需的操作

问题是,在这种情况下,我的所有测试都将被视为一个测试,因为它与
@Test
符号在同一个函数中。
是否可以以某种方式拆分它,而不必为每个测试文件使用单独的函数

所有测试都作为一个测试用例的问题是,我看不出哪个测试用例没有通过这个过程;如果一个失败了,其余的都失败了(我会得到一个测试失败,而不是5/30失败)

我目前正在使用JUnit(4.12),但我没有义务继续使用它,所以如果有更好的解决方案,我可以切换框架

谢谢

例如:

public class MyTests {
    @Test
    public void testFromFiles {
        // loop through all the files
    }
}

output: 1 test run successfully 

更新:选择的答案对我来说非常有用,我用JUnit 5(而不是4)添加了另一个解决方案,以防它对某人有所帮助。

尝试以下方法:

@RunWith(Parameterized.class)
public class EdiTest {

    @SuppressWarnings("WeakerAccess")
    @Parameterized.Parameter(value = 0)
    public String model;

    @SuppressWarnings("WeakerAccess")
    @Parameterized.Parameter(value = 1)
    public String filename;

    @Parameterized.Parameters(name = "{index}: testEDI({0}, {1})")
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][]{
                {"753", "edi753_A.edi"},
                {"753", "edi753_B.edi"},
                {"754", "edi754.edi"},
                {"810", "edi810-withTax.edi"},
                {"810", "edi810-withoutTax.edi"},
        });
    }

    @Before
    public void setUpContext() throws Exception {
        TestContextManager testContextManager = new TestContextManager(getClass());
        testContextManager.prepareTestInstance(this);
    }

    @Test
    public void testEDI() throws IOException {
        String edi = IOUtils.toString(ClassLoader.getSystemResource(filename));
        EdiConverter driver = ediConverterProvider.getConverter(model);

        // your test code here
    }

}
@RunWith(参数化的.class)
公共类编辑测试{
@抑制警告(“弱化访问”)
@参数化。参数(值=0)
公共字符串模型;
@抑制警告(“弱化访问”)
@参数化。参数(值=1)
公共字符串文件名;
@Parameterized.Parameters(name=“{index}:testEDI({0},{1})”)
公共静态收集数据(){
返回Arrays.asList(新对象[][]{
{“753”,“edi753_A.edi”},
{“753”,“edi753_B.edi”},
{“754”,“edi754.edi”},
{“810”,“edi810 with tax.edi”},
{“810”,“edi810不含税。edi”},
});
}
@以前
public void setUpContext()引发异常{
TestContextManager TestContextManager=新的TestContextManager(getClass());
testContextManager.prepareTestInstance(此);
}
@试验
public void testEDI()引发IOException{
字符串edi=IOUtils.toString(ClassLoader.getSystemResource(filename));
EdiConverter驱动程序=ediConverterProvider.getConverter(型号);
//您的测试代码在这里
}
}
尝试以下方法:

@RunWith(Parameterized.class)
public class EdiTest {

    @SuppressWarnings("WeakerAccess")
    @Parameterized.Parameter(value = 0)
    public String model;

    @SuppressWarnings("WeakerAccess")
    @Parameterized.Parameter(value = 1)
    public String filename;

    @Parameterized.Parameters(name = "{index}: testEDI({0}, {1})")
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][]{
                {"753", "edi753_A.edi"},
                {"753", "edi753_B.edi"},
                {"754", "edi754.edi"},
                {"810", "edi810-withTax.edi"},
                {"810", "edi810-withoutTax.edi"},
        });
    }

    @Before
    public void setUpContext() throws Exception {
        TestContextManager testContextManager = new TestContextManager(getClass());
        testContextManager.prepareTestInstance(this);
    }

    @Test
    public void testEDI() throws IOException {
        String edi = IOUtils.toString(ClassLoader.getSystemResource(filename));
        EdiConverter driver = ediConverterProvider.getConverter(model);

        // your test code here
    }

}
@RunWith(参数化的.class)
公共类编辑测试{
@抑制警告(“弱化访问”)
@参数化。参数(值=0)
公共字符串模型;
@抑制警告(“弱化访问”)
@参数化。参数(值=1)
公共字符串文件名;
@Parameterized.Parameters(name=“{index}:testEDI({0},{1})”)
公共静态收集数据(){
返回Arrays.asList(新对象[][]{
{“753”,“edi753_A.edi”},
{“753”,“edi753_B.edi”},
{“754”,“edi754.edi”},
{“810”,“edi810 with tax.edi”},
{“810”,“edi810不含税。edi”},
});
}
@以前
public void setUpContext()引发异常{
TestContextManager TestContextManager=新的TestContextManager(getClass());
testContextManager.prepareTestInstance(此);
}
@试验
public void testEDI()引发IOException{
字符串edi=IOUtils.toString(ClassLoader.getSystemResource(filename));
EdiConverter驱动程序=ediConverterProvider.getConverter(型号);
//您的测试代码在这里
}
}
使用JUnit 5和:

  • :

    类动态测试{
    @试验工厂
    列出createSomeTests(){
    返回数组.asList(
    DynamicTest.DynamicTest(“第一个动态创建的测试”,
    ()->资产真(真)),
    DynamicTest.DynamicTest(“第二个动态创建的测试”,
    ()->资产真实(真实))
    );
    }
    }
    
  • 获取和筛选所有测试文件的示例:

    class MyTestsClass {
        @TestFactory
        List<DynamicTest> runAllTestFiles() {
            List<DynamicTest> list = new ArrayList<DynamicTest>();
            try (Stream<Path> paths = Files.walk(Paths.get("tests_dir"))) {
                List<Path> files = paths
                        .filter(path -> path.getFileName().toString().endsWith(".mytests"))
                        .collect(Collectors.toList());
                files.forEach(file -> list.add(
                        DynamicTest.dynamicTest(
                            file.getFileName().toString(), 
                            () -> testFileWithSomeAsserts(file))
                ));
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return list;
        }
    }
    
    类MyTestsClass{
    @试验工厂
    列出runAllTestFiles(){
    列表=新的ArrayList();
    try(Stream path=Files.walk(path.get(“tests\u dir”)){
    列出文件=路径
    .filter(path->path.getFileName().toString().endsWith(“.mytests”))
    .collect(Collectors.toList());
    files.forEach(文件->列表.add(
    动态测试,动态测试(
    file.getFileName().toString(),
    ()->testFileWithSomeAsserts(文件))
    ));
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    退货清单;
    }
    }
    
@TestFactory
的工作原理与常规测试不同,在这种情况下,不能使用每个测试之前的
/
@之后的

动态测试生命周期

动态测试的执行生命周期与标准
@test
案例的执行生命周期截然不同。具体来说,没有针对单个动态测试的生命周期回调。这意味着对
@TestFactory
方法执行
@beforeach
@AfterEach
方法及其相应的扩展回调,但不对每个动态测试执行。换句话说,如果您访问lambda表达式中用于动态测试的测试实例中的字段,那么在执行同一
@TestFactory
方法生成的各个动态测试之间,回调方法或扩展不会重置这些字段

与JUnit 5和:

  • :

    类动态测试{
    @试验工厂
    列出createSomeTests(){
    返回数组.asList(
    DynamicTest.DynamicTest(“第一个动态创建的测试”,
    ()->资产真(真)),
    DynamicTest.DynamicTest(“第二个动态创建的测试”,
    ()->资产真实(真实))
    );
    }
    }
    
  • 获取和筛选所有测试文件的示例:

    class MyTestsClass {
        @TestFactory
        List<DynamicTest> runAllTestFiles() {
            List<DynamicTest> list = new ArrayList<DynamicTest>();
            try (Stream<Path> paths = Files.walk(Paths.get("tests_dir"))) {
                List<Path> files = paths
                        .filter(path -> path.getFileName().toString().endsWith(".mytests"))
                        .collect(Collectors.toList());
                files.forEach(file -> list.add(
                        DynamicTest.dynamicTest(
                            file.getFileName().toString(), 
                            () -> testFileWithSomeAsserts(file))
                ));
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return list;
        }
    }
    
    类MyTestsClass{
    @试验工厂
    列出runAllTestFiles(){
    列表=新的ArrayList();
    try(Stream path=Files.walk(path.get(“tests\u dir”)){
    列出文件=路径
    .filter(路径