在JUnit 5中参数化类和测试 [英] Parameterize both class and tests in JUnit 5

查看:59
本文介绍了在JUnit 5中参数化类和测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以同时测试类(例如您可以在JUnit 4中使用Parameterized@Parameters进行参数化)和测试方法(例如您可以在JUnit 4中使用JUnitParams或在JUnit 5中使用@ParameterizedTest)进行参数化)?我需要最后获取参数的笛卡尔积.

Is there a way to parameterize both test class (like you could do with Parameterized and @Parameters in JUnit 4) and test methods (like you could do with JUnitParams in JUnit 4 or with @ParameterizedTest in JUnit 5)? I need to get the Cartesian product of the parameters in the end.

使用所需方法对java.nio.ByteBuffer进行部分测试的示例:

Example of a partial test for java.nio.ByteBuffer using the desired approach:

public class ByteBufferTest {
    private static final int BUFFER_SIZE = 16384;
    private final ByteOrder byteOrder;
    private ByteBuffer sut;

    @Factory(dataProvider = "byteOrders")
    public ByteBufferTest(ByteOrder byteOrder) {
        this.byteOrder = byteOrder;
    }

    @DataProvider
    public static Object[][] byteOrders() {
        return new Object[][] {
                {ByteOrder.BIG_ENDIAN},
                {ByteOrder.LITTLE_ENDIAN}
        };
    }

    @BeforeMethod
    public void setUp() {
        sut = ByteBuffer.allocate(BUFFER_SIZE);
        sut.order(byteOrder);
    }

    @Test(dataProvider = "validPositions")
    public void position(int position) {
        System.out.println(byteOrder + " position " + position);
        sut.position(position);
        assertThat(sut.position()).isEqualTo(position);
    }

    @DataProvider
    public static Object[][] validPositions() {
        return new Object[][] {{0}, {1}, {BUFFER_SIZE - 1}};
    }

    @Test(dataProvider = "intPositionsAndValues")
    public void putInt(int position, int value, byte[] expected) {
        System.out.println(byteOrder + " position " + position + " value " + value);
        sut.putInt(position, value);
        assertThat(sut.array())
                .contains(expected[0], atIndex(position))
                .contains(expected[1], atIndex(position + 1))
                .contains(expected[2], atIndex(position + 2))
                .contains(expected[3], atIndex(position + 3));
    }

    @DataProvider
    public Object[][] intPositionsAndValues() {
        if (byteOrder == ByteOrder.BIG_ENDIAN) {
            return new Object[][]{
                    {0, 0, new byte[4]},
                    {5, 123456789, new byte[] {0x07, 0x5B, (byte) 0xCD, 0x15}},
            };
        } else {
            return new Object[][]{
                    {0, 0, new byte[4]},
                    {5, 123456789, new byte[] {0x15, (byte) 0xCD, 0x5B, 0x07}},
            };
        }
    }
}

它产生:

LITTLE_ENDIAN position 0
LITTLE_ENDIAN position 1
LITTLE_ENDIAN position 16383
BIG_ENDIAN position 0
BIG_ENDIAN position 1
BIG_ENDIAN position 16383
LITTLE_ENDIAN position 0 value 0
LITTLE_ENDIAN position 5 value 123456789
BIG_ENDIAN position 0 value 0
BIG_ENDIAN position 5 value 123456789

我们正在考虑从TestNG迁移到JUnit 5,但是我们经常使用这种方法.在上面的示例中,将字节顺序用作类级参数并不是巧合:我们经常需要对各种二进制数据处理器进行测试,其中测试构造函数将采用字节/位顺序参数,并且针对每个测试运行大端和小端.

We're thinking about migrating to JUnit 5 from TestNG, but we use this kind of thing pretty often. The use of the byte order as a class-level parameter in the example above is not a coincidence: we often need tests for various binary data processor, where the test constructor would take a byte/bit order argument, and we run every test for both Big Endian and Little Endian.

我当时正在考虑为此创建扩展,然后使用ExtendWith,但是也许有一个现有扩展或某些我可以错过的开箱即用的功能?

I was thinking about creating an extension for this and then use ExtendWith, but maybe there is an existing extension or something that works out-of-the-box that I have missed?

推荐答案

JUnit木星(香草)

您可以合并多个来源,例如@MethodSource.根据您的TestNG示例:

JUnit Jupiter (Vanilla)

You can combine multiple sources within e.g. a @MethodSource. Based on your TestNG example:

class ExampleTest {

    @ParameterizedTest
    @MethodSource("args")
    void test(String classParameter, String testParameter) {
        System.out.println(classParameter + " " + testParameter);
    }

    static Stream<Arguments> args() {
        return classParameters().flatMap(
                classParameter -> testParameters().map(
                        testParameter -> Arguments.of(classParameter, testParameter)));
    }

    static Stream<String> classParameters() {
        return Stream.of("classParam1", "classParam2");
    }

    static Stream<String> testParameters() {
        return Stream.of("testParam1", "testParam2");
    }

}

这将产生:

classParam1 testParam1
classParam1 testParam2
classParam2 testParam1
classParam2 testParam2

根据 OP 的要求,在此处是具有至少两种具有不同参数集的测试方法的示例":

As requested by the OP, here is "an example with at least two test methods with different set of parameters":

class ExampleTest {

    static Stream<String> classParams() {
        return Stream.of("classParam1", "classParam2", "classParam3");
    }

    static Stream<Arguments> withClassParams(List<?> methodParams) {
        return classParams().flatMap(
                classParam -> methodParams.stream().map(
                        methodParam -> Arguments.of(classParam, methodParam)));
    }

    @ParameterizedTest
    @MethodSource
    void booleanParams(String classParam, boolean booleanParam) {
        System.out.println(classParam + " " + booleanParam);
    }

    static Stream<Arguments> booleanParams() {
        return withClassParams(List.of(false, true));
    }

    @ParameterizedTest
    @MethodSource
    void integerParams(String classParam, int integerParam) {
        System.out.println(classParam + " " + integerParam);
    }

    static Stream<Arguments> integerParams() {
        return withClassParams(List.of(1, 2, 3, 4, 5, 6));
    }

    @ParameterizedTest
    @MethodSource
    void objectParams(String classParam, Object objectParam) {
        System.out.println(classParam + " " + objectParam);
    }

    static Stream<Arguments> objectParams() {
        return withClassParams(List.of(new Object()));
    }

}

3个类参数以及3个具有不同类型和大小的不同方法参数,产生以下输出:

3 class parameters plus 3 different method parameters with different types and sizes, producing the following output:

classParam1 java.lang.Object@35cabb2a
classParam2 java.lang.Object@35cabb2a
classParam3 java.lang.Object@35cabb2a
classParam1 1
classParam1 2
classParam1 3
classParam1 4
classParam1 5
classParam1 6
classParam2 1
classParam2 2
classParam2 3
classParam2 4
classParam2 5
classParam2 6
classParam3 1
classParam3 2
classParam3 3
classParam3 4
classParam3 5
classParam3 6
classParam1 false
classParam1 true
classParam2 false
classParam2 true
classParam3 false
classParam3 true

JUnit Pioneer

有用于JUnit Jupiter的 JUnit Pioneer 扩展包.它带有@CartesianProductTest.使用上面的扩展示例:

JUnit Pioneer

There is the JUnit Pioneer extension pack for JUnit Jupiter. It comes with @CartesianProductTest. Using the extended the example from above:

class CartProdTest {

    @CartesianProductTest(factory = "classWithObjectParams")
    void testClassWithObject(String classParam, Object objectParam) {
        System.out.println(classParam + " " + objectParam);
    }

    static CartesianProductTest.Sets classWithObjectParams() {
        return new CartesianProductTest.Sets()
                .addAll(classParams())
                .add(new Object());
    }

    @CartesianProductTest(factory = "classWithIntegerParams")
    void testClassWithInteger(String classParam, int integerParam) {
        System.out.println(classParam + " " + integerParam);
    }

    static CartesianProductTest.Sets classWithIntegerParams() {
        return new CartesianProductTest.Sets()
                .addAll(classParams())
                .add(1, 2, 3, 4, 5, 6);
    }

    @CartesianProductTest(factory = "classWithBooleanParams")
    void testClassWithBoolean(String classParam, boolean booleanParam) {
        System.out.println(classParam + " " + booleanParam);
    }

    static CartesianProductTest.Sets classWithBooleanParams() {
        return new CartesianProductTest.Sets()
                .addAll(classParams())
                .add(false, true);
    }

    static Stream<String> classParams() {
        return Stream.of("classParam1", "classParam2", "classParam3");
    }

}

这将产生相同的输出.

这篇关于在JUnit 5中参数化类和测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆