适当的unit testing技术

在使用TDD时,我发现自己需要测试一个包含查找值的常量(最终)散列图( 请查看为什么这是更新的情况

见下文

private static final Map singleDigitLookup = new HashMap(){{ put(0,"Zero");put(1,"One");put(2,"Two");put(3,"Three");put(4,"Four");put(5,"Five");put(6,"Six");put(7,"Seven"); put(8,"Eight");put(9,"Nine"); }}; 

对于TDD,它强调要一次测试一件事,所以我开始调用我的类来validation每个元素的有效性,如下所示。

测试风格1

 @Test public void whenWordIsOneThenReturn1(){ assertEquals(1, WordToIntegerConverter.toInteger("One")); } 

在编写第三个测试后,我认为它非常荒谬,并使用反向键值对创建了一个临时查找,并开始调用循环进行测试,如下所示。

测试风格2

 @Test public void whenWordIsZeroThroughNineReturnIntegerConversion(){ HashMap lookup = new HashMap(){{ put(0,"Zero");put(1,"One");put(2,"Two");put(3,"Three");put(4,"Four");put(5,"Five"); put(6,"Six");put(7,"Seven");put(8,"Eight");put(9,"Nine"); }}; for(int i = 0; i < 10; i++) { assertEquals(i, WordToIntegerConverter.toInteger(lookup.get(i))); } } 

我的问题是这样的; 使用样式1进行unit testing是否更好,或者使用样式2更好。

我看到两者的利弊。 例如,样式1非常简洁,只测试一件事并且更容易理解。 风格1的缺点除了做大量的打字之外,测试套件将会爆发许多琐碎的测试。 风格2的优点是unit testing较少。 样式2的缺点有点复杂,并且可能测试不止一件事,但我认为它只测试常量hashmap的有效性。

更新我收到了这个问题的大量反馈,所以让我进一步解释。 它本身并不是我关心的常量,而是validation了我的代码的不同情况。 这是一个实践问题(练习TDD Via Katas)而不是生产代码。 问题是将数字转换为单词,所以我在unit testing中关心的是确保我能够正确处理不同的数字。 还有其他常量,我没有包括例如常量存储青少年数字(11,12,13 ……)和tensDigits(20,30,40 ……)。 在这里打个字很容易。

方法#1完成工作,只需要进行大量的切割粘贴。 方法#2修复了这一问题,但代价是测试不是独立的:如果一个测试失败,则以下测试不会运行。 修复一个测试只是为了找到一堆新的现在失败是非常烦人的。 你可以通过参数化测试来改进这个,这是junit的wiki中的一个例子:

 @RunWith(Parameterized.class) public class FibonacciTest { @Parameters public static Collection data() { return Arrays.asList(new Object[][] { { 0, 0 }, { 1, 1 }, { 2, 1 }, { 3, 2 }, { 4, 3 }, { 5, 5 }, { 6, 8 } }); } private int fInput; private int fExpected; public FibonacciTest(int input, int expected) { fInput= input; fExpected= expected; } @Test public void test() { assertEquals(fExpected, Fibonacci.compute(fInput)); } } 

参数化测试包括输入/​​期望 – 输出对的集合,对于每对,输入和输出被传递到构造函数调用以进行测试,并且在新测试实例上调用测试方法。 循环保留在测试框架中并且不在测试之内,并且每个测试独立于其他测试成功或失败。