简体   繁体   中英

Generate Data-Driven Unit-Tests in Java

Let's say I have a junit method

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);
     }
}

Now let's assume that I have 20 folders under fixtures. How can I loop through the folders and for each folder generate a method similar to

    @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);
    }

Idlealy I would like to build this class out as part of maven.


Update

I'm using velocity to generate the class however, not sure how to engage the code generation from maven...

Using what Matt has listed for the File system traversal, you could use a parameterized test to perform your numerable validations.

This approach will provide you with well named tests based on the arguments to the @Parameters(name) annotation.

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);
    }
}

Do you really need to dynamically build the test classes? Another approach would be to iterate over all the subdirectories of your fixtures base path and then call the validatedFixture directly for each path. Find a sample in Java8 below:

@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);
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM