在 Java 中生成数据驱动的单元测试

Generate Data-Driven Unit-Tests in Java

假设我有一个 junit 方法

public class BusinessClassTest {

    private BusinessClass fixture;

    @Test
    public void test1() {
       //the following two paths reside in the man/test/resources folder
       String inputPath = "/fixtures/1/input";
       String expectedPath = "/fixtures/1/expected";
       validatedFixture(inputPath, expectedPath);
    }

    private void valiateFixture(String inputPath, String expectedPath) {
        //inputData = load the input data
        //feed it to a fixture
        //actual = fixture.process(inputData)
        //expectedData = loadExpectedData
        //validate(expectedData, actualData);
     }
}

现在假设我在 fixtures 下有 20 个文件夹。我如何遍历文件夹并为每个文件夹生成一个类似于

的方法
    @Test
    public void test{test_number}() {
       //the following two paths reside in the man/test/resources folder
       String inputPath = "/fixtures/{test_number}/input";
       String expectedPath = "/fixtures/{test_number}/expected";
       validatedFixture(inputPath, expectedPath);
    }

空闲时我想将此 class 构建为 maven 的一部分。


更新

我正在使用 velocity 来生成 class 但是,不确定如何从 maven 进行代码生成...

你真的需要动态构建测试类吗?另一种方法是遍历 fixtures 基本路径的所有子目录,然后直接为每个路径调用 validatedFixture。在下面的 Java8 中查找示例:

@Test
public void bigTest {
  File file = new File("/fixtures/");
  String[] dirs = file.list((current, name) -> 
                    new File(current, name).isDirectory());

  for (String testNumber : dirs) {
    String inputPath = "/fixtures/" + dirs + "/input";
    String expectedPath = "/fixtures/" + dirs + "/expected";
    // omit the test method and call validation directly
    validatedFixture(inputPath, expectedPath);
  }
}

使用 Matt 列出的文件系统遍历,您可以使用参数化测试来执行您的数字验证。

此方法将根据@Parameters(name) 注释的参数为您提供命名良好的测试。

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

import org.junit.Assert;
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 BusinessClassTest{
    @Parameters(name="{0}:{1}")
    public static Collection<Object[]> getTestPaths() {
        Collection<Object[]> allTests = new ArrayList<>();

         File file = new File("/fixtures/");
          String[] dirs = file.list((current, name) -> 
                            new File(current, name).isDirectory());

          for (String testNumber : dirs) {
            String inputPath = "/fixtures/" + dirs + "/input";
            String expectedPath = "/fixtures/" + dirs + "/expected";
            allTests.add(asConstructorArguments(inputPath, expectedPath));
          }

        return allTests;
    }

    private static Object[] asConstructorArguments(String inputPath, String expectedPath) {
        return new Object[]{inputPath, expectedPath};
    }

    private final String inputData;
    private final String expectedData;
    private final Fixture fakedFixture;


    public BusinessClassTest(String input, final String expected) {
        this.inputData = input;
        this.expectedData = expected;
        fakedFixture = new Fixture() {          
            @Override
            public String process(String path) {
                return expected;
            }
        };
    }

    @Test
    public void validateFixture() {
        //feed it to a fixture
        String actualData = fakedFixture.process(inputData);
        Assert.assertEquals(expectedData, actualData);
    }

    //Interface to emulate your API
    public interface Fixture {
        String process(String path);
    }
}