我正在做我的第一个Java项目,并且喜欢完全TDD它。我正在使用JUnit来编写测试。显然JUnit不支持data providers,这使得用20个不同版本的参数测试相同的方法相当烦人。什么是支持数据提供程序的最流行的/标准的Java测试工具?我遇到了TestNG,但不知道这个是多么受欢迎,或者它与替代品相比如何。
如果有一种方法可以使用JUnit获得这种行为,那么这也可能有用。
答案 0 :(得分:41)
我公司的同事为JUnit为TestNG风格编写了一个免费的DataProvider,你可以找到on 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 );
}
编辑:从v1.7起,它还支持其他方式提供数据(字符串,列表),并且可以内联提供程序,因此不一定需要单独的方法。
可以在github的手册页上找到完整的工作示例。它还有一些功能,比如在实用程序类中收集提供程序以及从其他类中访问它们等。手册页非常详细,我相信你会在那里找到任何问题。
答案 1 :(得分:27)
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
}
}
答案 2 :(得分:7)
根据您在灵活性与可读性方面的需求,您可以选择Parameterized
- junit的内置选项,由dkatzel描述。其他选项是由zohhak等外部库提供的外部junit运行器,您可以这样做:
@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) );
}
或junitParams功能稍有不同。只挑选最适合你的东西
答案 3 :(得分:1)
这是另一种选择。您不必使用Google Guava,那只是我的实现。
这与@dkatzel的答案使用相同的@Parameters
,但是@Parameters
注释代替了带有参数的类,而是用于特定的测试方法,因此您可以选择使用该集合的方法论据。
import java.util.Collection;
import com.google.common.collect.ImmutableList;
import junitparams.JUnitParamsRunner;
import junitparams.Parameters;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(JUnitParamsRunner.class)
public class FrobTester {
@SuppressWarnings("unused")
private Collection validfrobAndGorpValues() {
return ImmutableList.of(
new Object[] {"frob28953", 28953},
new Object[] {"oldfrob-189-255", 1890255}
);
}
@Test
@Parameters(method = "validfrobAndGorpValues")
public void whenGivenFrobString_thenGorpIsCorrect(
String frobString,
int expectedGorpValue
) {
Frob frob = new Frob(frobString);
Assert.assertEquals(expectedGorpValue, frob.getGorpValue());
}
}
答案 4 :(得分:0)
您可以使用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}")
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)
);
}
}
可以从注释,方法甚至CSV文件中加载测试参数。