【问题标题】:What is the best practice to write parameterized tests for validating string inputs?为验证字符串输入编写参数化测试的最佳实践是什么?
【发布时间】:2019-04-03 12:59:49
【问题描述】:

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

我想出了 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 看起来更干净,但它有验证我的错误逻辑的潜在危险,因为它使用与代码下的测试类似的方法来获取值。此外,如果我不将值写为字符串,我可能无法捕捉到可能的拼写错误。但一个相反的论点是,另一个试图修改此代码的用户可能无法理解该行为 只需查看那些任意字符串。

考虑所有这些论点,或者如果您必须添加更多,哪一个是最好的方法?

【问题讨论】:

    标签: java junit parameterized-unit-test


    【解决方案1】:

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

    @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 应该在哪个索引处选择哪个参数。

    其余的应该是自我解释

    【讨论】:

    • 感谢您的建议。但我的问题更多是关于在 parameters() 方法中创建列表的点。将字符串值放入正确的方法还是我们应该写类似 return Arrays.stream(Exp.Animal.values()).map(e -> Arguments.of(e.name(), e.getMood() ));获取值。即:`@Parameters public static List parameters() { return Arrays.stream(Exp.Animal.values()).map(e -> Arguments.of(e.name(), e.getMood ())); }`
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-24
    • 2016-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-01
    • 1970-01-01
    相关资源
    最近更新 更多