Java Reference
In-Depth Information
method. If a test can't verify a feature in isolation, it usually means the code isn't flexi-
ble enough and you should refactor it. Modifying code to test it is normal.
4.1.6
Documenting expected behavior
Imagine you need to learn a new
API
. On one side is a 300-page document describ-
ing the
API
, and on the other are some examples showing how to use it. Which
would you choose?
The power of examples is well known. Unit tests are exactly this: examples that
show how to use the
API
. As such, they make excellent developer documentation.
Because unit tests match the production code, they
must
always be up to date, unlike
other forms of documentation,
Listing 4.1 illustrates how unit tests help provide documentation. The
test-
TransferWithoutEnoughFunds()
method shows that an
AccountInsufficientFunds-
Exception
is thrown when an account transfer is performed without enough funds.
Listing 4.1
Unit tests as automatic documentation
import
org.junit.Test;
public
class
TestAccount {
[...]
@Test(expected=AccountInsufficientFundsException.
class
)
public
void
tranferWithoutEnoughFunds() {
long
balance = 1000;
long
amountToTransfer = 2000;
Account credit =
new
Account(balance);
Account debit =
new
Account();
credit.transfer(debit, amountToTransfer);
}
}
At
b
we declare the method as a test method by annotating it with
@Test
and declare
that it must throw the
AccountInsufficientFundsException
(with the
expected
parameter). Next, we create a new account with a balance of 1000
C
and the amount
to transfer
D
. Then we request a transfer of 2000
E
. As expected, the transfer
method throws an
AccountInsufficientFundsException
. If it didn't,
JU
nit would fail
the test.
B
C
D
E
4.1.7
Enabling code coverage and other metrics
Unit tests tell you, at the push of a button, if everything still works. Furthermore, unit
tests enable you to gather code-coverage metrics (see the next chapter) showing, state-
ment by statement, what code the tests caused to execute and what code the tests did
not touch. You can also use tools to track the progress of passing versus failing tests
from one build to the next. You can also monitor performance and cause a test to fail
if its performance has degraded compared to a previous build.