参数化测试

Java 测试入门

Maria Milusheva

Senior Software Engineer

示例:用户名校验

回顾第 1 章的用户名校验练习:

public static boolean isValidUsername(String username) {
    if (username == null || username.isEmpty() || username.contains(" ")) {
        return false;
    }
    return username.length() >= 3;
}
Java 测试入门

示例:重复的校验测试

回想这些测试如下所示:

@Test
void isValidUsername_returnsFalse() {
    String username = "____";

    boolean actual = isValidUsername(username);

    assertFalse(actual);
}

无需写 3 个这样的测试!

1 https://en.wikipedia.org/wiki/Don%27t_repeat_yourself
Java 测试入门

参数化测试:语法

@ParameterizedTest 替代 @Test

其导入位置:

import org.junit.jupiter.params.ParameterizedTest;

还需另一个注解:@ValueSource

其导入位置:

import org.junit.jupiter.params.provider.ValueSource;
Java 测试入门

参数化测试:示例测试

@ParameterizedTest
@ValueSource(strings = {"", "jane doe"}) // 注意:是 "strings",不是 String
void isValidUsername_returnsFalse(String username) { // 测试可接收参数
    boolean actual = isValidUsername(username);

    assertFalse(actual);
}

JUnit 将其作为两个测试执行:

Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
All tests passed!
Java 测试入门

@ValueSource 的限制

@ValueSource 仅支持特定类型。

@ValueSource(bytes = {1, 2, 3, 42})
@ValueSource(shorts = {100, 200, 300})
@ValueSource(ints = {1, 2, 3, 42})
@ValueSource(longs = {1000L, 2000L, 3000L})
@ValueSource(floats = {1.0f, 3.14159f, 2.71828f})
@ValueSource(doubles = {3.14, 2.71828, 1.4142})
@ValueSource(chars = {'a', 'b', 'c', 'Z'})
@ValueSource(booleans = {true, false})
@ValueSource(strings = {"Hello", "JUnit", "5", "Parameter"})
@ValueSource(classes = {String.class, Integer.class, ValueSourceExamples.class})
1 https://junit.org/junit5/docs/5.7.1/api/org.junit.jupiter.params/org/junit/jupiter/params/provider/ValueSource.html
Java 测试入门

@NullSource

无法将 null 传给 @ValueSource,否则无法编译:

@ParameterizedTest
@ValueSource(strings = {"", "jane doe", null}) // 无法编译
void isValidUsername_returnsFalse(String username) {
    boolean actual = isValidUsername(username);

    assertFalse(actual);
}

请改用 @NullSource

Java 测试入门

运行完整的 ParameterizedTest

如果向 @ValueSource 传入 null,将无法编译。

@ParameterizedTest
@NullSource // 添加一个 null 输入用例
@ValueSource(strings = {"", "jane doe"})
void isValidUsername_returnsFalse(String username) {
    boolean actual = isValidUsername(username);

    assertFalse(actual);
}
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0
All tests passed!
Java 测试入门

每个测试的多个参数

@ValueSource 的另一限制:每个测试只能传一个值。

看看这个方法:

int countLetters(String input) {
    if (input != null) {
        return input.length();
    }
    return 0;
}
Java 测试入门

@CsvSource

对于多值,请使用 @CsvSource(CSV = 逗号分隔值):

@ParameterizedTest
@CsvSource({"Hello World, 11", "DataCamp, 8", "'', 0", ", 0"})
void countLetters_countsLetters(String input, int expected) {
    int actual = countLetters(input);

    assertEquals(expected, actual);
}

注意 ", 0" 表示输入为 null 和 0。要输入空字符串,请在 JUnit 5.10 中使用 "'', 0"

@CsvSource has similar type limitations as @ValueSource.

Java 测试入门

注意:导入 Source 注解

所有 @____Source 注解可从此处导入:

import org.junit.jupiter.params.provider.*;
Java 测试入门

¡Vamos a practicar!

Java 测试入门

Preparing Video For Download...