Reputation: 7790
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...
Upvotes: 1
Views: 122
Reputation: 1145
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);
}
}
Upvotes: 3
Reputation: 6448
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);
}
}
Upvotes: 2