Consider you need to write the software for a vending machine.
It is possible to insert coins and press buttons for bananas and apples. If enough money is input, a banana or an apple will be dispensed. There is a cancel button that cancels a transaction. All money that has been input so far will be returned.
There is only one use case Buy Fruit, but it has a lot of alternative scenarios because of all the possible ways to press the various buttons and to input coins.
Use Case: Buy Fruit
The project description requires you to develop test cases for functional tests from use cases. First, you should develop the tables that define the input sets and then tables that define the test cases themselves, in the form described in the note on testing by Peter Sestoft, and then you should implement the test cases in JUnit.
Here is the first table for our vending machine use case defining the input sets with their input properties. Note that the table contains many different input sets corresponding closely to the various alternative scenarios of the use case.
Input data set | Input property |
A | Exact coins; enough fruits; first coins, then fruit selection |
B | Exact coins; enough fruits; first fruit selection, then coins |
C | Exact coins; not enough fruits; first coins, then fruit selection, then cancel |
D | Exact coins; not enough fruits; first fruit selection, then coins, then cancel |
E | More coins; enough fruits; first coins, then fruit selection |
F | More coins; enough fruits; first fruit selection, then coins |
G | More coins; not enough fruits; first coins, then fruit selection, then cancel |
H | More coins; not enough fruits; first fruit selection, then coins, then cancel |
I | Less coins; enough fruits; first coins, then fruit selection |
J | Less coins; enough fruits; first fruit selection, then coins |
K | Less coins; not enough fruits; first coins, then fruit selection, then cancel |
L | Less coins; not enough fruits; first fruit selection, then coins, then cancel |
Here is the second table describing the actual test cases based on the input set definition from the previous table, i.e. the current input that belongs to the input set and the expected output..
Input data set | Contents | Expected Output |
A | 1,2; apple | apple dispensed |
B | Apple; 1,2 | apple dispensed |
C | 1,2; apple; cancel | no fruit dispensed; returned DKK 3 |
D | Apple; 1,2; cancel | no fruit dispensed; returned DKK 3 |
E | 5, apple | apple dispensed; returned DKK 2 |
F | Apple; 5 | apple dispensed; returned DKK 2 |
G | 5, apple; cancel | no fruit dispensed; returned DKK 5 |
H | Apple; 5; cancel | no fruit dispensed; returned DKK 5 |
I | 5; banana | no fruit dispensed; current money shows 5 |
J | Banana; 5,1 | no fruit dispensed; current money shows 6 |
K | 5,1; banana; cancel | no fruit dispensed; returned DKK 6 |
L | Banana; 5,1;cancel | no fruit dispensed; returned DKK 6 |
One way of running the tests is to run them manually, i.e. to start up the application and then, e.g. input coins 1 and 2 and then press apple. If the output of the machine is the same as the expected output, then the test was executed successfully, else unsuccessfully.
Manual tests are very costly and cannot be executed in their entirety very often. Therefore, one would like to execute these tests automatically, so that whenever one changes the code of the application one can run the tests again to see if one has broken some functionality or not. One way to do this (and the way you should be doing this in your project) is to use a layered architecture with a thin presentation layer and an application layer containing all the functionality. This can be called testing the system under the UI. In this case, each test case from the second table needs to have its own test method. Within a layered architecture, all the interactions with the system (e.g. button presses, mouse movements, etc.) are translated by the presentation layer to messages to the application layer (e.g. input(money), selectFruit(fruit), and cancel()). These messages can be used in JUnit test methods to simulate the user interaction. The following is an example of how the first 4 test cases of 12 test cases of second table can be implemented using JUnit.
public void testInputDataSetA() { VendingMachine m = new VendingMachine(10, 10); m.input(1); m.input(2); assertEquals(3, m.getCurrentMoney()); m.selectFruit(Fruit.APPLE); assertEquals(Fruit.APPLE, m.getDispensedItem()); } public void testInputDataSetB() { VendingMachine m = new VendingMachine(10, 10); m.selectFruit(Fruit.APPLE); m.input(1); m.input(2); assertEquals(0, m.getCurrentMoney()); assertEquals(Fruit.APPLE, m.getDispensedItem()); } public void testInputDataSetC() { VendingMachine m = new VendingMachine(0, 0); m.input(1); m.input(2); assertEquals(3, m.getCurrentMoney()); m.selectFruit(Fruit.APPLE); assertEquals(null, m.getDispensedItem()); m.cancel(); assertEquals(null, m.getDispensedItem()); assertEquals(3, m.getRest()); } public void testInputDataSetD() { VendingMachine m = new VendingMachine(0, 0); m.selectFruit(Fruit.APPLE); m.input(1); m.input(2); assertEquals(3, m.getCurrentMoney()); m.cancel(); assertEquals(null, m.getDispensedItem()); assertEquals(3, m.getRest()) } ...
![]()
![]()
![]()
Next: About this document ... Up: More information on the Previous: Use case template Hubert Baumeister 2010-04-12