The general idea of the testrunner is “stolen” from the “chat” program of the Linux ppp package.
Imagine your test target has a tcp/ip port to connect to. So a normal test would consist of sending commands and wait for the expected answers. For a telnet login that might be:
"ogin:" -> "thomas\n"; "assword:" -> "geheim\n";
This is the base of the testrunner syntax. In addition to this, the testrunner needs a timeout. Because, whenever the expected string does not arrive at all, after a while a timeout has to expire.
So this is a complete test script, which you could use to log in into a telnet server:
section login { timeout(10000) : "ogin:" -> "thomas\n"; "assword:" -> "geheim\n"; };
To start the testrunner, copy the above testscript into a file named “test.txt” and call:
testrunner -h myhost.de -p 23 -s test.txt
The testrunner will:
congratulations you did run you first simple test script.
The above test leaks of some very essential parts.
To solve this, we have to add some additional lines:
section login { watch: timeout -> report("timeout -> exit\n"), exit; timeout(10000) : always -> report("Test login begin\n"); "ogin:" -> "thomas\n"; "assword:" -> "geheim\n"; always -> report("Test login successful!\n"); };
This little test is pretty complete. It handles the timeout and it generates a nice test report (to std::cout).
The testrunner syntax consists of lists of “triggers” and “actions. So far we used 3 types of triggers:
And we used 3 types of actions:
The language is recursive. That means, each section may contain sections! So we could extend our test, and use two subsections “login” and “ls”.
section myTest { watch: timeout -> report("timeout -> exit\n"), exit; section login { timeout(10000) : always -> report("Test myTest begin\n"); "ogin:" -> "thomas\n"; "assword:" -> "geheim\n"; } section ls { timeout(2000) : "$" -> "ls\n"; "$" -> none; always -> report("Test login successful!\n); }; };
We have now two sub sections, with different timeouts. The trigger for the timeout is still in the top section. It is possible to do it this way. But we could have additional timeout triggers in the subsection, doing different things.
But be aware: if the timeout triggers inside a sub section, it will only trigger there. The event (timeout) is consumed and will not trigger in the main section!
In the section before, we have a main “section” and do some reporting, when it starts and when it ends. There is a special keyword for this behaviour: “test”. A test is a section, too. But it has additional functionality. One is, that the reporting at the begin and the end is already build in. So this would do exactly the same, as the example before:
test myTest { watch: timeout -> report("timeout -> exit\n"), exit; section login { timeout(10000) : "ogin:" -> "thomas\n"; "assword:" -> "geheim\n"; } section ls { timeout(2000) : "$" -> "ls\n"; "$" -> none; }; };
If you want to generate test reports in xml format to import them in other tools (e.g. PTC) you can add a testnumber into the script, like this:
test login[34567] { watch: timeout -> report("timeout -> exit\n"), exit; timeout(10000) : "ogin:" -> "thomas\n"; "assword:" -> "geheim\n"; };
if you run the testrunner, specifying an xml file:
testrunner -h localhost -p 40000 -s test.txt -x test.xml
you get a xml report:
<ActionList> <SetResult caseID="34567"> <Annotation> </Annotation> <Verdict>Passed</Verdict> </SetResult> </ActionList>
if you start the testrunner in verbose mode, you get texts in different colors.
testrunner -v -h myhost.de -p 23 -s test.txt