Page 168 -
P. 168

It’s not enough to just test for expected results. A good unit test suite will include tests for
                          boundary conditions, or inputs at the edge of the range of acceptable values. There are many
                          kinds of boundary conditions, including:
                          • Zero values, null values, or other kinds of empty or missing values
                          • Very large or very small numbers that don’t conform to expectations (like a rate of
                            10000%, or an account that has been active for a million years)
                          • Arrays and lists that contain duplicates or are sorted in unexpected ways
                          • Events that happen out of order, like accessing a database before it’s opened
                          • Badly formatted data (like an invalid XML file)

                          A few tests will verify that these boundary conditions are handled as expected. This unit
                          test verifies that calculateFee( ) can handle an account with a zero interest rate:
                            public void testZeroRate( ) {
                                Account accounts[] = new Account[1];

                                accounts[0] = new Account( );
                                accounts[0].principal = 1000;
                                accounts[0].rate = (float) 0;
                                accounts[0].daysActive = 100;
                                accounts[0].accountType = Account.PREMIUM;
                                float result = feeCalculation.calculateFee(accounts);
                                assertEquals(result, 0, 0.00001);
                            }
                          This test passes in an account with a negative principal (a calculator was used to come up
                          with the expected result by hand):
                            public void testNegativePrincipal( ) {
                                Account accounts[] = new Account[1];

                                accounts[0] = new Account( );
                                accounts[0].principal = -10000;
                                accounts[0].rate = (float) 0.263;
                                accounts[0].daysActive = 100;

                                accounts[0].accountType = Account.PREMIUM;
                                float result = feeCalculation.calculateFee(accounts);
                                assertEquals(result, -9.33265, 0.0001);
                            }
                          In this case, the programmer expects the correct mathematical result to be returned, even
                          though it may not make business sense in this context. Another programmer maintaining
                          the code can see this expectation simply by reading through this unit test.

                          The next test verifies that the software can handle a duplicate reference. feeCalculation( )
                          takes an array of objects. Even if one of those objects is a duplicate reference of another
                          one in the array, the result should still match the one calculated by hand:




                   160  CHAPTER SEVEN
   163   164   165   166   167   168   169   170   171   172   173