java 在JUnit 5中为@ParameterizedTest生成显示名称

cnwbcb6i  于 2023-04-28  发布在  Java
关注(0)|答案(4)|浏览(135)

我有一堆@ParameterizedTest,它们从@MethodSource接收参数,并得到相当冗长的toString()结果(例如:例如 selenium 的WebDriver)。默认情况下,这些名称用于组成相应的显示名称。JUnit 5用户指南:
默认情况下,参数化测试调用的显示名称包含调用索引和该特定调用的所有参数的String表示。但是,您可以通过@ParameterizedTest注解的name属性[。..]
虽然这允许在一定程度上自定义显示名称,但似乎我无法调整单个参数的字符串表示。不幸的是,通过@DisplayNameGeneration指定生成器只能应用于类级别,并且不会影响参数化测试调用的显示名称。
有没有办法将DisplayNameGenerator用于@ParameterizedTest,或者定制给定参数的字符串表示形式?

5sxhfpxr

5sxhfpxr1#

从JUnit 5开始。8.0中,有一个Named<T>接口作为JUnit Jupiter API的一部分,“自动支持将包含的有效负载[参数]直接注入参数化方法”(参见issue #2301)。示例:

@DisplayName("A parameterized test with named arguments")
@ParameterizedTest
@MethodSource("namedArguments")
void testWithNamedArguments(File file) {}

static Stream<Arguments> namedArguments() {
    return Stream.of(
        Arguments.of(Named.of("An important file", new File("path1"))),
        Arguments.of(Named.of("Another file", new File("path2")))
    );
}

如果你喜欢静态导入,你也可以从ArgumentsNamed中选择相应的别名:

arguments(named("An important file", new File("path1")))

更多信息,请参阅相应文档。

ldxq2e6h

ldxq2e6h2#

为了间接地实现您的目标,直到JUnit直接支持它,您总是可以向测试添加一个参数,该参数是所需的字符串。然后需要在参数提供程序方法中进行定制。

@ParameterizedTest(name = "{index} {1}")
@MethodSource("argumentProvider")
public void testSomething(Object someObject, String niceRepresentation) {
    // Test something
}

private static Stream<Arguments> argumentProvider() {
    return Stream.of(
            Arguments.of(new Object(), "Nice 1"),
            Arguments.of(new Object(), "Nice 2")
    );
}

缺点是单元测试提供的参数在测试的实现中没有使用,这可能会损害清晰度,但随后它会成为测试报告中冗长名称的折衷。

xqnpmsa8

xqnpmsa83#

只是在surefire报告中添加了类似的问题。
使用@DisplayName@ParameterizedTest(name = "{0}")后,报告中未获得正确的测试名称。
这个问题解决了我的问题#1255

<plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>3.0.0-M4</version>
            <configuration>
                <statelessTestsetReporter
                        implementation="org.apache.maven.plugin.surefire.extensions.junit5.JUnit5Xml30StatelessReporter">
                    <disable>false</disable>
                    <version>3.0</version>
                    <usePhrasedFileName>false</usePhrasedFileName>
                    <usePhrasedTestSuiteClassName>true</usePhrasedTestSuiteClassName>
                    <usePhrasedTestCaseClassName>true</usePhrasedTestCaseClassName>
                    <usePhrasedTestCaseMethodName>true</usePhrasedTestCaseMethodName>
                </statelessTestsetReporter>
            </configuration>
        </plugin>
wh6knrhe

wh6knrhe4#

对于较大的单元(例如需要更多参数,与一些服务交互等)。)我通常使用TestCase记录并覆盖toString()方法以获得一个显示良好的名称。

class Test {
    
    private record TestCase(
        String testName,
        // params, expected outputs, validators, etc
    ) {
        @Override
        public String toString() {
            return testName;
        }
    }

    @ParameterizedTest(name = "{index}. {0}")
    @MethodSource("testCases_source")
    void checkTestCase(TestCase testCase) {
        // test method impl
    }

    public static Stream<Arguments> testCases_source() {
        return TestCases.testCasesStream(
            new TestCase(
                "should return value and invoke the method", // testName
                InputDto.of("v1"), // input 
                (service) -> { verify(mockk, times(1)).method() }, // verifier
                true // output       
            )
            new TestCase(
                "should return value and invoke the service twice",
                // ...
            )
            // other test cases 
        )
    }

    // helper from other class to apply some syntax sugar:
    public Stream<Arguments> testCasesStream(TestCase... testCases) {
        return Arrays.stream(testCases).map(Arguments::of); 
    }
}

不幸的是,Java没有任何记录的创建模式,所以我通常用Java Class + Lombok替换记录(或者使用Kotlin)。

相关问题