循环 JUnit 测试的最佳实践
Best practice for looped JUnit test
在学校作业中,我应该为 returns true
参数 < 80 的方法编写黑盒测试,否则 false
。目前我的做法是
for (int i = 0; i < 80; i++) {
assertTrue(someMethod(i));
}
for (int i = 80; i <= 100; i++) {
assertFalse(someMethod(i));
}
但是,这需要 100 个单独的断言。有没有best/better的修炼方法?如果相关的话,我正在使用 JUnit 5,但如果需要可以切换到 JUnit 4(毕竟这只是一项学校作业)。问候。
您通常只测试边缘情况就可以了,也许还有一个范围的额外代表,例如
assertTrue(someMethod(79));
assertFalse(someMethod(80));
// not reaaaally necessary
assertTrue(someMethod(50));
assertFalse(someMethod(100));
在您的情况下,您可能还想将截止值添加为常量(例如 static final int THRESHOLD = 80
)并在您的测试用例中使用它;这样,如果阈值发生变化,更改起来会更容易。
对于 JUnit 5,考虑重复测试功能:
https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
对于你的情况,你可以重复 100 次:
@ParameterizedTest
@MethodSource("args")
public void so(int argument)
{
assertTrue((argument < 80) == someMethod(argument));
}
private static IntStream args()
{
return IntStream.range(0, 100);
}
我同意检查 1 - 100 不是完全必要的,只需检查 80 (79, 80, 81) 左右。 可能 唯一值得的其他情况是检查负数,但在这种情况下即使那样似乎也有点过分了。
如果您决定只检查 79、80、81,那么 ValueSource
注释更清晰:
@ParameterizedTest
@ValueSource(ints = { 79, 80, 81 })
public void so(int argument)
{
assertTrue((argument < 80) == someMethod(argument));
}
您可以(在 JUnit5 中)执行以下操作:
编写(至少)三个涵盖三个主要用例的测试用例,即输入 < 80
、输入 > 80
和输入 = 80
.
看起来像这样:
@Test
@DisplayName("[< 80]")
@Tag("below_eighty")
void numberBelowEightyTest(TestInfo testInfo) {
int number = 79;
assertTrue(someMethod(number));
}
@Test
@DisplayName("[= 80]")
@Tag("equals_eighty")
void numberEqualsEightyTest(TestInfo testInfo) {
int number = 80;
assertFalse(someMethod(number));
}
@Test
@DisplayName("[> 80]")
@Tag("above_eighty")
void numberAboveEightyTest(TestInfo testInfo) {
int number = 81;
assertFalse(someMethod(number));
}
测试了这三个用例后,由于直接测试了边界以及最近的邻居,您可以确定所有剩余数字。
如果有人使用 JUnit 4:
@RunWith(Parameterized.class)
public class PerformanceStatusTest {
@Parameterized.Parameters
public static List<Integer> data() {
return IntStream.range(0, 100)
.boxed()
.collect(Collectors.toList());
}
private int testValue;
public PerformanceStatusTest(final int testValue) {
this.testValue = testValue;
}
@Test
public void someMethodTest() {
assertTrue((testValue < 80) == someMethod(testValue));
}
}
提到另一个选项,在这个简单的例子中,它会进行全方位检查:在 JUnit 5 平台上使用基于 属性 的测试和 jqwik:
import org.junit.jupiter.api.*;
import net.jqwik.api.*;
import net.jqwik.api.constraints.*;
class PartitionedFunctionProperty {
@Property
void below80returnTrue(@ForAll @IntRange(min= 0, max = 79) int aNumber) {
Assertions.assertTrue(someMethod(aNumber));
}
@Property
void from80returnFalse(@ForAll @IntRange(min = 80, max = 100) int aNumber) {
Assertions.assertFalse(someMethod(aNumber));
}
private boolean someMethod(int aNumber) {
if (aNumber < 80) return true;
return false;
}
}
如果想真正看到全范围真的在生成,加
注释 @Report(Reporting.GENERATED)
到 属性 方法,您将获得以下输出:
timestamp = 2018-12-05T14:50:36.668, generated = [80]
timestamp = 2018-12-05T14:50:36.671, generated = [81]
timestamp = 2018-12-05T14:50:36.672, generated = [82]
timestamp = 2018-12-05T14:50:36.672, generated = [83]
...
timestamp = 2018-12-05T14:50:36.676, generated = [98]
timestamp = 2018-12-05T14:50:36.676, generated = [99]
timestamp = 2018-12-05T14:50:36.677, generated = [100]
timestamp = 2018-12-05T14:50:36.679
tries = 21
checks = 21
generation-mode = EXHAUSTIVE
after-failure = SAMPLE_ONLY
seed = 4490524914178941008
在学校作业中,我应该为 returns true
参数 < 80 的方法编写黑盒测试,否则 false
。目前我的做法是
for (int i = 0; i < 80; i++) {
assertTrue(someMethod(i));
}
for (int i = 80; i <= 100; i++) {
assertFalse(someMethod(i));
}
但是,这需要 100 个单独的断言。有没有best/better的修炼方法?如果相关的话,我正在使用 JUnit 5,但如果需要可以切换到 JUnit 4(毕竟这只是一项学校作业)。问候。
您通常只测试边缘情况就可以了,也许还有一个范围的额外代表,例如
assertTrue(someMethod(79));
assertFalse(someMethod(80));
// not reaaaally necessary
assertTrue(someMethod(50));
assertFalse(someMethod(100));
在您的情况下,您可能还想将截止值添加为常量(例如 static final int THRESHOLD = 80
)并在您的测试用例中使用它;这样,如果阈值发生变化,更改起来会更容易。
对于 JUnit 5,考虑重复测试功能:
https://junit.org/junit5/docs/current/user-guide/#writing-tests-parameterized-tests
对于你的情况,你可以重复 100 次:
@ParameterizedTest
@MethodSource("args")
public void so(int argument)
{
assertTrue((argument < 80) == someMethod(argument));
}
private static IntStream args()
{
return IntStream.range(0, 100);
}
我同意检查 1 - 100 不是完全必要的,只需检查 80 (79, 80, 81) 左右。 可能 唯一值得的其他情况是检查负数,但在这种情况下即使那样似乎也有点过分了。
如果您决定只检查 79、80、81,那么 ValueSource
注释更清晰:
@ParameterizedTest
@ValueSource(ints = { 79, 80, 81 })
public void so(int argument)
{
assertTrue((argument < 80) == someMethod(argument));
}
您可以(在 JUnit5 中)执行以下操作:
编写(至少)三个涵盖三个主要用例的测试用例,即输入 < 80
、输入 > 80
和输入 = 80
.
看起来像这样:
@Test
@DisplayName("[< 80]")
@Tag("below_eighty")
void numberBelowEightyTest(TestInfo testInfo) {
int number = 79;
assertTrue(someMethod(number));
}
@Test
@DisplayName("[= 80]")
@Tag("equals_eighty")
void numberEqualsEightyTest(TestInfo testInfo) {
int number = 80;
assertFalse(someMethod(number));
}
@Test
@DisplayName("[> 80]")
@Tag("above_eighty")
void numberAboveEightyTest(TestInfo testInfo) {
int number = 81;
assertFalse(someMethod(number));
}
测试了这三个用例后,由于直接测试了边界以及最近的邻居,您可以确定所有剩余数字。
如果有人使用 JUnit 4:
@RunWith(Parameterized.class)
public class PerformanceStatusTest {
@Parameterized.Parameters
public static List<Integer> data() {
return IntStream.range(0, 100)
.boxed()
.collect(Collectors.toList());
}
private int testValue;
public PerformanceStatusTest(final int testValue) {
this.testValue = testValue;
}
@Test
public void someMethodTest() {
assertTrue((testValue < 80) == someMethod(testValue));
}
}
提到另一个选项,在这个简单的例子中,它会进行全方位检查:在 JUnit 5 平台上使用基于 属性 的测试和 jqwik:
import org.junit.jupiter.api.*;
import net.jqwik.api.*;
import net.jqwik.api.constraints.*;
class PartitionedFunctionProperty {
@Property
void below80returnTrue(@ForAll @IntRange(min= 0, max = 79) int aNumber) {
Assertions.assertTrue(someMethod(aNumber));
}
@Property
void from80returnFalse(@ForAll @IntRange(min = 80, max = 100) int aNumber) {
Assertions.assertFalse(someMethod(aNumber));
}
private boolean someMethod(int aNumber) {
if (aNumber < 80) return true;
return false;
}
}
如果想真正看到全范围真的在生成,加
注释 @Report(Reporting.GENERATED)
到 属性 方法,您将获得以下输出:
timestamp = 2018-12-05T14:50:36.668, generated = [80]
timestamp = 2018-12-05T14:50:36.671, generated = [81]
timestamp = 2018-12-05T14:50:36.672, generated = [82]
timestamp = 2018-12-05T14:50:36.672, generated = [83]
...
timestamp = 2018-12-05T14:50:36.676, generated = [98]
timestamp = 2018-12-05T14:50:36.676, generated = [99]
timestamp = 2018-12-05T14:50:36.677, generated = [100]
timestamp = 2018-12-05T14:50:36.679
tries = 21
checks = 21
generation-mode = EXHAUSTIVE
after-failure = SAMPLE_ONLY
seed = 4490524914178941008