1

I'm writing unit tests for my (small) program, and the test cases are specified in around 30 different files.
To test it, all I need is a loop that goes over all the files, parse them, and execute what's needed.

The problem is that in that case, all of my tests will be considered as one, since it's all in the same function with the @Test notation.
Is it possible to split it somehow without having to have a separate function for each test file?

The problem with all the tests as one test case, is that I can't see which test case fail the process; and if one fails it fail the rest (I'll get 1 test failed instead of 5/30 failed)

I'm currently using JUnit (4.12), but I'm not obligated to keep using it, so I can switch framework if there's a better solution.

Thanks!

Example:

public class MyTests { @Test public void testFromFiles { // loop through all the files } } output: 1 test run successfully 

Update: The selected answer worked great for me, and I added another solution with JUnit 5 (instead of 4), in case it will help someone.

10
  • 1
    Just throwing this out there... why? Commented May 7, 2017 at 10:28
  • 1
    Why what? didn't got you. Why the test cases are in files? why I want to separate them? Commented May 7, 2017 at 10:30
  • Why you think you want to run your tests in this way? Commented May 7, 2017 at 10:31
  • 2
    Don't you use a (server-side) build server like Jenkins including Maven, Gradle, ant, whatever? Your IDE should be capable of running those tests as well including some kind of report... Commented May 7, 2017 at 10:36
  • 1
    I agree: you are waisting your time here. Learn how off the shelf product implementations work... Instead of trying to invent your own wheel! Seriously: having many testcase and getting helpful information on failed ones is a SOLVED problem. Commented May 7, 2017 at 10:38

2 Answers 2

6

Try this way:

@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 } } 
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks! I'll have a look at that
Working 😎 Exactly what I was looking for. Thanks!!
3

With JUnit 5 and Dynamic Tests:

  • Basic example:

    class DynamicTests { @TestFactory List<DynamicTest> createSomeTests() { return Arrays.asList( DynamicTest.dynamicTest("First dynamically created test", () -> assertTrue(true)), DynamicTest.dynamicTest("Second dynamically created test", () -> assertTrue(true)) ); } } 
  • Example of getting and filtering all test files:

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

The @TestFactory works differently than regular tests, and @BeforeEach / @AfterEach cannot be used in that case:

Dynamic Test Lifecycle

The execution lifecycle of a dynamic test is quite different than it is for a standard @Test case. Specifically, there are no lifecycle callbacks for individual dynamic tests. This means that @BeforeEach and @AfterEach methods and their corresponding extension callbacks are executed for the @TestFactory method but not for each dynamic test. In other words, if you access fields from the test instance within a lambda expression for a dynamic test, those fields will not be reset by callback methods or extensions between the execution of individual dynamic tests generated by the same @TestFactory method.

More examples in the official documentation.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.