The importance of not Seeing

For a long time now, I have been pondering about writing crisp unit tests. On one side, it seemed that having everything you wanted to know about the test in one method was good, but experience in reading code (thats rite, reading code) has taught me that test methods with a lot of variables are hard to understand.

Honestly, I simply could not see how I could present (to myself) the importance of keeping a test or for that matter, any piece of code simple. But recently a series of “spot the” type of images that crept up in facebook gave me the breakthrough idea.

The following is a map of silicon valley. Quick question, how long does it take for you to spot the Sun Micro system logo?

 I would expect that it would have taken atleast a scan of three fourths of the picture to  spot it, if you are not already familiar with it. Another question, surely you would have noticed a logo of a company you know. And once you have spotted the logo, some facts about the company would have flashed across your mind. How many times did this happen? Every time this happens, it takes you longer to find what you are looking for.

This might seem to be something that has nothing to do with programming. As it turns out, it is alarmingly similar. Here is a piece of code, that is pretty common in unit tests. It is written in Junit and uses Mockito for mocking dependencies. But I guess the code is explanatory enough

public class IncomeTaxCalculatorTest {

        @Mock
        IncomeTaxTable incomeTaxTable;

        IncomeTaxCalculator incomeTaxCalculator = new IncomeTaxCalculator(incomeTaxTable);

        @Test
        public void shouldCalculateIncomeTax(){
                Employee employee = new Employee();
                employee.setStatus("married");

                PayPackage payPackage = new PayPackage();
                payPackage.setBasicPay(20,000);
                payPackage.setFlexiblePay(30,000);
                payPackage.setHRAPercetage(0.10);

                employee.setPayPackage(payPackage);

                int manuallyCalculatedTaxableIncome = 27,000;

                when(incomeTaxTable.getTaxPercentageFor(manuallyCalculatedTaxableIncome)).thenReturn(20);

                double result = incomeTaxCalulator.compute(employee);

                double manuallyComputedIncomeTax = 2,000;

                assertEquals(manuallyComputedIncomeTax, result);
        }

}

Now when reading this test, it would seem to me that there is no relationship between the net taxable income and the basic and flexibly pays. The argument is that, if it is not necessary to know the relationship in the test, the basic and the flexible pays should not be present in the test.

As I explained in my previous post, the primary value that the unit test adds to code is that, it represents an understanding of the class which is being coded. Tests such as the above fail in that aspect miserably.

For argument sake, let us say that the primary reason for a unit test is to verify the class under test. In that respect too, the above test fails. I can assure you if the above test passes, that the class will work for the given example inputs. But there is no way of determining if it will work for the real world inputs. There are plenty of techniques to make such assertions. But back to the topic.

Now how would it read if the test were written something like this.

public class IncomeTaxCalculatorTest {

        @Mock
        IncomeTaxTable incomeTaxTable;

        IncomeTaxCalculator incomeTaxCalculator = new IncomeTaxCalculator(incomeTaxTable);

        @Test
        public void shouldCalculateIncomeTax(){
                // Group 1 employee is married and has taxable income > 40,000 & HRA is 10 percent
                Employee employee = new Group1Employee(40,000);//The net taxable income

                when(incomeTaxTable.getTaxPercentageFor(employee)).thenReturn(20);

                double result = incomeTaxCalulator.compute(employee);

                double manuallyComputedIncomeTax = 2,000;
                assertEquals(manuallyComputedIncomeTax, result);
        }

}

The IncomeTax calculator does not care what is the actual value of the basic and flexible pays. All it cares is the net taxable income. Likewise, the IncomeTaxTable does not care about the actual value of the netTaxableIncome. It just wants to know if the employee is in Grade1 to give out the tax percentage.

The primary difference between the two pieces of code is that, both test a class that behaves similarly, but the second test, contains lot less detail.

Aha. As it is with everything else, in programming too, the “devil is in the details”. So the lesser you bombard yourselves with un-necessary details, the lesser unnecessary details you “see”, the better you understand something. True with unit test as with everything else. What if the map had only Sun’s logo on it? We could have spotted it immediately.

Writing correct software is hard. As Booch points out, in his excellent book, “Complexity is an essential property of software. We can but only master it”. And mastering complexity is what we do when we consider only the details that we immediately need, forgetting for the time being those that we dont require rite away.

Quote for the day,

“Every closed eye is not sleeping, and every open eye is not seeing.” – Bill Cosby

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s