As you may recall the first part of this blog was addressing the challenges facing automated testers and companies. The second part provided an overview to the solution. Finally, in this blog we are presenting a couple of examples to demonstrate how we write our acceptance tests. The tests have been written in given-when-then style to aid readability and to describe behaviour of the object under test. Anyone who is familiar with Cucumber framework will recognise this notation. The ‘given’ keyword is for providing the set of preconditions, ‘when’ is for user or system actions, ‘then’ is for verifying the post-conditions.
There are two fixtures (referred as ‘fxticket’ and ‘trading’ in the test) used to able to run this test as well as a fixture factory which creates instance of these fixtures. Let’s have a look at the first example line by line:
(1) it("provides a confirmation message after spot trade is successful", function() { (2) given("fxticket.opened = true"); (3) and("fxticket.model.spot.setup.amount.value = '1000'"); (4) and("fxticket.model.currencyPair.value = 'USDGBP'"); (5) and("fxticket.model.spot.setup.tradeLeg.dealtCurrency.value = 'USD'"); (6) when("fxticket.model.getQuote() => ‘invoked’"); (7) and("trading.eventReceived => 'OpenAck'"); (8) and("trading.eventReceived => 'PriceUpdate'"); (9) and("ticket.model.spot.execution.executeSell() => ’invoked’"); (10) and("trading.eventReceived => 'TradeConfirmed'"); (11) then("fxticket.model.state = 'TradeConfirmed'"); (12) and(fxticket.model.spot.confirmationMessage = ‘You have sold 1000 USD against GBP'"); });
The first line describes what the test is about in plain English with a declaration of a JavaScript function for the test body:
(1) it("provides a confirmation message after spot trade is successful", function() {
The second line is the first given statement where the ‘fxticket’ object (ViewModel in the diagram in part II) is created by the fixture factory.
(2) given("fxticket.opened = true");
The third, fourth and fifth lines are about setting the preconditions. For example we need an amount of money, and a currency to be able to trade.
The sixth line is for user action; instead of clicking ‘Get Quote’ button on the user interface we are calling the function which is invoked by clicking that button.
(6) when("fxticket.model.getQuote() => ‘invoked’");
The seventh and eighth lines are for backend functionality. Our second fixture ‘trading’ mock object is simulating sending messages from the backend. This mock object represents ‘Model’ in the diagram part II. The fxticket object needs to get the prices so that it can display buy and sell buttons for user to trade.
The ninth line is for again user action, clicking buy button (the test again calls the function linked to that button).
The tenth line is to simulate backend sending the ‘TradeConfirmed’ message to the fxticket.
The eleventh and twelfth lines are verifying the post-conditions. In other words these last two lines are the ones testing the actual result against expected results. We expect that ticket state should be ‘TradeConfirmed’ and also we expect the confirmation message reflecting the user actions.
(11) then("fxticket.model.state = 'TradeConfirmed'"); (12) and(fxticket.model.spot.confirmationMessage = ‘You have sold 1000 USD against GBP'");
So far we have tested the interaction between ‘Model’ and the ‘ViewModel’. What about testing the View? If the buttons are not bound to the corresponding functions, then the tests will happily pass but clicking buttons will do nothing. Similarly, the developers have to bind all the other controls such as input boxes and drop down lists in the View to the objects’ properties in the ViewModel. The example for testing function binding is below:
(1) it("calls getQuote function when the Quote button is clicked", function(){ (2) given("fxticket.view.new = true"); (3) and("fxticket.model.getQuote.invocationCount = 0"); (4) when("fxticket.view.(.buttonQuote).clicked => true"); (5) then("fxticket.model.getQuote.invocationCount = 1"); });
The test simply checks the click count before and after the click event is simulated. The ‘view’ is another fixture which represents ‘View’ in the diagram.
To run these tests, we have enhanced Js Test Driver and also adapted Jasmine framework to write the tests in the style shown above.
In this blog we have pointed out the challenges facing institutions, recommended a design pattern which is integral to the SUT and finally we have demonstrated how to implement this design pattern by solid examples.
Happy (automated) testing everyone!