Webtest WebTest GitHub Home

Samples to give you a jump start

The samples should give you an easy jump start. You can copy/paste them from this page into your editor.

We will start with the easiest examples and explain more advanced topics as we proceed. The description of every sample is based on the preceeding examples.

This page only shows very few of the available steps that can be used with Canoo WebTest. See the various Syntax Reference pages (e.g. Syntax Reference - Core Steps) for more details about the steps. In particular, Syntax Reference - PDF Steps has usage samples for the PDF Steps.

This page assumes that you have already followed the Install instructions.

Simple test

The first simple example shows how to connect to a webapplication starting at http://www.myserver.com:8080/myApp/login.

SimpleTest.xml
<project name="SimpleTestbasedir=".default="wt.full">

  <property name="webtest.homelocation="C:/java/webtest" />
  <import file="${webtest.home}/webtest.xml"/>

  <target name="wt.testInWork">
    <webtest name="my simple Test">
      <invoke
        url="http://www.myserver.com:8080/myApp/login"
        description="get Login Page" />
      <verifyTitle 
        text="Login Page"
        description="we should see the login title" />
    </webtest>
  </target>
</project>

Look above the import task. It is crucial that you replace C:/java/webtest with your WEBTEST_HOME installation directory. Otherwise, Canoo WebTest may not find its implementation. You can also provide this value as a relative path, e.g. a value of "../webtest" is convenient if your SimpleText.xml is stored in a directory next to your WEBTEST_HOME.

Put this file where you would like your tests to be, open a command shell in that directory and type:

webtest -buildfile SimpleTest.xml

Organize your tests

The import statement in the previous example should be executed only once and not be present in all test files to avoid memory problems. For this reason it is wise to organize tests in a subfolder as done in the sample project created by wt.createProject and call the real tests from the main build file

build.xml
<project default="wt.full">

  <property name="webtest.homelocation="C:/java/webtest" />
  <import file="${webtest.home}/webtest.xml"/>

  <target name="wt.testInWork">
    <ant dir="testsfile="allTests.xml"/>
  </target>
</project>
tests/allTests.xml
<project default="all">
  <target name="all">
    <ant file="testFoo.xml"/>
    <ant file="testSomething.xml"/>
    <ant file="testSomethingElse.xml"/>
  </target>
</project>

Include files

It is important to avoid duplications to keep tests maintainable. This can be achieved with the usage of entities (or with macros). Entities are standard XML features allowing to refer (external) xml fragments through a DTD.

webtest.xml provides facilities to make work with entities and DTD easier: a DTD file dtd/Project.dtd is automatically created to reference the files contained in the includes folder.

This means that when your includes> folder contains a file like this:

includes/goToLogin.xml
<invoke
  url="http://www.myserver.com:8080/myApp/login"
  description="get Login Page" />
<verifyTitle 
  text="Login Page"
  description="we should see the login title" />

WebTest will automatically generate dtd/Project.dtd containing a reference like:

<!ENTITY goToLogin SYSTEM "../includes/goToLogin.xml">

Referencing this DTD in your tests allows to make usage of the entities:

tests/testSomething.xml
<!DOCTYPE project SYSTEM "../dtd/Project.dtd">

<project default="test">
  <target name="test">
    <webtest name="my simple Test">
      &goToLogin;
      <setInputField forLabel="Logintext="John"/>
      <setInputField forLabel="Passwordtext="secret"/>
      <clickButton label="Login"/>
      ...
    </webtest>
  </target>
</project>

Property Usage

You can use the full range of ANT features to deal with properties. A typical example is that you use a url that has some common prefix but is extended with different parameters. Using a property for describing the common prefix makes your tests both: more readable and easier to adapt to changes.

property usage
..
  <property name="urlvalue="login?scott="/>

  <target name="main">
    <webtest name="myTest">
      &config;
      <steps>
        <invoke
          description="bad login"
          url="${url}wolf" />
        <verifyTitle text="Sorry, bad login" />
        <invoke
          description="proper login"
          url="${url}tiger" />
        <verifyTitle text="Welcome" />
      </steps>
    </webtest>
  </target>
..

This opens quite a number of possibilities.

Entity Modules
When extracting a block into an external file as shown above, you can still use the ${property} syntax. This makes external files more reusable in different contexts. They can effectively become modules that capture the structure of the steps you are executing.
Property Files
If you have a 'family' of properties that change values together, e.g. label.a and label.b both for english and french, then you can create two files: english-labels.properties and french-label.properties and select it via <property file="english-labels.properties"> in your webtest. The files themselves contain the properties in the format name=value one at a line. See the ANT documentation for more details.
Immutable Properties
The value of a property cannot change once it has been set. While this is sometimes annoying it makes for quite a nice way to reuse a test that depends on properties. In the above example we could set the property "url" from a caller of the test target to a different value. A caller can use the <ant> or <antcall> tasks to do that (using nested property elements). See the ANT documentation for more details.

Putting it all together

Let's stick to our login examle. Say we want to create a "Login" module. It could look like this:

includes/login.xml
<invoke
  description="goto start page"
  url="${start.page}" />
<setInputField description="set user name"
  name="username"
  value="${user}" />
<setInputField description="set password"
  name="password"
  value="${login.ok.password}" />
<clickButton
  label="login"
  description="Click the submit button" />
<verifyTitle description="Home Page follows if login ok"
  text="${login.ok.title}"  />

This should be reasonably self-explanatory. Note that you can use xml comments at any time, but they do not get reported. Therefore, I like it better to use the description for commenting.

There will be a lot of Use Cases using this module. Here is one.

tests/loginAndStep.xml
<?xml version="1.0"?>

<!DOCTYPE project SYSTEM "../dtd/Project.dtd">

<project default="test">

  <target name="test">
    <webtest name="loginAndStep">
      &login;
      &step;
    </webtest>
  </target>
</project>

Other Use Cases will be different in what they do after the login. They are likely to share even more modules, e.g. "step". They will differ in how they assemble the modules and what they do in between the module calls. How do we make sure that all use cases get executed? We collect them in a test suite:

tests/allUseCasesTestSuite.xml
<?xml version="1.0"?>

<project default="testSuite">

  <property name="start.pagevalue="myStartPage"/>

  <target name="testSuite">
    <ant antfile="loginAndStep.xml"/>
    <ant antfile="useCase2.xml"/>
  </target>
</project>

However, the Use Cases do not change in structure for different languages. Only the labels change. We put those languages in different property files.

properties/english.properties
user=scott
login.ok.password=tiger
login.ok.title=Welcome
properties/french.properties
user=pascal
login.ok.password=fleur
login.ok.title=Bienvenue

In Order to properly test all Use Cases for all languages, we build a test suite that calls the AllUseCasesTestSuite for each language property file.

tests/allLanguagesTestSuite.xml
<project default="testSuite">

  <property name="suite.xmlvalue="allUseCases.xml" />

  <target name="testSuitedepends="testSuiteFrench,testSuiteEnglish" />

  <target name="testSuiteFrench">
    <ant antfile="${suite.xml}">
      <property file="properties/french.properties"/>
    </ant>
  </target>
  <target name="testSuiteEnglish">
    <ant antfile="${suite.xml}">
      <property file="properties/english.properties"/>
    </ant>
  </target>

</project>

For keeping the tests manageable, proper naming of your test files, entities, and properties helps much. The same holds true for the directory structure. The structure used above allows to use webtest.xml propertly but it is in no way mandatory. In short it looks like this:

Test Directory Structure
WebTestProject
  dtd
  includes
  properties
  tests

Following the proposed strategy of removing duplication in the tests will enable you to keep your tests managable and flexible enough to keep up to speed with application development. The goal is to keep every file understandable and comprehensive for its own, at its own level of abstraction. Sure this goes at the price of not having a flat view over the test "storybook". However, this can be achieved 'after-the-fact' by using the builtin reporting features. See the "Build Info"."Selftest Report" for an example.

You should now be able to tackle even more complicated scenarios like different datasets in local, test, and integration environments.

Rules of thumb

Strike Two - You're Out!
This is hardball. As soon as you find yourself using code a second time, don't copy but refactor. Put it in a property, an own ant file, a separate target, or a module (external entity).
Keep targets short
Remember that you can call every target separately. Putting all your tests in one target limits your options of running selective tests.
Use description
When writing the description think what message would help you if this step fails.
Fail first
Assure that the test fails as expected and watch how it fails, i.e. make it fail with a meaningful message. This is a mean of "test-the-test". Sometimes it is useful to even keep a negative test in a "not" step. You will find lots of those in the selftests of Canoo WebTest.
One test at a time
Only write one test at a time. Make it fail, make it run.
Use a proper editor
Take that little extra time to set up your editor such that it recognizes the WebTest.dtd. This will payback multiple times.
Learn XPATH
Make yourself familiar with the XPath syntax. This will enhance the power, flexibility and clarity of your tests by far. Use the XPath Explorer to make your life easier.
Database Setup
If your tests rely on a specific population in the database, make sure, this population is reconstructed right before the test. Look at DbUnit on how to achieve this.