The right unit testing methodology

When using TDD, I found that I need to check a constant (final) hashmap that contains the search values ​​(PLEASE SEE THE REASONS WHY IT WAS THE UPDATE CASE)

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, he was strained to check one thing at a time, so I started calling my class, checking the validity of each of the elements, as shown below.

TEST STYLE 1

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

after writing the third test, I thought it was pretty funny, and created a temporary search with pairs of return key values ​​and started ringing in a loop to check as shown below.

TEST STYLE 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.

I see the pros and cons for both. for example, style 1 is very concise, checking only one thing is easier to understand. cons for style 1, except that the ton of input for the test suite will explode with a lot of trivial tests. Pluses for style 2 are less than single tests. cons for style 2 has little complexity and can test several things, but I would say that this is the only thing that checks the hashmap constant.

UPDATE I got a decent return on this question, so let me explain further. This is not constant self-care, but a check of various cases of my code. It was a practice problem (TDD Via Katas practice), not production code. The problem was converting the numbers into words, so it worries me in my unit testing so that I can correctly handle the different possible numbers. There were other constants to which I did not include, for example, the constant memorization of the number of teenagers (11, 12, 13 ...) and tensDigits (20, 30, 40 ...). Its quite easy to make a typo here.

+5
source share
1 answer

Approach # 1 does its job, just with the disgusting amount of n-insert cut. Approach No. 2 corrects this, but due to the fact that the tests are not independent: if one test fails, the next ones do not start. Fixing one test to find a bunch of new ones that are failing now is quite annoying. You can improve this by doing a parameterized test, here is an example from the 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)); } } 

A parameterized test includes a set of input / expected output pairs, for each pair the input and output are transferred to the constructor call for the test, and the test method is called in a new test instance. The cycle is stored in the test structure and exits the test, and each test succeeds or fails independently of the others.

+10
source

Source: https://habr.com/ru/post/1240490/


All Articles