编写用于验证字符串输入的参数化测试的最佳实践是什么?

时间:2019-04-03 12:59:49

标签: java junit parameterized-unit-test

我正在为代码编写类似于以下内容的参数化单元测试,以确保我的测试涵盖所有可能的输入情况,并且系统运行正常。

我想出了3种方法,即testGetAnimalMood1,testGetAnimalMood2,testGetAnimalMood3:

public class Exp {

    enum Animal{
        CAT("Cat is happy"),
        DOG("Dog is sad");

        Animal(String mood){
            this.mood = mood;
        }

        private String mood;

        public String getMood(){
            return this.mood;
        }
    }

    public static String getAnimalsMood(String animal){
        return Animal.valueOf(animal).getMood();
    }
}

public class ExpTest {

    @ParameterizedTest
    @CsvSource({"CAT, Cat is happy", "DOG, Dog is sad"})
    public void testGetAnimalMood1(String animal, String expected){
        String mood = Exp.getAnimalsMood(animal);

        Assertions.assertEquals(expected, mood);
    }

    @ParameterizedTest
    @MethodSource("getAnimalMoodParameters2")
    public void testGetAnimalMood2(String animal, String expected){
        String mood = Exp.getAnimalsMood(animal);

        Assertions.assertEquals(expected, mood);
    }

    public static Stream<Arguments> getAnimalMoodParameters2(){
        return Stream.of(Arguments.of("CAT", "Cat is happy"),Arguments.of("DOG", "Dog is sad"));
    }

    @ParameterizedTest
    @MethodSource("getAnimalMoodParameters3")
    public void testGetAnimalMood3(String animal, String expected){
        String mood = Exp.getAnimalsMood(animal);

        Assertions.assertEquals(expected, mood);
    }

    public static Stream<Arguments> getAnimalMoodParameters3(){
        return Arrays.stream(Exp.Animal.values()).map(e -> Arguments.of(e.name(), e.getMood()));
    }

}
通过使用MethodSource,

testGetAnimalMood2看起来比testGetAnimalMood1干净。但是,与此同时,要比以前更难读取用于测试的值。认为getAnimalMoodParameters2方法没有太多附加值,哪个版本是更好的做法?

testGetAnimalMood3看起来更干净,但是它可能会验证我的错误逻辑,因为它正在对代码下的测试使用类似的方法来获取值。另外,如果我不将值写为字符串,则可能无法捕获可能的错字。但是有一个相反的说法是,另一个试图修改此代码的用户可能无法理解该行为 只看那些随意的字符串。

考虑所有这些参数,或者如果您必须添加更多参数,哪种方法是最佳方法?

1 个答案:

答案 0 :(得分:0)

我在编写参数化测试时使用以下设置:

@RunWith(Parameterized.class)
public class MyTest {
    @Parameter(0)
    public String animal;
    @Parameter(1)
    public String expected;

    @Parameters
    public static List<String[]> parameters() {
        return Arrays.asList(
            new String[]{"CAT", "Cat is happy"},
            new String[]{"DOG", "Dog is sad"}
        );
    }

    @Test
    public void testGetAnimalMood(){
        String mood = Exp.getAnimalsMood(animal);

        Assertions.assertEquals(expected, mood);
    }
}

@RunWith(Parameterized.class)告诉JUnit使用不同的参数运行您的类。

@Parameters注释的静态方法是您的方法源。

@Parameter注释的两个字段告诉JUnit应该在哪个索引处选择哪个参数。

其余应该自我解释