JUnit 5参数化测试

JUnit 5参数化测试_第1张图片 JUnit 5参数化测试_第2张图片

本文向您展示如何使用不同的参数(即所谓的“参数化测试”)多次运行测试,让我们看看以下为测试提供参数的方法:

  • @ValueSource
  • @EnumSource
  • @MethodSource
  • @CsvSource
  • @CsvFileSource
  • @ArgumentsSource

我们需要junit-jupiter-params支持参数化测试。

pom.xml

		org.junit.jupiter
		junit-jupiter-engine
		5.5.2
		test
	

	
	
		org.junit.jupiter
		junit-jupiter-params
		5.5.2
		test
	

PS已通过JUnit 5.5.2测试

1. @ValueSource

1.1用于单参数测试。

ValueSourceTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertTrue;

public class ValueSourceTest {

    // This test will run 3 times with different arguments
    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3})
    void test_int_arrays(int arg) {
        assertTrue(arg > 0);
    }

    @ParameterizedTest(name = "#{index} - Run test with args={0}")
    @ValueSource(ints = {1, 2, 3})
    void test_int_arrays_custom_name(int arg) {
        assertTrue(arg > 0);
    }

    @ParameterizedTest(name = "#{index} - Run test with args={0}")
    @ValueSource(strings = {"apple", "banana", "orange"})
    void test_string_arrays_custom_name(String arg) {
        assertTrue(arg.length() > 1);
    }

}

输出量

JUnit 5参数化测试_第3张图片 JUnit 5参数化测试_第4张图片

1.2我们可以通过@EmptySource@NullSource@NullAndEmptySource (自JUnit 5.4起)将空值或空值传递给测试。 让我们看下面的示例来测试isEmpty()方法。

ValueSourceEmptyTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;

import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class ValueSourceEmptyTest {

    boolean isEmpty(String input) {
        return (input == null || input.length() == 0);
    }

	// run 3 times, 1 for empty, 1 for null, 1 for ""
    @ParameterizedTest(name = "#{index} - isEmpty()? {0}")
    @EmptySource
    @NullSource
    //@NullAndEmptySource
    @ValueSource(strings = {""})
    void test_is_empty_true(String arg) {
        assertTrue(isEmpty(arg));
    }

    @ParameterizedTest(name = "#{index} - isEmpty()? {0}")
    @ValueSource(strings = {" ", "\n", "a", "\t"})
    void test_is_empty_false(String arg) {
        assertFalse(isEmpty(arg));
    }
    
}

输出量

JUnit 5参数化测试_第5张图片 JUnit 5参数化测试_第6张图片

2. @EnumSource

2.1运行以Enum为参数的测试。

EnumSourceTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;

import java.util.EnumSet;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.EnumSource.Mode.EXCLUDE;

public class EnumSourceTest {

    enum Size {
        XXS, XS, S, M, L, XL, XXL, XXXL;
    }

    @ParameterizedTest
    @EnumSource(Size.class)
    void test_enum(Size size) {
        assertNotNull(size);
    }

    @ParameterizedTest(name = "#{index} - Is size contains {0}?")
    @EnumSource(value = Size.class, names = {"L", "XL", "XXL", "XXXL"})
    void test_enum_include(Size size) {
        assertTrue(EnumSet.allOf(Size.class).contains(size));
    }

    // Size = M, L, XL, XXL, XXXL
    @ParameterizedTest
    @EnumSource(value = Size.class, mode = EXCLUDE, names = {"XXS", "XS", "S"})
    void test_enum_exclude(Size size) {
        EnumSet excludeSmallSize = EnumSet.range(Size.M, Size.XXXL);
        assertTrue(excludeSmallSize.contains(size));
    }

}

输出。

$ java -jar junit-platform-console-standalone-1.5.2.jar 
	-cp "target/test-classes/" 
	--select-class com.mkyong.params.EnumSourceTest 
	--disable-ansi-colors
	
+-- JUnit Jupiter [OK]
| '-- EnumSourceTest [OK]
|   +-- test_enum_include(Size) [OK]
|   | +-- #1 - Is size contains L? [OK]
|   | +-- #2 - Is size contains XL? [OK]
|   | +-- #3 - Is size contains XXL? [OK]
|   | '-- #4 - Is size contains XXXL? [OK]
|   +-- test_enum(Size) [OK]
|   | +-- [1] XXS [OK]
|   | +-- [2] XS [OK]
|   | +-- [3] S [OK]
|   | +-- [4] M [OK]
|   | +-- [5] L [OK]
|   | +-- [6] XL [OK]
|   | +-- [7] XXL [OK]
|   | '-- [8] XXXL [OK]
|   '-- test_enum_exclude(Size) [OK]
|     +-- [1] M [OK]
|     +-- [2] L [OK]
|     +-- [3] XL [OK]
|     +-- [4] XXL [OK]
|     '-- [5] XXXL [OK]
'-- JUnit Vintage [OK]

3. @MethodSource

3.1运行采用静态method生成参数的测试。

MethodSourceTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.stream.IntStream;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

public class MethodSourceTest {

    @ParameterizedTest(name = "#{index} - Test with String : {0}")
    @MethodSource("stringProvider")
    void test_method_string(String arg) {
        assertNotNull(arg);
    }

    // this need static
    static Stream stringProvider() {
        return Stream.of("java", "rust");
    }

    @ParameterizedTest(name = "#{index} - Test with Int : {0}")
    @MethodSource("rangeProvider")
    void test_method_int(int arg) {
        assertTrue(arg < 10);
    }

    // this need static
    static IntStream rangeProvider() {
        return IntStream.range(0, 10);
    }

}

输出量

+-- JUnit Jupiter [OK]
| '-- MethodSourceTest [OK]
|   +-- test_method_int(int) [OK]
|   | +-- #1 - Test with Int : 0 [OK]
|   | +-- #2 - Test with Int : 1 [OK]
|   | +-- #3 - Test with Int : 2 [OK]
|   | +-- #4 - Test with Int : 3 [OK]
|   | +-- #5 - Test with Int : 4 [OK]
|   | +-- #6 - Test with Int : 5 [OK]
|   | +-- #7 - Test with Int : 6 [OK]
|   | +-- #8 - Test with Int : 7 [OK]
|   | +-- #9 - Test with Int : 8 [OK]
|   | '-- #10 - Test with Int : 9 [OK]
|   '-- test_method_string(String) [OK]
|     +-- #1 - Test with String : java [OK]
|     '-- #2 - Test with String : rust [OK]
'-- JUnit Vintage [OK]

3.2多个参数

MethodSourceMultiTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.params.provider.Arguments.arguments;

public class MethodSourceMultiTest {

    @ParameterizedTest
    @MethodSource("stringIntAndListProvider")
    void testWithMultiArgMethodSource(String str, int length, List list) {
        assertTrue(str.length() > 0);
        assertEquals(length, list.size());
    }

    static Stream stringIntAndListProvider() {
        return Stream.of(
                arguments("abc", 3, Arrays.asList("a", "b", "c")),
                arguments("lemon", 2, Arrays.asList("x", "y"))
        );
    }

}

输出量

+-- JUnit Jupiter [OK]
| '-- MethodSourceMultiTest [OK]
|   '-- test_method_multi(String, int, List) [OK]
|     +-- [1] abc, 3, [a, b, c] [OK]
|     '-- [2] lemon, 2, [x, y] [OK]
'-- JUnit Vintage [OK]

4. @CsvSource

4.1运行以逗号分隔值(csv)作为参数的测试。

CsvSourceTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CsvSourceTest {

    @ParameterizedTest
    @CsvSource({
            "java,      4",
            "clojure,   7",
            "python,    6"
    })
    void test_csv(String str, int length) {
        assertEquals(length, str.length());
    }

}

5. @CsvFileSource

5.1从文件中导入逗号分隔值(csv)作为参数。

src/test/resources/simple.csv
java,      4
clojure,   7
python,    6
CsvFileSourceTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class CsvFileSourceTest {

	// Skip the first line
    @ParameterizedTest
    @CsvFileSource(resources = "/simple.csv", numLinesToSkip = 1)
    void test_csv_file(String str, int length) {
        assertEquals(length, str.length());
    }

}

输出量

+-- JUnit Jupiter [OK]
| '-- CsvFileSourceTest [OK]
|   '-- test_csv_file(String, int) [OK]
|     +-- [1] clojure, 7 [OK]
|     '-- [2] python, 6 [OK]
'-- JUnit Vintage [OK]

6. @ArgumentsSource

6.1创建一个可重用的参数提供程序。

CustomArgumentsProvider.java
package com.mkyong.params;

import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;

import java.util.stream.Stream;

public class CustomArgumentsProvider implements ArgumentsProvider {

    @Override
    public Stream 
		provideArguments(ExtensionContext extensionContext) throws Exception {
        return Stream.of("java", "rust", "kotlin").map(Arguments::of);
    }
}
ArgumentsSourceTest.java
package com.mkyong.params;

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ArgumentsSource;

import static org.junit.jupiter.api.Assertions.assertNotNull;

public class ArgumentsSourceTest {

    @ParameterizedTest
    @ArgumentsSource(CustomArgumentsProvider.class)
    void test_argument_custom(String arg) {
        assertNotNull(arg);
    }

}

下载源代码

$ git clone https://github.com/mkyong/junit-examples
$ cd junit5-examples
$检查src / test / java / com / mkyong / params / *。java

参考文献

  • JUnit 5参数化测试
  • Maven标准目录布局

翻译自: https://mkyong.com/junit5/junit-5-parameterized-tests/

你可能感兴趣的:(JUnit 5参数化测试)