myexpext.pl: verifies output from program tests
expect(FILE,MESSAGE,patlist)
verifies that each pattern in
patlist
matches lines in FILE.
The simplest way of using expect()
is to write a list of patterns
that should be found in the output of the test. Suppose the output
contains:
Output run of program QBFG running on day Sun Apr 8 08:48:23 ART 2001 ..... more lines here Total volume: 34.56 more lines here... Total area: 23.43 more lines here... Total impedance: 46.4 more lines here...
You want to check that figures in lines Total...
are precise
to the first digit. The ouput is in file QBFG.out
and you write a
small perl program like this
#!/usr/bin/perl require 'myexpect.pl'; expect("QBFG.out","Check on ouput of QBFG.out",<<'EOT'); Total volume: 34.5 Total area: 23.4 Total impedance: 4 EOT
final_check();
In the default mode, expect()
takes the first pattern at a time
and starts scanning the file from the beginning, each lie at a time
until it finds a line that matches the pattern. Patterns are the usual
Perl patterns. So that remember to escape asterisks '*
', question
marks '?
', dots and others. You can leave the dot unescaped since
it matches itself, but the pattern is less strict (dot matches any
other character also). Normally, when entering patterns with a here
in document, as in the previous example, you protect the backslash
characters in the pattern list using quotes in the 'EOT'
terminator.
If the pattern is not found an error is reported and the test is
counted as a failure. If a line matching is found, expect()
takes
the folowing pattern and continue scanning the file from the line
following the previous match. If all the patterns are matched, then
the test is counted as a succes. If FILE
can't be opened, then this
is reported separately from error. The final count is reported by a
call to final_check()
.
You can alter this default behavior adding special directives in the pattern list. They are
__REWIND__
#------ contents of file test1.out line at the beginning ... other line ...
matches the following call
expect("test1.out","Check on ouput of test1.out",<<'EOT'); other line __REWIND__ line at the beginning EOT thanks to the presence of the L<__REWIND__> directive.
__BACKWARD__
__FORWARD__
__NO_SKIP__
__SKIP__
__EXACT_MATCH__
.
, *
, etc...
__REGEXP_MATCH__
__SWITCH_FILE__ <file
>file
. File
name is taken absolute if starts with /
otherwise relative to the
current working directory. The working directory is taken from the
first file entered or changed with the __CONFIG_ WD "<dir>"
(directive. Example:
__SWITCH_FILE__ foodir/foofile.out
__CONFIG__
__CONFIG__ var "value" ...
Set configuration variable $var
to value
. Current configuration
variables are
PRE
, SEP
, POST
COMMENT
#>>
.
WD
The double quote delimiter around value
may be changed by any
non-blank character. Examples:
__CONFIG__ PRE "<<" SEP "><" POST ">>" WD "foodir/bardir" COMMENT "#" __CONFIG__ PRE COMMENT |#:|
The last one sets comment start to #:
.
You can embed Perl code blocks in the pattern for checking the result
of the matches themselves. The syntax is {{CONDITION}}
or
{{PATTERN}{CONDITION}}
. In the first form the {{...}}
block is
replaced with (.*)
. If the output line matches, then every
CONDITION
is evaluated and the line matches if every condition
returns true. Inside the condition the special variable $W
takes
the value of the matching string. Example: the following output lines
Total mass: 0.356, max density: 0.48956, min density: 0.001234
match the following pattern lines
Total mass: {{abs($W-0.355)<2e-3}}, max density: {{abs($W-0.4)<0.1}}, min density: {{$W<2e-3}}
In the second form the PATTERN
section allows to specify pattern
which is replaces the block. Example: the output line
Total items: 890.
matches
Total items: {{\d*}{$W<1000}}\.
The syntax of the block may be changed with the __CONFIG__
directive. The corresponding variables are PRE
, SEP
y
<POST>. Possible choices are
#>> Following three examples use matching delimiters (like <>, () or[]) #>> warning: angles (<>) may collide with comparison expressions __CONFIG__ PRE "((" SEP ")(" POST "))" __CONFIG__ PRE "<<" SEP "><" POST ">>" __CONFIG__ PRE "[[" SEP "][" POST "]]" #>> This is very simple __CONFIG__ PRE "{" SEP "," POST "}" #>> Another simple one __CONFIG__ PRE "<" SEP "|" POST "}"
In order to avoid collision you can increase the delimiter levels, e.g.
#>> Very paranoid __CONFIG__ PRE "{{{{" SEP "}}{{" POST "}}}}" #>> Combines with colon __CONFIG__ PRE "<<:" SEP ":><:" POST ":>>"
Sometimes it is useful to divide tests into sections. Start sections
with begin_section("section name")
, and end with end_section()
.
All enclosed calls to expect()
are assumed to be in the same
logical section of tests and a summary is reported for that section.
Example:
begin_section("Navier stokes tests"); expect("NS/output1.txt","NS Test 1","NS Test 1 OK"); expect("NS/output1.txt","NS Test 2","NS Test 2 OK"); expect("NS/output1.txt","NS Test 3","NS Test 3 OK"); end_section();
begin_section("Electro-magnetic tests"); expect("EM/output1.txt","EM Test 1","EM Test 1 OK"); expect("EM/output1.txt","EM Test 2","EM Test 2 OK"); expect("EM/output1.txt","EM Test 3","EM Test 3 OK"); expect("EM/output1.txt","EM Test 4","EM Test 4 OK"); end_section();
Mario A. Storti <mstorti@intec.unl.edu.ar>