Account
class.
In that lab the focus was on implementing a set of tests that had
already been developed. The goal of today's lab is to practice
designing appropriate unit tests.
postCharge
method of the Account
class. THIS SHOULD BE DONE IN GROUPS OF TWO OR THREE.
postCharge
method. Don't proceed until you have a
clear understanding of how that method is supposed to work.The next step is to design a set of tests that will ensure that
behavior of postCharge
conforms to the specification. It
isn't possible to guarantee that the behavior is correct
through testing. Doing so would require that we
test postCharge
with every possible input for every
possible configuration of an account object. Instead, our goal is to
come up with a manageable number of tests that cover all of the
meaningfully different ways in which the method might be called.
Characterizing "meaningfully different" situations takes practice. As an example, consider an account with a charge limit of $50.00. It would be overkill to include tests that post charges of $.00, $.01, $.02, all the way up to $49.99. That would require almost 5000 tests and if the method works correctly for a charge of $1.12 it is likely to work correctly for a charge of $1.13. On the other hand, a charge of $49.99 is meaningfully different from a charge of $50.00, and a charge of -$.01 is different from a charge of $.00. These points where the expected behavior of the method changes are referred to as "boundary cases" and they make good candidates for creating tests.
Take 10-15 minutes to write down an appropriate set of tests. (Type the descriptions into your worksheet.) In developing your tests, you should take into consideration:
Test | Correct Outcome |
---|---|
A charge of $.01 is posted to an open account with a charge limit of $50.00 and a charge balance of $.00. | The new charge balance should be $.01. |
A charge of $-.01 is posted to a newly created account. | IllegalArgumentException is raised, and the charge balance remains 0. |
Account.java
passes the test. To get you started,
we have provided implementations of the two tests described above.
These tests assume that that the test class has an instance
variable named testAccount
and that setUp
has assigned an appropriate value to that variable.
/*********************************************************** * Test a valid charge on an account with balance 0. ***********************************************************/ @Test public void testValidChargeOnZeroBalance() { testAccount.setChargeLimit(5000); //$50.00 testAccount.postCharge(1); //$00.01 Assert.assertEquals(1, testAccount.getChargeBalance()); } /*********************************************************** * Test negative charge on a new account. ***********************************************************/ @Test public void testNegativeChargeNewAccount() { try { testAccount.postCharge(-1); //-$.01 } catch (IllegalArgumentException e) { Assert.assertEquals(0, testAccount.getChargeBalance()); return; } //If we get here, the appropriate exception was not raised. Assert.fail(); }
Here is an alternate implementation of the second test that takes advantage of JUnit's ability to check that tested code throws the desired exception. This approach would be preferred if the only important outcome of the running the test is the exception.
/*********************************************************** * Test negative charge on a new account. ***********************************************************/ // TEST WILL FAIL UNLESS THIS EXCEPTION IS RAISED // | // v @Test(expected=IllegalArgumentException.class) public void testNegativeChargeNewAccountAlternate() { try { testAccount.postCharge(-1); //-$.01 } catch (IllegalArgumentException e) { Assert.assertEquals(0, testAccount.getChargeBalance()); throw e; //re-throw the exception. } }
Once you have implemented all of your tests, download the file
Account.class
to your lab directory, overwriting your
existing Account.class
file. (Be careful not to
re-compile Account.java
until you are finished with this
exercise. Doing so will overwrite the Account.class
file
that you are testing.) Re-run your tests. Describe any tests that
this implementation fails. Without being able to look at the source,
what errors do you think were made by the programmer of this version
of the Account.java
class?
Hint: There is more than one error in this implementation
of Account.java
. If you testing didn't uncover them,
spend some time rethinking your tests.