Writing good unit tests is just as important as writing high-quality code. Tests should be well written and readable. The quality of the test can be checked with code review and quality rules verification for tests.
When writing test, the developers should think to test behavior not methods. Good test method names should include information about the scenario they verify.
The testing methods should reproduce the use-case scenarios. For example, for a payer that wants to use an online payment platform:
Use-case scenario | Testing implementation | Testing behaviour |
Create new account, balance should be zero | testCreateAccount() testBalance() | shouldHaveZeroBalanceAfterCreation() |
It is possible to make a payment | testBalance() testSum() testRecipient() | ShouldAllowToMakePayments() |
It is possible to receive payments | testSum()
| ShouldAllowToReceivePayments() |
Payments account misuse | testBalance() testAmount() testRecipient() | shouldNotAllowtoMakePaymentsFromEmptyAccount() shouldNotAllowToMakePaymentsForNegativeAmount() shouldNotAllowToUseEmptyRecipientForSendPayment() |
For the above use- cases the corresponding java classes are:
public class Payment { private String recipient; private double balance; private double sum; public String getRecipient() { return recipient; } public void setRecipient(String recipient) { this.recipient = recipient; } public double getBalance() { return balance; } public void setBalance(double balance) { this.balance = balance; } public double getSum() { return sum; } public void setSum(double sum) { this.sum = sum; } } //business logic class public class PaymentBusinessLogic { Payment payment; public PaymentBusinessLogic(Payment payment){ this.payment=payment; } public boolean sendPayment( ){ if(payment.getSum()>0 && payment.getBalance()> 0 && (payment.getBalance()-payment.getSum())>0 && !"".equals(payment.getRecipient())) return true; else return false; } public boolean receivePayment(double sum){ if(sum>0){ payment.setBalance(payment.getBalance()+sum); return true; } else return false; } } //test class import org.junit.Before; import org.junit.After; import org.junit.Test; import static org.junit.Assert.*; public class PaymentAccountTest { Payment payment PaymentBusinessLogic paymentBS ; @Before public void setUp(){ payment = new Payment(); paymentBS = new PaymentBusinessLogic(payment); } @After public void tearUp(){ payment = null; paymentBS = null; } @Test public void shouldHaveZeroBalanceAfterCreation(){ assertEquals(0.0,payment.getBalance(),0.001); } @Test public void ShouldAllowToMakePayments(){ assertTrue(payment.getBalance()>0); assertTrue(payment.getSum()>0); assertTrue((payment.getSum()-payment.getBalance())>0); assertNotEquals("",payment.getRecipient()); } @Test public void ShouldAllowToReceivePayments(){ assertTrue(payment.getSum()>0); } }
Some IDEs provide a functionality to create test methods automatically, for example for a method doSomething() the generated test method will be named testDoSomething(). It is preferable to avoid such solutions because in this case the tests will be focused on method testing and not on class behavior testing.
Complexity should be avoided when creating tests. It is preferable to have no if structure or switch statements or decision making. Otherwise the results of the tests will depend on the quality of the logic of production code and the quality of the logic of test code. Bug fixing will be doubled with the work of finding the bug also in test code. Also the documentation role provided by testing will be lost.
Test should not be over specified – this means they should not verify aspects which are irrelevant to the scenario that is tested.
Because quality assurance teams are put more and more under pressure to reduce the time that need to carry out their testing, automated test tools are used frequently. Selenium for example, is a popular open source tool for web application testing.
Coverage tools are also useful to identify what areas of a project need more attention, but this does not mean that the areas with good coverage should not need more attention.
Code review is also another good way to ensure test quality. This practice consists of a systematic examination of the source code. It improves the quality of the software and the developers’ skills. Code reviews are done in forms of pair programming, informal walkthroughs and formal inspections.