Anteater

October 04, 2002

Anteater with Jelly

Anteater | Web services

Jeff Turner just released a new version of Anteater which integrates with Jelly. It's interesting to see things moving so fast, especially after the recent discussion related to XML-based scripting languages.

Anteater is a testing framework for HTTP and SOAP applications, built as an extension of Ant. The way you write scripts is by using a declarative syntax, where you specify actions to be taken and a set of expected output(s). You can check the output in various ways, including string equality, regular expressions or XPath expressions.

In addition to emulating an HTTP or SOAP client, Anteater can also be used to emulate the server side, in order to test an HTTP or SOAP client application, or to test asynchronous Web services. Anteater embeds a full blown servlet container (Tomcat 3.3), which is used to receive incoming HTTP requests. You can apply the same checks as described above not only on the response received, but also on an incoming request. With this functionality, Anteater can be used to implement test scripts for asynchronous Web services, including ebXML and BizTalk. Anteater can also be used to quickly test Web applications by deploying them on its internal servlet container, making testing such applications a real breeze.

If you're familiar with Ant for writing build scripts, you should be able to grasp Anteater very easily. And since is based on Ant, Anteater is extensible, you can define new tasks and matchers that fit your needs very easily. Check out Anteater's user manual for more information on what it is and how it works.

Posted by ovidiu at 10:27 PM |

August 06, 2002

Properties grouping

Anteater
Jeff Turner finished implementing property groups in Anteater. These allow properties to be grouped and referred to as a whole in all the places they are needed.

In Anteater you define the behavior of a test by specifying various properties which affect the tasks which are part of the test. Up until property groups, you'd have to specify these properties each time you were using a particular task. With groups, you specify these properties in one place, and refer to all of them in your tasks. You can define specialized groups which inherit from a common set of properties, and modify or add new property definitions.

Here is Jeff's description of this feature:

Groups

Groups are like containers for Anteater objects, allowing reuse of definitions:

<group id="mygroup">
  <session/>
  <logger type="xml"/>
  <property name="host" value="localhost"/>
</group>

<!-- Each member task inherits the group's logger and session -->
<httpRequest group="mygroup" path="/a.html" .. />
<httpRequest group="mygroup" path="/b.html" .. />

Group Properties

Anteater tasks' behaviour is now configured through properties of the group to which the task belongs. Currently recognised properties are 'host', 'port', 'debug', 'timeout', 'protocol', 'haltonerror' and 'usetidy'. So if we had:

<group id="cocoontests">
  <property name="host" value="myhost.com"/>
  <property name="port" value="8080"/>
  <property name="debug" value="0"/>
</group>
<httpRequest group="cocoontests" ... />
<httpRequest group="cocoontests" ... />

Then those tasks would run against myhost.com:8080, with debug level 0, unless overridden by attributes on the httpRequest object.

Group properties can also be set from outside a group:

<property name="cocoontests.debug" value="2"/>

This allows group values to be specified in properties files outside the test script, or from the command-line, eg:

anteater -Dcocoontests.host=localhost -Dcocoontests.debug=2 -f tests.xml

Group Inheritance

Since a Group object is an Anteater object, a Group can belong to another Group, either by nesting:

<group id="a">
  <property name="host" value="myhost.com"/>
  <group id="b"/>
</group>

or by the 'inherits' attribute ('group' also works):

<group id="a">
  <property name="host" value="myhost.com"/>
</group>
<group id="b" inherits="a"/>

Group elements are inherited in what I hope seems a natural manner. Properties are passed through unless overridden, so 'b' in the above example has host 'myhost.com'. Loggers are passed through, unless any loggers are defined in the child group. Same with sessions.

The Default Group

There is an implicit 'default' group, to which all tasks belong unless otherwise indicated. If the default group were written out, it would look like this:

  <group id="default">
  <session/>
  <logger type="minimal"/>
  <property name="host" value="localhost"/>
  <property name="debug" value="0"/>
  <property name="port" value="BUILTIN,8080"/>
  <property name="timeout" value="30s"/>
  <property name="protocol" value="HTTP/1.0"/>
  <property name="haltonerror" value="false"/>
  <property name="usetidy" value="false"/>

  <!-- Declare all other groups as children of 'default' here -->
  <group refid=".."/>
  ...
</group>

So by default, all tasks get a session, and a logger that prints to stdout, plus a bunch of properties used to configure the default Anteater behaviour.

The default group can be overridden by the user, by declaring a group with id 'default'. This way, we can override specific properties for all tasks:

<group id='default'>
  <property name="host" value="myhost.com"/>
  <property name="port" value="8080"/>
</group>

All other items are inherited from the 'default' defaults.

And of course the 'default' group properties can be overridden at the command-line, eg -Ddefault.host=myotherhost.com.

Putting it all together

The purpose of grouping has been to make simple things easier, and complicated things possible. Some scenarios, from simple to complex:

  • With the advent of the default group, most users need never bother with loggers, sessions, groups or properties. They just rely on the defaults, maybe occasionally overriding them, eg -Ddefault.debug=5.
  • For users for whom the defaults need modifying, that can easily be done by overriding the 'default' group, and otherwise not touching the script. Want to log to XML as well as the console? Redefine the default group:
      <group id="default">
        <logger type="minimal"/>
        <logger type="xml" todir="${log.dir}"/>
      </group>
      
  • Users with somewhat large scripts, who want to break it up into sections can do so, by defining a hierarchy of groups:
      <group id="mytests">
        <property debug="0"/>
      </group>
      <group id="livesite" inherits="mytests">
        <property name="host" value="www.mysite.com"/>
        <logger type="xml" todir="{docs.dir}"/> <!-- HTML report -->
      </group>
      <group id="devsite" inherits="mytests">
        <property name="host" value="www.mysite-dev.com"/>
        <property name="debug" value="1"/> <!-- devsite a bit unstable -->
        <property name="failonerror" value="true"/> <!-- Don't waste time testing whole site -->
    
        <group id="devsite-brokenbit">
          <!-- Very broken bit of devsite -->
          <property name="debug" value="10"/>
      </group>
    
      <httpRequest group="section1" ... />
      ...
    

So we define a hierarchy of groups at the top of the script, and then use it in the subsequent tests.

Posted by ovidiu at 04:21 PM |
 
Cool stuff
  Arduino TinyWebServer: part 3 and part 2
Search
More from me
Picture gallery
Admin
Copyright © 2002-2016 Ovidiu Predescu.