Search code examples
javajunit5

Discovering JUnit5 parameterized test via class and method name throws org.junit.platform.commons.PreconditionViolationException


I have sets of tests that I run to test the UI of various tools on my company's website. I built a system that runs these tests in different environments, and for my concern here, I wrote code that allows me to run a single test in these multiple environments. The problem is that when I try to run a parameterized test via MethodSelector (passing both class and method name as a String), I get the following error:

Caused by: org.junit.platform.commons.PreconditionViolationException: Could not find method with name [TestTheThing] in class [tests.tool.fragments.TestClass].

I then tried passing the method name including the parameter, but then I got this error:

Failed to load parameter type [String param] for method [TestTheThing] in class [tests.tool.fragments.TestClass].

I've been researching this for a little while, but I haven't gotten anywhere, and would appreciate some help. Here's a mockup of the test:

public class TestClass {

    @ParameterizedTest
    @MethodSource("getParams")
    public void TestTheThing(String param) {
        // test code here
    }
}

And this is the actual code I use to find and run the test (all selectors from getAllTestSelectors are of type ClassSelector):

    // Runs a single tests in a fragment of a tool (used for batch-testing only)
    public void runSingleTestInFragment(String fragment, String test) {
        
        if (fragment.equals(""))
            throw new MasterTestException("Fragment name is empty");
        
        if (test.equals(""))
            throw new MasterTestException("Test name is empty");
        
        // Make sure test fragment exists
        String className = null;
        
        for (DiscoverySelector s : getAllTestSelectors()) {
            ClassSelector classSelector = (ClassSelector) s;
            String cname = classSelector.getClassName();
            String name = cname.substring(cname.lastIndexOf(".") + 1);
            
            if (name.contains(fragment)) {
                className = classSelector.getClassName();
                break;
            }
        }
        
        if (className == null)
            throw new MasterTestException("Could not find a test fragment named '" + fragment + "' for the tool " + data.getAsEnum("tool"));
        
        // Create the selector
        MethodSelector selector = DiscoverySelectors.selectMethod(className + "#" + test);
        
        // Test that the selector is valid (will throw a PreconditionViolationException if otherwise)
        try {
            selector.getJavaMethod();
            
        } catch (PreconditionViolationException e) {
            throw new MasterTestException("The test method '" + test + "' does not exist in the fragment '" + fragment + "'", e);
        }
        
        runTests(selector);
    }

Solution

  • The type name is not String param.

    Rather, it has to be a fully qualified type name. For String that is java.lang.String.

    When selecting your parameterized method by its fully qualified method name, if your class in the example package, that would be example.TestClass#TestTheThing(java.lang.String).

    This is fully documented in the Javadoc.