NAME
WWW::Webrobot::pod::Testplan - How to write a test plan for webrobot
SYNOPSIS
<?xml version="1.0" encoding="iso-8859-1"?>
<plan>
<request>
<method value='GET'/>
<url value='http://google.de/'/>
</request>
<include file='a-file-name'>
<parm name='application' value='${application}'/>
<parm name='username' value='koester'/>
</include>
<plan action="shuffle">
<request>
<method value='GET'/>
<url value='http://google.de/'/>
<description value='Visit Google'/>
<assert>
<and>
<status value='200'/>
<regex value='Erweiterte Suche'/>
<not>
<regex value='Sprachtools'/>
</not>
<timeout value='2.5'/>
</and>
</assert>
</request>
<request>
<method value='POST'/>
<url value='http://yourserver.com'/>
<data>
<parm name='username' value='me'/>
<parm name='password' value='secret'/>
</data>
<description value='Login at yourserver.com'/>
</request>
</plan>
<cookies value='clear'/>
<referrer value='on'/>
<request>
<method value='GET'/>
<url value='http://google.de/'/>
</request>
</plan>
DESCRIPTION
A test plan is a list of elements. An element itself may be a request
, a (sub) test plan
, an include
or a cookie
control command.
While processing a plan will be flattened and all requests are executed in sequence. This ist the top level structure of a test plan:
<?xml version="1.0" encoding="iso-8859-1"?>
<plan>
... request ...
... include ...
... (sub)plan ...
</plan>
Tag <plan>
Besides structure the main purpose of this tag is to shuffle its containing requests with a pseudo random generator.
Attributes:
action='shuffle'
Tag <include>
This tag includes another test plan.
Attributes:
file='filename'
<include> tags may define names local to the file included. This is a way to parameterise a files content. See section Names (Variables).
Example:
<include file='a file name'>
<parm name='application' value='${application}'/>
<parm name='username' value='mary'/>
<parm name='useragent' value='marysagent'/>
</include>
Tag <cookies>
By default cookies are on
. You can switch cookies off
or you can just clear
the cookies. While clear
will clear all cookies, clear_temporary
will clear only temporary cookies. A browser must clear all temporary cookies when it will be closed.
Example:
<cookies value='on'/>
<cookies value='off'/>
<cookies value='clear'/>
<cookies value='clear_temporary'/>
Tag <referrer>
By default no http referrers will be sent. You can switch this behaviour on or off or you can just clear the referrer. If you want referrers to be switched on, then place the <referrer> tag at least before the request that must be referred to.
Example:
<referrer value='on'/>
<referrer value='off'/>
<referrer value='clear'/>
Tag <config>
Read more config variables. These variables must be in a name/value format (similar to java.util.Properties). The name/value pairs may be read from a file (use attribute "filename") or from a program (use attribute "script").
Example:
<config filename='example-filename.cfg'/>
<config script='example-script.sh'/>
Example for the properties format:
name=value
another_name=anothervalue
Tag <request>
This tag denotes a single request (however, see the <recurse>
tag). A request must define a method and an url. All other tags are optional. The child elements of request are shown below.
Request <method>
The http method of the request, usually GET or POST.
<method value='GET'/>
Values: GET, HEAD, POST, PUT.
POST and PUT may be feeded by the <data
> section. Note that there are other uses of GET and POST that are currently not supported.
Request <url>
The requested url.
<url value="http://google.de"/>
Request <description>
A free form description of this request.
<description value="Visit google"/>
Request <useragent>
This tag is used to have different useragents each with its own cookies within one testplan. You can control the access sequence of different users. You can effectivly simulate multiple users. The type is string and it defaults to the empty string.
This tag is usefull for test plans containing interwoven but serialized requests of multiple users. Useragents are created behind the scene, so you need not declare anything, just use it. If you do not specify a useragent you implicitly specified the default user.
<useragent value="first user"/>
The value of this attribute is concatenated to the HTTP header attribute 'user_agent'. So you can easily determine which user caused the request, see HTML output.
Request <http-header>
Specify HTTP headers. These headers are set in this request only. Specify HTTP headers in the config file if you want to set HTTP headers for any request.
<http-header name="User-Agent" value="overwrites the user agent"/>
<http-header name="A-New-Name" value="a new value"/>
Request <data>
For web forms you need to transmit the form data. This is done with the data tag:
<data>
<parm name='login' value='mary'/>
<parm name='password' value='secret'/>
</data>
The data tag will work for the GET and POST method. For the GET method this is equivalent to adding the parameters: <url value='http://.../?login=yourself&password=secret'/>
For the POST method the data is transmitted as the content of the request.
RESTRICTION: Currently there is only support for the application/x-www-form-urlencoded
content type.
Request <assert>
Assertions are somewhat different to the other tags. The only element within an <assert> tag is a tag that denotes a class name. This class is dynamically loaded (require
).
Currently the only available element is <WWW.Webrobot.Assert>
which denotes the class WWW::Webrobot::Assert
.
The class will get the child elements as input. This means that the syntax within <WWW.Webrobot.Assert>
is dependant on WWW::Webrobot::Assert
. Consider this behaviour in case you want to supply your own class.
Now look at the syntax within <WWW.Webrobot.Assert>
: It contains an expression which is
a simple predicate.
an
<and>
tag containing at least one expression.an
<or>
tag containing at least one expression.a
<not>
tag containing exactly one expression.
The predicates yield a boolean value. The tags <and>
, <or>
and <not>
do the designated boolean operation.
Predicates itself are tags, too:
- <status>
-
This checks the HTTP status code of the response. If requests are redirected the last response is taken, so there should usually be no HTTP response code 3xx (but see
<recurse>
tag).If the
value
is a three digit number then the predicate does an exact string compare to the status code.If the
value
is a one digit number then the predicate compares to the error class, i.e. value 4 matches all HTTP errors 4xx. - <string>
-
This predicate matches whether the
value
is in the content. - <file>
-
Like <string> but matches against the content of the file denoted by the value attribute.
- <regex>
-
This predicate matches the
value
against the returned content (which is often HTML). The value is a regular expression. - <xpath>
-
This predicate converts the returned content to XML. Then it applies the
xpath
expression and matches the result to thevalue
.A useful way of usage is:
Get your desired page with an <xpath> in your assertion to enforce the XML conversion (XML conversion is done lazy).
Figure out your desired xpath expression with xpath-shell and add it to your test plan.
Run your testplan again.
Note: This predicate is very time consuming. That XML stuff isn't that efficient, better use <regex> if you can.
BUG: The returned content must be of type text/html, otherwise the behavior is undefined.
- <timout>
-
The predicate is true if the request takes no more than
value
seconds. - <header>
-
This predicate tests whether a header field
name
contains the valuevalue
. Example:<header name="Content-type" value="text/html"/>
Note 1: A toplevel and
operator may be left out.
Note 2: The class name WWW.Webrobot.Assert
may be left out. Class names must start with a capital letter and must contain a period, while operators and predicates don't.
Example where toplevel and
and class name WWW.Webrobot.Assert
is left out:
<assert>
<status value='2'/>
<or>
<string value='Login'/>
<regex value='Log(out|off)'/>
</or>
<not>
<string value='Error'/>
</not>
<xpath xpath='//title/text()' value='Welcome'/>
<timeout value='2.7'/>
</assert>
Complete example doing the same:
<assert>
<WWW.Webrobot.Assert>
<and>
<status value='2'/>
<or>
<string value='Login'/>
<regex value='Log(out|off)'/>
</or>
<not>
<string value='Error'/>
</not>
<xpath xpath='//title/text()' value='Welcome'/>
<timeout value='2.7'/>
</and>
</WWW.Webrobot.Assert>
</assert>
The built-in default assertion (if you do not annotate any assertion) is <status value='2'/>
.
Tag content:
Instead of defining a 'value' attribute you may define a value as content of a tag. Leading and trailing white space including new line characters will be skipped. This allows for smart formatting in the test plan. Note that any other white space must be precisely adhered to. See the leading white space of '<head>'.
<string>
<![CDATA[
<html>
<head>
<title>A_Static_Html_Page</title>
</head>
<body>
A simple text.
</body>
</html>
]]>
</string>
Request <recurse>
The recurse tag follows the same logic as the assert tag. Its purpose is to add some request to the original request. The procedure is simple (and you may write your own class):
Do the first request.
Call the
next
method of the class with the last request as a parameter.If the
next
method returns (undef,undef) then finish (goto the next step in the test plan). Otherwise apply (2) with the value returned bynext
.
For more information see WWW::Webrobot::pod::Recur.
The dependant requests (i.e. which do not appear in the testplan, but come into play by the recurse
tag) show different in many output filters. Usually there are some preceding dots (...). Currently there are two classes available:
WWW.Webrobot.Recur.Browser:
This class does what a usual http browser does when you hit an url: It loads the url, any images and frames. This class takes no arguments.
<recurse>
<WWW.Webrobot.Recur.Browser/>
</recurse>
WWW.Webrobot.Recur.LinkChecker:
This class will do nearly the same as <WWW.Webrobot.Recur.Browser>, but it additionally follows HTML links. This makes it a link checker.
This class accepts a parameter to restrict the links to be visited. The argument language is the same as with assert
, but the predicates are different.
This feature is among others usefull
to restrict the linkchecker to your site
to prevent it from logout (if you did a login before)
to prohibit a language switch
<recurse>
<WWW.Webrobot.Recur.LinkChecker>
<and>
<url value="^http://myserver.org"/>
<scheme value="http"/>
<not><url value="logout\.jsp"/></not>
<not><url value="logout\.do"/></not>
<not><url value="setUserLocale.do"/></not>
</and>
</WWW.Webrobot.Recur.LinkChecker>
</recurse>
Note: You do not want to linkcheck the entire WWW, so carefully define which links to visit. Do not harass public websites.
I added an example for any predicate. Let the example url be http://www.myhost.org:4321/show/page.html
. The predicates are:
- <url>
-
The
value
is a regular expression. It matches against the entire url. Example:http://www.myhost.org:4321/show/page.html
- <scheme>
-
The
value
is a regular expression. It matches against the scheme part of the url. Example:http
- <host>
-
The
value
is a regular expression. It matches against the host part of the url. Example:www.myhost.org
- <port>
-
The
value
is a regular expression. It matches against the port part of the url. Example:4321
- <host:port>
-
The
value
is a regular expression. It matches against the host:port part of url. Example:www.myhost.org:4321
Note: Say you want to exclude the logout link, but your website may have menu links redirected to the logout link. It is sufficient to forbid the logout link, all redirected menu links are aborted as soon as they redirect to the logout link. I think this is the only case where a request ends up in a HTTP 3xx response code.
Request <property>
The property tag is used to define new properties. It must have a name Attribute that defines the name of the new property. It must also have a second attribute that defines the value of the property. The value attribute must be one of the following:
- value
-
This attribute defines the value of the property to be a simple string.
- regex
-
This attribute matches the HTTP response against a regular expression. The regular expression must contain a pair of parenthesis that denote the result.
- xpath
-
This attribute applies an XPath expression to the HTTP response and assigns the result to the property.
- header
-
This attribute extract the designated HTTP response header value.
- status
-
This attribute is applied to the HTTP response status line. Possible values are
- code
-
for the HTTP response code (e.g. '200').
- message
-
for the HTTP response message (e.g. 'Ok').
- protocol
-
for the HTTP response protocol (usually 'HTTP/1.0' or 'HTTP/1.1').
- random
-
This attribute yields a random number with the number of digits designated by its value.
rand='5'
gives a 5 digit random number. The maximum number of digits is limited to 15.
Examples:
<property name='a_name' value='a_value'/>
<property name='a_name' regex='any(value)matched'/>
<property name='a_name' xpath='//title/text()'/>
<property name='a_name' header='Content-type'/>
<property name='a_name' status='code'/>
<property name='a_name' random='5'/>
Tag <global-assertion>
This assertion is executed for any request (from the point on where you define it). Name substitution takes place when the calling request is executed, so this assertion my expand different during the execution of the test.
An assertion of a request is true if both the global assertion is true and and the assertion of the request is true.
The build-in assertion will only be executed if there is neither a global assertion nor an assertion specific to a request.
Example:
<global-assertion mode='new'>
<assert>
<status value='500'/>
<timeout value='2.7'/>
</assert>
</global-assertion>
The mode value may be
new
New global assertion. Invalidates previous global assertion
add (default)
accumulate global assertion (AND conjunction)
Names (Variables)
If you defined names in a corresponding config file, see WWW::Webrobot::pod::Config. You can use a name in your test plan by using the perl like syntax ${myhost}
. Though - this is no perl variable, it just looks like one. Example:
In a config.prop
file define
names=host=www.myserver.de
names=port=4321
This maps to an internal data structure
host => www.myserver.de
port => 4321
In your testplan.xml
plan use
<request>
<method value='GET'/>
<url value='http://${host}:${port}/'/>
</request>
Predefined names
- _id
-
This name is "1" if used with webrobot.
It takes a value out of [1, 2, ... load.number_of_clients] if used with webrobot-load. It is a unique id for any child process.
This is especially usefull if you want to use different logins for each client, see the
<config>
tag.
BUGS
- charset
-
The internal representation of XML is utf-8 and independent of your XML's charset. Some strings are internally converted to iso-latin (for output only), so you might encounter problems in the output if you rely on anything else but iso-latin.
NOTE
In XML
&
must be coded&
and<
must be coded<
SEE ALSO
RFCs
- RFC 2616
- RFC 1945
- RFC 2818
-
http://www.faqs.org/rfcs/rfc2818.html HTTPS
- RFC 2617
-
http://www.faqs.org/rfcs/rfc2617.html: HTTP Authentication: Basic and Digest Access Authentication
- RFC 2965
-
http://www.faqs.org/rfcs/rfc2965.html HTTP State Management Mechanism
- RFC 2109
-
http://www.faqs.org/rfcs/rfc2109.html Cookies: HTTP State Management Mechanism
- RFC 1521
Tutorials
http://www.research.att.com/~bala/papers/h0vh1.html: Key Differences between HTTP/1.0 and HTTP/1.1
http://www.ibiblio.org/mdma-release/http-prob.html: Analysis of HTTP Performance problems
http://www.jmarshall.com/easy/http/: HTTP Made Really Easy
http://www.rad.co.il/networks/1999/http/index.htm: The Hypertext Transfer Protocol (HTTP/1.1)
http://www.netscape.com/newsref/std/cookie_spec.html: Netscape Cookies
http://www.cookiecentral.com/faq/: The Unofficial Cookie FAQ
http://www.isi.edu/in-notes/iana/assignments/media-types/media-types: Media Types
AUTHOR
Stefan Trcek
COPYRIGHT
Copyright(c) 2004 ABAS Software AG
This software is licensed under the perl license, see LICENSE file.