min*_*ibi 2 java junit unit-testing naming-conventions junit5
我读了一些关于测试命名约定的文章,并决定使用带有“should”的文章。它在大多数情况下都工作得很好,例如:
但是我在测试 DecimalRepresentation 类时遇到了问题,该类显示不同数字系统中的数字,只需查看代码:
public class DecimalRepresentationTest {
private DecimalRepresentation decimal;
@BeforeEach
void setup() {
decimal = new DecimalRepresentation();
}
@Test
void shouldReturnZeroIfNumberNotSpecified() {
assertEquals("0", decimal.toBinary());
}
@Test
void shouldReturn10IfNumber2() {
decimal.setNumber(2);
assertEquals("10", decimal.toBinary());
}
@Test
void shouldReturn1111IfNumber15() {
decimal.setNumber(15);
assertEquals("1111", decimal.toBinary());
}
}
Run Code Online (Sandbox Code Playgroud)
现在还不错,但如果我测试负输入,它看起来很糟糕:
@Test
void shouldReturn11111111111111111111111110001000IfNumberNegative120() {
decimal.setNumber(-120);
assertEquals("11111111111111111111111110001000", decimal.toBinary());
}
@Test
void shouldReturn11111111111111111111111111111111IfNumberNegative1() {
decimal.setNumber(-1);
assertEquals("11111111111111111111111111111111", decimal.toBinary());
}
Run Code Online (Sandbox Code Playgroud)
在上面的示例中,我对正输入和负输入进行了两次测试,以确保没有硬编码结果并且算法工作正常,因此我决定将测试分组到嵌套类中以保持约定:
@Nested
@DisplayName("Tests for positive numbers")
class PositiveConverter {
@Test
void shouldReturn10IfNumber2() {
decimal.setNumber(2);
assertEquals("10", decimal.toBinary());
}
@Test
void shouldReturn1111IfNumber15() {
decimal.setNumber(15);
assertEquals("1111", decimal.toBinary());
}
}
@Nested
@DisplayName("Tests for negative numbers")
class NegativeConverter {
@Test
void shouldReturn11111111111111111111111110001000IfNumberNegative120() {
decimal.setNumber(-120);
assertEquals("11111111111111111111111110001000", decimal.toBinary());
}
@Test
void shouldReturn11111111111111111111111111111111IfNumberNegative1() {
decimal.setNumber(-1);
assertEquals("11111111111111111111111111111111", decimal.toBinary());
}
}
Run Code Online (Sandbox Code Playgroud)
我意识到由于惯例,它过于复杂。万一我失误了,它看起来会好得多:
@Test
void testPositiveConversions() {
assertAll(
() -> {decimal.setNumber(2); assertEquals("10", decimal.toBinary());},
() -> {decimal.setNumber(15); assertEquals("1111", decimal.toBinary());}
);
}
@Test
void testNegativeConversions() {
assertAll(
() -> {decimal.setNumber(-120); assertEquals("11111111111111111111111110001000", decimal.toBinary());},
() -> {decimal.setNumber(-1); assertEquals("11111111111111111111111111111111", decimal.toBinary());}
);
}
Run Code Online (Sandbox Code Playgroud)
我应该打破惯例以保持简单吗?我在测试中遇到同样的命名问题,他们得到带有输入和输出或动态测试的列表:
@TestFactory
Stream<DynamicTest> shouldReturnGoodResultsForPositiveNumbers(){ // look at method name lol
List<Integer> inputs = new ArrayList<>(Arrays.asList(2, 15));
List<String> outputs = new ArrayList<>(Arrays.asList("10", "1111"));
return inputs.stream().map(number -> DynamicTest.dynamicTest("Test positive " + number, () -> {
int idx = inputs.indexOf(number);
decimal.setNumber(inputs.get(idx));
assertEquals(outputs.get(idx), decimal.toBinary());
}));
}
Run Code Online (Sandbox Code Playgroud)
名字应该是有帮助的。有时规则有助于找到好名字,有时则不然。然后答案就是放弃规则,也许采取完全不同的东西,比如:
@Test
void testResultForNegativeInput() {
decimal.setNumber(-120);
assertEquals("11111111111111111111111110001000", decimal.toBinary());
}
Run Code Online (Sandbox Code Playgroud)
如果您有多个这样的方法,也许添加“ForMinus120”左右是可以接受的。
但与其在这里花费精力命名:真正的问题是您使用了错误的测试类型:您有一大堆输入数据,这只会导致需要检查的不同输出值。您所有的测试都是关于:一个特殊的输入值应该导致一个特殊的输出值。
您不会使用许多几乎相似的测试方法来做到这一点 - 相反,您转向参数化测试!含义:使用表格来驱动测试。对于 JUnit 5和参数化测试,请转到此处(感谢用户Sam Brannen)。
您花费时间和精力使您的测试易于阅读,这真是太好了。但在这种情况下,这会导致大量代码重复。相反,将输入/输出值放入一张表中,并进行一个测试来检查该表中的所有条目。