module SimpleWeather { type record weatherRequest { charstring location, charstring date, charstring kind } template weatherRequest ParisWeekendWeatherRequest := { location := "Paris", date := "15/06/2006", kind := "actual" } type record weatherResponse { charstring location, charstring date, charstring kind, integer temperature, integer windVelocity, charstring conditions } template weatherResponse ParisResponse := { location := "Paris", date := "15/06/2006", kind := "actual", temperature := (15..30), windVelocity := (0..20), conditions := "sunny" } type port weatherPort message { in weatherResponse; out weatherRequest; } type component MTCType { port weatherPort weatherOffice; } testcase testWeather() runs on MTCType { weatherOffice.send(ParisWeekendWeatherRequest); alt { [] weatherOffice.receive(ParisResponse) { setverdict(pass) } [] weatherOffice.receive { setverdict(fail) } } } control { execute (testWeather()) } }
<weatherRequest kind="actual"> <weatherStation location= "Paris"/> <date day="15" month="06" year="2006"/> </weatherRequest>
template weatherResponse ParisResponse := { location := "Paris", date := "15/06/2006", kind := "actual", temperature := (15..30), windVelocity := (0..20), conditions := "sunny" }
weatherOffice.receive(ParisResponse); setverdict(pass)
TTCN-3 achieves yet another separation of concern. It separates behavior from the conditions governing behavior. TTCN-3 enables to specify test behavior as trees of alternate behaviors. The conditions governing this behavior are specified using TTCN-3 templates that in essence act as traditional if-then-else statements but in a very concise way. This behavior presentation approach enables a clear overview quality of the test behavior, a quality rarely found in traditional programming languages.
In our weather service example, we use an alternative to specify the possibility to
receive an unexpected and unspecified response message in which case we could
decide that the test case failed.
Verdicts are usually located in the leafs of the behavior tree.
alt { [] weatherOffice.receive(ParisResponse) { setverdict(pass) } [] weatherOffice.receive { setverdict(fail) } }
One of TTCN-3's major feature is parametrization. This feature enables to maximize the principle of re-usability.
Parametric templates
templates can be assembled using other templates.
template myTypeA myRomeLocation := { city := "Roma", country := "italy" } template myTypeB myGenericWeatherRequest (myTypeA theLocationTemplate) := { location := theLocationTemplate, request := "road conditions" }
the above template myGenericWeatherRequest can be actualized when used in a TTCN-3 send or receive operation:
weatherOffice.send(myGenericWeatherRequest(myRomeLocation)); ...
Parametric test cases
templates can be passed to a test case or function as parameters and can
be used in any of the TTCN-3 send or receive operation.
testcase testWeather(myTypeB theWeatherRequest, someResponseType theExpectedResponse) runs on MTCType { weatherOffice.send(theWeatherRequest); alt { [] weatherOffice.receive(theExpectedResponse) { setverdict(pass) } [] weatherOffice.receive { setverdict(fail) } } }
The above test case can be executed with actual values as follows:
execute(testWeather(myGenericWeatherRequest(myRomeLocation), myExectedResponse)); ...
and this test case can be re-used for a variety of similare tests like in our case checking the weather in different locations:
execute(testWeather(myGenericWeatherRequest(myParisLocation), parisExpectedResponse)); ...