用数据提供程序编写Java测试

Jer*_*auw 33 java testing junit

我正在做我的第一个Java项目,并且喜欢完全TDD它.我正在使用JUnit来编写测试.显然JUnit不提供对数据提供程序的支持,这使得用20个不同版本的参数测试相同的方法相当烦人.什么是支持数据提供程序的最流行的/标准的Java测试工具?我遇到过TestNG,但不知道它是多么受欢迎,或者它与替代品相比如何.

如果有一种方法来获得这种行为是一种使用JUnit的好方法,那么这也可能有效.

Ing*_*ürk 43

我们公司的同事为JUnit编写了一个免费提供的TestNG风格的DataProvider,你可以在github上找到它(https://github.com/TNG/junit-dataprovider).

我们在非常大的项目中使用它,它对我们来说效果很好.它比JUnit有一些优势,Parameterized因为它可以减少单独类的开销,也可以执行单个测试.

一个例子看起来像这样

@DataProvider
public static Object[][] provideStringAndExpectedLength() {
    return new Object[][] {
        { "Hello World", 11 },
        { "Foo", 3 }
    };
}

@Test
@UseDataProvider( "provideStringAndExpectedLength" )
public void testCalculateLength( String input, int expectedLength ) {
    assertThat( calculateLength( input ) ).isEqualTo( expectedLength );
}
Run Code Online (Sandbox Code Playgroud)

编辑:从v1.7开始,它还支持其他方式提供数据(字符串,列表),并且可以内联提供程序,因此不一定需要单独的方法.

可以在github的手册页上找到完整的工作示例.它还有一些功能,比如在实用程序类中收集提供程序以及从其他类访问它们等.手册页非常详细,我相信你会发现任何问题都可以解答.

  • 对于那些试图运行上面例子的人:不要忘记在测试类中添加`@RunWith(DataProviderRunner.class)`注释! (5认同)

dka*_*zel 32

JUnit 4具有参数化测试,它与php数据提供者的功能相同

@RunWith(Parameterized.class)
public class MyTest{ 
     @Parameters
    public static Collection<Object[]> data() {
           /*create and return a Collection
             of Objects arrays here. 
             Each element in each array is 
             a parameter to your constructor.
            */

    }

    private int a,b,c;


    public MyTest(int a, int b, int c) {
            this.a= a;
            this.b = b;
            this.c = c;
    }

    @Test
    public void test() {
          //do your test with a,b
    }

    @Test
    public void testC(){
        //you can have multiple tests 
        //which all will run

        //...test c
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 当您有多个测试使用同一列表中的相同参数列表或元素时,这很有用.如果没有重叠,它实际上没有帮助.在我的例子中,我有一个有效输入列表和一个无效输入列表,没有重叠.把它们放在一起会非常奇怪. (10认同)
  • 这是类似的,虽然不一样.PHP数据提供程序将参数传递给您的方法.在您的示例中,参数将传递给测试类的构造函数.如果我有多个测试方法,我想要一个值列表怎么办?为每个人创建一个测试类非常尴尬. (8认同)

pio*_*rek 7

根据您在灵活性和可读性方面的需求,您可以选择Parameterized- junit的内置选项,由dkatzel描述.其他选项是外部图书馆提供的外部junit跑步者,如zohhak,你可以这样做:

 @TestWith({
        "clerk,      45'000 USD, GOLD",
        "supervisor, 60'000 GBP, PLATINUM"
    })
    public void canAcceptDebit(Employee employee, Money money, ClientType clientType) {
        assertTrue(   employee.canAcceptDebit(money, clientType)   );
    }
Run Code Online (Sandbox Code Playgroud)

junitParams具有不同的功能.只挑选最适合你的东西


Jus*_*der 5

您可以使用 JUnit 5 的 ParameterizedTest。这是来自https://www.petrikainulainen.net/programming/testing/junit-5-tutorial-writing-parameterized-tests/的一个例子:

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
 
import java.util.stream.Stream;
 
import static org.junit.jupiter.api.Assertions.assertEquals;
 
@DisplayName("Should pass the method parameters provided by the sumProvider() method")
class MethodSourceExampleTest {
 
    @DisplayName("Should calculate the correct sum")
    @ParameterizedTest(name = "{index} => a={0}, b={1}, sum={2}")
    @MethodSource("sumProvider")
    void sum(int a, int b, int sum) {
        assertEquals(sum, a + b);
    }
 
    private static Stream<Arguments> sumProvider() {
        return Stream.of(
                Arguments.of(1, 1, 2),
                Arguments.of(2, 3, 5)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

可以从注释、方法甚至 CSV 文件加载测试参数。