HTTPTest Documentation
- NAME
- Purpose
- SCRIPT CATEGORIES
- PREREQUISITES
- COREQUISITES
- OSNAMES
- Description
- Usage
- Battery File
- Element List
- Example Tests
- Example msg Tests
- The Include Path
- Outstanding Issues
NAME
HTTPtest.pl
Purpose
HTTPtest is a generalized HTTP request test program. It allows for efficient regressions testing of any HTTP-based server.
Warning: This program is under construction, so the documentation is subject to change.
SCRIPT CATEGORIES
HTTP - suggested
PREREQUISITES
This script depends on both the strict
and vars
pragmas. The script also uses
the FindBin
LWP::UserAgent
, HTTP::Cookies
, URI::Escape
, XML::Parser
,
Getopt::Std
, and File::Spec
modules.
COREQUISITES
If the Time::HiRes
module is available, it is used to generate higher-resolution
timings on the time subtest and the script timing.
OSNAMES
any. Tested on MSWin32 and Linux.
Description
The HTTPtest program uses a battery file to describe a series of tests to perform using the HTTP protocol. In general, a set of tests are aimed at a single server or service. Like HTTP itself, the tests are defined in terms of a request and a response. The battery file describes the tests in an XML-based format, described below.
HTTPtest reads each test in the battery file, performs the specified request, and evaluates the response based on the criteria described in the test. If all criteria are met, the test is successful. Otherwise, the test fails.
Usage
HTTPtest is executed as follows:
perl HTTPtest.pl [-vwqVl] [-o logfile] [-I incpath] [-f suite] [-jJ cjar] [name=value ...] test.files ...
Where: -v verbose output -w normal output, default -q quiet output -V print version information -l log results to HTTPtest.log -o send results to specified logfile -I semicolon-separated path to check for include files -f supply a test suite filename -j use a temporary cookie jar -J use the cookie jar file 'cjar'
name=value pairs override parameters in the test files
test.files is a list of files that contain the tests to run
If run with a bad option or no test files, the above message is printed.
Battery File
The battery file contains a battery
root element. The battery
may
contain include
elements to include information from other files,
param
elements which factor out reused parameters, and test
elements
which describe the tests to run.
Each test
consist of a request
, which describes the HTTP request, and
a response
which describes the criteria for evaluating the HTTP response.
A request
specifies the URL to call including any query parameters, an
HTTP method such as GET or POST, and an optional request body.
A response
contains a series of subtests which include the ability to test:
- status
- The response status code for the response. Reasonable values include 200 and 404.
- header
- Tests for the existence or value of particular MIME-headers in the response. Useful for verifying redirections and testing returned cookies.
- content
- Evaluation subtest for the content of response.
- time
- Compare the response time of the URL request against a minimum and maximum timespan in seconds.
- code
- Execute arbitrary Perl code on the response to evaluate the response.
- msg
- This pseudo-subtest displays a message to the user and optionally aborts the current battery or program run.
- filter
- This pseudo-subtest executes Perl code specifically designed to perform some form of filtering on the response. Always succeeds.
- call
-
This pseudo-subtest executes a list of subtests defined using the
subtest-def
element.
By default all of the evaluations in the response
must succeed in order
for the test
to succeed. However, five other elements are supported to
allow for arbitrary logical combinations of the evaluations.
- and
-
All of the subtests contained in the
and
element must succeed in order for theand
to succeed. Any unsuccessful evaluation causes theand
to fail without executing any remaining children. - and-all
-
All of the subtests contained in the
and-all
element must succeed in order for theand-all
to succeed. Unlike theand
subtest, all children are executed regardless of the success or failure of any child. - or
-
One of the subtests contained in the
or
element must succeed in order for theor
to succeed. Any successful evaluation causes theor
to succeed without executing any remaining children. - or-all
-
One of the subtests contained in the
or-all
element must succeed in order for theor-all
to succeed. Unlike theor
subtest, all children are executed regardless of the success or failure of any child. - not
-
The sense of the subtest contained in the
not
element is reversed, so that a failure becomes a success.
Element List
and
The and
element is used to combine a set of subtests in a logical and
relationship. The and
element can contain any of the subtest elements or
the logical elements. The and
element has one optional attribute label
which is a displayable description of the set of subtests contained in the
and
. It may be used in logging and failure reporting.
HTTPtest evaluates the response based on each of the children of the
and
in turn. When a subtest fails, no more children are tested and the
and
evaluation fails.
and-all
The and-all
element is used to combine a set of subtests in a logical and
relationship. The and-all
element can contain any of the subtest elements or
the logical elements. The and-all
element has one optional attribute label
which is a displayable description of the set of subtests contained in the
and-all
. It may be used in logging and failure reporting.
HTTPtest evaluates the response based on each of the children of the
and-all
in turn. Unlike the and
subtest, all of the children are
evaluated regardless of the success or failure of any given child.
auth
The auth
element supplies an optional user id and password for HTTP
authentication of a request. Currently only supports Basic authentication.
The auth
element has two reuired attributes user and password. These
attributes have the obvious values.
battery
The battery
is the root element of the battery file. It can contain zero
or more param
elements, followed by zero or more codelib
elements, followed
by zero or more test
elements. In addition, include
elements may occur
anywhere in the battery
element.
The battery
has one required attribute, label which is a short displayable
description of the test set.
body
The body
element supplies the content for an HTTP request. It is currently
only supported for the POST HTTP method. The content of this element is
used as the body of the request by HTTPtest. Since this content resides in
an XML document, it may be necessary to wrap the content in a CDATA section
in order for the file to remain well-formed.
The body
element has two optional attributes. The type
attribute specifies
the MIME type of the content. By default, the content type is
application/x-www-form-urlencoded, which is the type used by browsers on HTML
forms. The encode
attribute specifies whether the content needs to be
URL-encoded. The default value is no. If you have already encoded the data, the
correct answer is no.
call
The call
element executes the list of subtests that have been defined in
an earlier subtest_def
element. This element allows a group of subtests to
be factored out of a response
and reused in other response
s.
code
The code
element specifies a piece of Perl code to execute in order to evaluate
the HTTP response. The code
element has one optional attribute. The label
attribute provides a displayable description of this element that can be used in
error reporting and logging.
The content of this element is raw Perl code. Since Perl code can easily violate the well-formedness criteria, it is recommended that the whole content of this element be placed in a CDATA section.
The Perl code is executed with a set of variables that are accessible. These variables can be used to determine how to perform the tests or communicate with other pieces of code. The variables of interest are:
- $resp
-
This is a reference to an HTTP::Response object containing the current response. This
is a
my
variable, and therefore only available directly inside thecode
element. - $label
-
This string is the value of the label attribute for the current test. This is a
my
variable, and therefore only available directly inside thecode
element. - %Params
-
This is a global hash matching all of the parameter names to their current values. The
Perl code is allowed to modify values in this hash to pass data to other tests.
Direct access to this hash is deprecated. Parameters should be accessed through
the following methods:
param()
-
This is the get/set function for parameters. When called with one argument,
the value of the parameter with the supplied name is returned. If the function
is called with two arguments, the parameter named by the first argument is set
to the value of the second argument. For example,
my $server = param( 'server' ); param( 'server' => 'www.example.com' );
param_exists()
- This function returns a boolean value that specifies whether the named parameter exists. It has one argument, the name of the parameter to test.
- $parser
- This is a global reference to an XML::Parser object configured with the Objects style. This object may be used to parse XML from the response to simplify testing. See the XMLdata.pm library file for tools that can manipulate this structure.
response_time()
- This function returns the time in seconds for the HTTPresponse to return.
The Perl code should return a list of scalars. The first item in the list is the only required item. It is true if the test was successful, and false otherwise. The second item in the list is a short string describing the result of the test. The third and final item is a long string giving a verbose description of the result of the test. If either the second or third items is missing, a generic answer is used in each case.
codelib
The codelib
element declares Perl code that is to be compiled into the test script
for use in later tests. This is a good place to use modules or define routines that
are needed by code
subtest defined later in the file. The content of this element
is raw Perl code. Since Perl code can easily violate the well-formedness criteria, it
is recommended that the whole content of this element be placed in a CDATA section.
The codelib
element has one required attribute and one optional attribute. The label
attribute provides a displayable description of this element that can be used in error
reporting and logging. The optional id attribute is used to uniquely identify a
codelib
. This helps HTTPtest to recognize if a codelib
is encountered more than
once. (For example through the use of include
elements.) If a codelib
id is
encountered a second time, that codelib
is not evaluated the second or subsequent times.
If a codelib
does not contain an id and it is encountered more than once, it is
evaluated each time it is encountered.
content
The content
element specifies subtest for the body of the HTTP response.
The content
element has one optional attribute. If the match attribute is missing
or has a value of exact, the body of the HTTP response must match the content of the
content
element exactly. If the match attribute has a value of regexp, the
content of the element is treated as a regular expression to be matched against the
HTTP response content. If the match attribute has a value of substr, the
content of the element is expected to exist somewhere in the response.
WARNING: There is a limit to the size of a regular expression in Perl. It is better to break a complicated test into several smaller tests.
filter
The filter
element is a special subset of the functionality of the code
element. The filter
element has two optional attributes. The label
attribute supplies a displayable label for this filter. The class attribute
specifies which class of filter we are specifying. If the class attribute
is missing or if it has the value content, the filter modifies the content
of the response which is available in the variable $_
. If the class
attribute has the value response, the filter can affect any portion of the
response. The response is available in the variable $resp
as an
HTTP::Response
object.
header
The header
element specifies a MIME header in either a request
or a
response
. It has three attributes that are treated slightly differently
depending on whether the element is contained in a request
or a response
.
In both cases, the name attribute is required and supplies the name of
the MIME header of interest.
The value attribute specifies the value of that MIME header. In the case of
a request
, this attribute is required and specifies the literal text of the
value of the header. In the case of a response
, the value attribute is
interpreted as described by the match attribute.
The match attribute is specifies the interpretation of the value attribute
on a header
in a response
. The default value of the match attribute
is exact. The valid values for match are
- exact
-
The value of the MIME header must exactly match the value of the
header
. - regexp
-
The value of the
header
is treated as a regular expression to match the value of the specified MIME header. - exist
- The MIME header must exist in the HTTP response. The value attribute is ignored.
- nonexist
- The MIME header must not exist in the HTTP response. The value attribute is ignored.
include
The include
element allows portions of a battery
to be factored into separate
files. This supports sharing of information between battery files and can simplify
maintenance of test sets.
The include
element has one required attribute (file) and two optional attributes
(label and parse). The file attribute specifies the file to be included.
HTTPtest looks for the file as it is specified, relative to the current directory, first.
If the file is not found and the filename is not an absolute path, HTTPtest then attempts
to find the file by appending the file attribute to each path in the include path.
label attribute is a displayable description only used for logging and error reporting.
The parse attribute tells HTTPtest how to treat the data from the included file. If
the parse attribute is missing or if its value is xml, the contents of the included
file are parsed and all children of the root element replace the include
element. If the
value of the parse attribute is text, the contents of the file are treated as a text
node that replaces the include
element. Since this data is not handled directly by the
XML parser, there is no need to use character entities such as <
and &
.
One extra constraint on the include
is that the test set file should still be a valid
document after the include
elements are replaced by the content of their files.
inclusion
The inclusion
element is the root element of any included xml-parsed file. Its purpose
is to provide a well-formed XML document for the included file.
msg
The msg
element is used to report unusual problems to the user and optionally to
abort a test run. The msg
element has two optional attributes and contains text
to display. The print attribute determines when the message is printed. Possible
values are:
- always
-
Always print the message when the
msg
element is encountered. - normal
-
Print the message when the
msg
element is encountered and the -w or -v switches are active. This is the default printing behavior. - verbose
-
Print the message when the
msg
element is encountered and the -v switch is active.
The action attribute determines the effect of this pseudo-subtest on the test in progress. The possible values are:
- success
-
Treat the
msg
element as a successful subtest. - fail
-
Treat the
msg
element as a failed subtest. This is the default action. - stop
- Stop the current battery, but continue processing any battery files remaining on the command line.
- exit
- Exit the HTTPtest.pl script, altogether.
The msg
element is best used as part of an or
or and
condition. This
allows an earlier subtest to determine whether or not the msg
element is
processed at all.
not
The not
element is used to logically invert the outcome of a subtest.
The not
element can contain any one of the subtest elements or the logical elements.
The not
element has one optional attribute label which is a displayable description.
It may be used in logging and failure reporting.
option
The option
element configures default processing options for HTTPtest. All of the
options configurable through the option
element are also available through command
line parameters. The command line parameters override whatever option
s are in the test
set file. All of the option
elements must come before any other elements in
the battery
.
The option
element has two required attributes, name and value. The value
attributes will be interpreted differently depending on option they are applied to. The
allowable options are:
- incpath
- The value attribute for this option is a semicolon-separated list of paths to use in finding include files. Unlike the other options, the command line switch does not override this option. Instead the paths supplied by the -I switch are prepended to the include path.
- logging
- The value for this option is either yes (enable logging) or no (disable logging). This is equivalent to the -l switch.
- logfile
- The value for this option is the name of a file into which the logging information is written. This is equivalent to the -o switch.
- msgs
- The value for this option is either an empty string (normal output), quiet (quiet mode), or verbose (verbose mode). This modes are equivalent to the -w, -q, and -v switches.
- cookiejar
-
The value for this option is either an empty string (temporary cookie jar) or the name of a
file to store the cookie jar. If this option is supplied, HTTPtest retains cookies across all
of the
test
s in thebattery
. If no name is specified, the cookie jar will be empty when the script begins and all cookies wil be discarded at exit. This usage is equivalent to the -j switch. If a filename is specified, that file is read to initialize the cookie jar if the file exists. When the program prepares to exit, the current state of the cookie jar is saved to the specified file. This usage is equivalent to the -J switch.
or
The or
element is used to combine a set of subtests in a logical or
relationship. The or
element can contain any of the subtest elements or the
logical elements. The or
element has one optional attribute label which
is a displayable description of the set of subtests contained in the or
. It
may be used in logging and failure reporting.
HTTPtest evaluates the response based on each of the children of the
or
in turn. When an subtest succeeds, no more children are tested and the
or
subtest succeeds.
or-all
The or-all
element is used to combine a set of subtests in a logical or
relationship. The or-all
element can contain any of the subtest elements or
the logical elements. The or-all
element has one optional attribute label
which is a displayable description of the set of subtests contained in the
or-all
. It may be used in logging and failure reporting.
HTTPtest evaluates the response based on each of the children of the
or-all
in turn. Unlike the or
subtest, all of the children are evaluated
regardless of the success or failure of any given child.
param
The param
element is an empty element which gives a name to a piece of text
which is expected to be reused many times in the test set. A good example would
be the name of the server undergoing test. For example,
<param name="server" value="testserver.telescan.com"/>
Using a param
in this way simplifies pointing the test to a new server. The
param
is then referenced in any text or attribute in the test set file using
the form {{server}}.
In addition, the value of a param
may be changed from the HTTPtest command
line using the syntax: name=value. To run this battery
on the server
live.telescan.com, you would add server=live.telescan.com to the command
line before the name of the battery file.
The param
element has two required attributes. The name attribute specifies
the name by which this parameter is referenced. The value attribute specifies
the replacement text.
request
The request
element describes a complete HTTP request to be used in the test.
The request
has a required attribute, url, which specifies the URL to
which the request is made. This URL may contain a query string. Because of the
requirements of XML, this query string will need to be modified if it contains
the ampersand character &. The ampersand must be replaced by ``&''
in the url attribute. This string will be converted back to its proper form
before it is requested.
The request
element also has an optional method attribute, which defaults
to GET. Currently, HTTPtest supports values of GET and POST for this
attribute. At some point, the program may be extended to support all of the HTTP
request methods.
The request
element can contain zero or more header
elements followed by
zero or more body
elements. In addition, include
elements may optionally
occur anywhere in the request
content. The header
elements allow you to
specify MIME headers to apply to the request. The body
element is used to
contain the content of a POST request. At this time, only one body
element
is supported in a request. However, at a future date, this will be extended to
multiple body
elements for support of the multipart Content types.
response
The response
element defines the subtests to execute for the current test.
After the HTTP request has been made and an HTTP response is returned,
HTTPtest walks the children of the response
element and attempts to verify
the response.
The response
element has one optional attribute. The label attribute defines
a displayable description of this response set that may be used in error messages
or logging.
The content of the response
response element must include one or more of the
following elements:
- status
- header
- time
- content
- code
- msg
- filter
- and
- or
- and-all
- or-all
- not
- call
The response
element may also contain include
elements. After the
include
is resolved, the only child elements allowed in a response
are
the ones listed above.
session
The session
element is a deprecated synonym for test-set
.
skip
The skip
element declares a Perl expression that can determine if the containing
test
test should not be executed. This expression can be used to test for
command line options, system resources, current date or time, or anything else
that might cause the running of the test to be a bad idea. The skip
element
has a required attribute if that specifies the Perl expression that determines
the need to skip the test. If the expression evaluates to a true value, the
test is skipped, otherwise the test is performed as normal. The skip
element
also supports an optional label attribute.
If the skip test succeeds and HTTPtest is running in verbose mode, the contents
of the skip
element are displayed as an explanation for the test being
skipped. If the content is empty, the label
is used. If there is no label,
the actual test expression is displayed.
Skipped tests are reported separately from successful or failed tests. This allows you to count them whichever way makes the most sense.
status
The status
element specifies values to match for the HTTP Response status
code. The element has one required attribute and one optional attribute. The
required code attribute specifies a value to use in the comparison. This
value is interpreted based on the value of the optional match attribute.
If the value of the match attribute is exact or the attribute is missing,
the code must match the response exactly. If the value of the match attribute
is regexp, the value of code is treated as a regular expression.
subtest_def
The subtest_def
element supports naming a group of subtests so that they
may be used from multiple response
s.
test
The test
element describes a particular test to be run. The test
contains only
zero or more skip
elements, a request
, and a response
. The test
also
has one required attribute label, which is a displayable description of the
test which is used in failure reporting.
testset
The testset
element is a deprecated synonym for battery
.
test-set
The test-set
element groups a set of test
elements together as a single
group.
time
The time
element specifies the expected time limits for an HTTP response. The
time
element has two optional attributes, min and max. If the min
attribute is specified, the test fails if the HTTP response returns in less than
that many seconds. If the max attribute is specified, the test fails if the HTTP
response returns in more than that many seconds. If the value of min is greater
than the value of max, the test will always fail.
Example Tests
The following is a very simple test. We are just testing to see if the page is returned in a reasonable amount of time. In this case, the test is successful if we recieve a status code of 200 (OK) and if the page returns in no more than 10 seconds.
<test label="Did it come back"> <request url="http://www.tscn.com/" method="GET"/> <response> <status code="200"/> <time max="10"/> </response> </test>
To extend this test a little, we will check to see if the returned page is an HTML document. In this case, I am taking advantage of the fact that I know the page has the HTML tags in all upper case.
<test label="Respond in HTML"> <request url="http://www.tscn.com/" method="GET"/> <response> <status code="200"/> <time max="10"/> <header name="Content-Type" value="text/html"/> <content match="regexp"><![CDATA[<HTML>.*</HTML>]]> </response> </test>
Now we will check to see if we are getting the page (or, at least the title) that we think we are getting back.
<test label="Old WSC root page"> <request url="http://www.tscn.com/" method="GET"/> <response> <status code="200"/> <time max="10"/> <header name="Content-Type" value="text/html"/> <content match="regexp"><![CDATA[<HTML>.*</HTML>]]> <content match="regexp"><![CDATA[ <TITLE>Wall Street City - The Investor's Supersite on the Web</TITLE> ]]> </response> </test>
Example msg Tests
The msg
element is a little more subtle than most of the other subtests. It
is almost always used in conjunction with the or
or and
elements. The msg
element serves two purposes: display a message alerting the user to an unusual condition,
abort a battery in case an exceptional situation is detected.
In order to report an exceptional condition that has been recognized in the test, use
the and
element. For example,
<test label="Part of a long sequence of tests"> <request url="http://www.test.com/" method="GET"/> <response> <status code="200"/> <and> <content match="regexp">This is exceptional</content> <msg action="stop" print="always"> WARNING: Exceptional condition detected. Aborting test set... </msg> </and> </response> </test>
If, on the other hand, you want to report the failure of a critical subtest on
that would affect any tests that follow, use the or
element. For example,
<test label="First test in a long set"> <request url="http://www.test.com/" method="GET"/> <response> <status code="200"/> <or> <content match="regexp">This MUST be found</content> <msg action="stop" print="always"> WARNING: Required content missing. Aborting test set... </msg> </or> </response> </test>
The Include Path
HTTPtest will search the include path starting with the paths specified in the -I
command line switch, in the order specified. Next, any paths specified in option
elements in the order they are specified in the test set file. Finally, as a last resort,
the subdirectory lib under the directory from which HTTPtest was run is checked.
Outstanding Issues
The following are issues still outstanding:
-
The
codelib
functionality has not been extensively tested. -
The
code
functionality has not been extensively tested. In addition, it's functionality may change slightly in the near future. - Need to clean up the reporting and logging subsystems.
-
I do not like the name of the
inclusion
element. It is subject to change. - The -f suite command line option which names a test suite file containing the names of battery files. Need to check handling of params in this case.
-
Need to support multiple
body
tags inside of arequest
. Also need to check definition of boundaries and multiple levels of nesting. - Need to look into other HTTP request methods to verify that the script can support them and add them to the DTD and input function.
-
Once I figure out what a
test-set
is, I need to implement it. Need to extend thetest-set
s so they are more than just a dumb container. -
Need to add functionality similar to
param
forinclude
elements. This new child ofinclude
would declare replaceable parameters that would be replaced in the body of the included file. These templatized includes could simplify creation and maintenance of similar tests. -
I need to add tutorial docs for the use of
code
andcodelib
, especially the new id feature ofcodelib
.