[英]Proper unit testing technique
While Using TDD I found myself needing to test a constant (final) hashmap which contains lookup values ( PLEASE SEE REASON WHY THIS WAS THE CASE UNDER UPDATE ) 在使用TDD时,我发现自己需要测试一个包含查找值的常量(最终)hashmap( 请查看为什么这是更新的情况 )
See below 见下文
private static final Map<Integer,String> singleDigitLookup = new HashMap<Integer, String>(){{
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");
}};
With TDD its stressed to test one thing at a time so i started calling my class verifying the validity of each of the elements as below. 对于TDD,它强调一次测试一件事,所以我开始调用我的类来验证每个元素的有效性,如下所示。
TEST STYLE 1
测试风格1
@Test
public void whenWordIsOneThenReturn1(){
assertEquals(1, WordToIntegerConverter.toInteger("One"));
}
after writing the third test I thought it was pretty ridiculous and created a temporary lookup with the reverse key value pairs and began calling in a loop to test as below. 在编写第三个测试后,我认为它非常荒谬,并使用反向键值对创建了一个临时查找,并开始调用循环进行测试,如下所示。
TEST STYLE 2
测试风格2
@Test
public void whenWordIsZeroThroughNineReturnIntegerConversion(){
HashMap<Integer, String> lookup = new HashMap<Integer, String>(){{
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)));
}
}
My Question is this; 我的问题是这个; is it better to use style 1 for unit testing or is it better to use style 2.
使用样式1进行单元测试是否更好,或者使用样式2更好。
I see pros and cons for both. 我看到两者的利弊。 for example style 1 is very concise, test only one thing and easier to understand.
例如,样式1非常简洁,只测试一件事并且更容易理解。 cons for style 1 besides doing a ton of typing the Test suite will blow up with many trivial test.
风格1的缺点除了做大量的打字之外,测试套件将会爆发许多琐碎的测试。 Pros for style 2 is less unit tests.
风格2的优点是单元测试较少。 cons for style 2 has a bit of complexity and may be testing more than one thing but I would argue its only testing one thing the validity of the constant hashmap.
样式2的缺点有点复杂,并且可能测试不止一件事,但我认为它只测试常量hashmap的有效性。
UPDATE I've received a decent amount of blowback from this question so let me further explain. 更新我收到了这个问题的大量反馈,所以让我进一步解释。 Its not the constant I care about per se but validating the different cases of my code.
它本身并不是我关心的常数,而是验证了我的代码的不同情况。 This Was a practice problem (Practicing TDD Via Katas) not production code.
这是一个练习题(练习TDD Via Katas)而不是生产代码。 The problem was converting numbers to words so what I care about in my unit testing is ensuring I could properly handle the different possible numbers.
问题是将数字转换为单词,所以我在单元测试中关心的是确保我能够正确处理不同的数字。 There were other constants that I didn't include for example constant storing teen numbers (11, 12, 13...) and tensDigits(20, 30, 40...).
还有其他常量,我没有包括例如常量存储青少年数字(11,12,13 ......)和tensDigits(20,30,40 ......)。 Its fairly easy to make a typo here.
在这里打个字很容易。
Approach #1 gets the job done, just with an obnoxious amount of cut-n-pasting. 方法#1完成工作,只需要进行大量的切割粘贴。 Approach #2 fixes that, but at the expense that the tests aren't independent: if one test fails the following ones don't run.
方法#2修复了这一问题,但代价是测试不是独立的:如果一个测试失败,则以下测试不会运行。 Fixing one test just to find a bunch of new ones now fail is pretty annoying.
修复一个测试只是为了找到一堆新的现在失败是非常烦人的。 You can improve on this by making a parameterized test, here's an example from junit's wiki:
你可以通过参数化测试来改进这个,这是junit的wiki中的一个例子:
@RunWith(Parameterized.class)
public class FibonacciTest {
@Parameters
public static Collection<Object[]> 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));
}
}
The parameterized test includes a collection of input/expected-output pairs, for each pair the input and output get passed into the constructor call for the test and the test method is called on the new test instance. 参数化测试包括输入/预期 - 输出对的集合,对于每对,输入和输出被传递到构造函数调用以进行测试,并且在新测试实例上调用测试方法。 The looping is kept in the test framework and out of the test, and each test succeeds or fails independently of the others.
循环保存在测试框架中并且不在测试之中,并且每个测试独立于其他测试成功或失败。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.