JWebUnit Quickstart

This quickstart contains sample code and guidance to get you started with JWebUnit. To see all of the methods available, consult the Javadocs - particularly the WebTestCase class for full documentation.

Creating a JUnit 4 TestCase

JWebUnit uses two approaches for creating JUnit 4 test cases: static import and delegation. The simplest is to statically import all methods of net.sourceforge.jwebunit.junit.JWebUnit.

import static net.sourceforge.jwebunit.junit.JWebUnit.*;

public class ExampleWebTestCase {
	
    @Before
    public void prepare() {
        setBaseUrl("http://localhost:8080/test");
    }

    @Test
    public void test1() {
        beginAt("home.xhtml"); //Open the browser on http://localhost:8080/test/home.xhtml
        clickLink("login");
        assertTitleEquals("Login");
        setTextField("username", "test");
        setTextField("password", "test123");
        submit();
        assertTitleEquals("Welcome, test!");
    }
}

An alternative is to include an instance of the WebTester class in your TestCase and delegate navigation and assertions to it. This is provided in case you need or prefer delegation.

import net.sourceforge.jwebunit.junit.WebTester;

public class ExampleWebTestCase {
    private WebTester tester;

    @Before
    public void prepare() {
        tester = new WebTester();
        tester.setBaseUrl("http://localhost:8080/test");
    }
    
    @Test
    public void test1() {
        tester.beginAt("home.xhtml"); //Open the browser on http://localhost:8080/test/home.xhtml
        tester.clickLink("login");
        tester.assertTitleEquals("Login");
        tester.setTextField("username", "test");
        tester.setTextField("password", "test123");
        tester.submit();
        tester.assertTitleEquals("Welcome, test!");
    }
}

In the following samples, JUnit 4 and static import will be used.

Creating a JUnit 3 TestCase (deprecated)

JWebUnit uses two approaches for creating JUnit 3 test cases: inheritance and delegation. The simplest is to inherit from WebTestCase rather than junit.framework.TestCase.

import net.sourceforge.jwebunit.junit.WebTestCase;

public class ExampleWebTestCase extends WebTestCase {
	
    public void setUp() {
        super.setUp();
        setBaseUrl("http://localhost:8080/test");
    }

    public void test1() {
        beginAt("home.xhtml"); //Open the browser on http://localhost:8080/test/home.xhtml
        clickLink("login");
        assertTitleEquals("Login");
        setTextField("username", "test");
        setTextField("password", "test123");
        submit();
        assertTitleEquals("Welcome, test!");
    }
}

An alternative is to include an instance of the WebTester class in your TestCase and delegate navigation and assertions to it. This is provided in case you need or prefer delegation.
WARNING: WebTester was migrated to JUnit 4. As a result all assertXX will throw java.lang.AssertionError instead of old junit.framework.AssertionFailedError.

import junit.framework.TestCase;
import net.sourceforge.jwebunit.junit.WebTester;

public class ExampleWebTestCase extends TestCase {
    private WebTester tester;

    public void setUp() {
        super.setUp();
        tester = new WebTester();
        tester.setBaseUrl("http://localhost:8080/test");
    }
    
    public void test1() {
        tester.beginAt("home.xhtml"); //Open the browser on http://localhost:8080/test/home.xhtml
        tester.clickLink("login");
        tester.assertTitleEquals("Login");
        tester.setTextField("username", "test");
        tester.setTextField("password", "test123");
        tester.submit();
        tester.assertTitleEquals("Welcome, test!");
    }
}

Configuring logging

JWebUnit use SLF4J to log. SLF4J is only a facade so with the default Maven configuration you will only get slf4j-api in your classpath with no implementation. If you run your tests you will see a message like this:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

but no log at all.

Many popular logging framework do support SLF4J: log4j, jcl, logback, ... For example here are the steps to configure logback logging framework:

First you should add logback JAR to your classpath. If you are using Maven, simply add:

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.0.6</version>
        <scope>test</scope>
    </dependency>

Now if you run your tests everything will be logged to console. Some components are very verbose so here is a sample logback configuration to reduce verbosity. Just create a file called logback-test.xml in your classpath (src/test/resources is a good place if you are following Maven conventions). This will suppress all debugging messages unless they are at the ERROR level or higher.

<configuration debug="false">
	<!-- definition of appender STDOUT -->
	<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
		<encoder>
			<pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
		</encoder>
	</appender>

	<root level="ERROR">
		<!-- appender referenced after it is defined -->
		<appender-ref ref="STDOUT" />
	</root>
</configuration>

Please read logback documentation for more details.

Selecting the plugin you want to use

JWebUnit can use different plugins to execute the tests you write. Only one line makes the difference:

import net.sourceforge.jwebunit.util.TestingEngineRegistry;
import org.junit.Before;

import static net.sourceforge.jwebunit.junit.JWebUnit.*;

public class ExampleWebTestCase {

    @Before
    public void prepare() {
        setTestingEngineKey(TestingEngineRegistry.TESTING_ENGINE_HTMLUNIT);    // use HtmlUnit
        setTestingEngineKey(TestingEngineRegistry.TESTING_ENGINE_WEBDRIVER);    // use WebDriver
    }
}
NB: If you have only one plugin in your classpath, you don't need to explicitly specify to use it, JWebUnit will find and use it.

Navigating Your Web Application

The primary way that JWebUnit allows you to test your web application is through navigation of the application itself. You can consider each test case as a use case through the application itself. The first step is to point where the testable application is hosted so that it may be accessed by JWebUnit. It can generally be done in a test fixture.

    @Before
    public void prepare() {
        setBaseUrl("http://myserver:8080/myapp");
    }

Note that you should not be pointing to the production version of your web application, but rather a sandboxed development or testing server!

Now that the TestCase is pointed at your application, you can navigate to a particular resource to ensure that it exists, and contains the content you expect. For example, if your application starts at index.html and contains a link to your login page under "Login", you may test these assertions through the following code:

    @Test
    public void testIndexLogin() {
        beginAt("index.html");        // start at index.html
        assertTitleEquals("Home");     // the home page should be titled "Home"
        assertLinkPresent("Login");    // there should be a "Login" link
        clickLink("Login");            // click the link
        assertTitleEquals("Login");    // we should now be on the login page
    }
assertLinkPresent() searches for links by a string ID; assertLinkPresentWithText() searches for links that contain a text string. For more information on the differences between the various testing methods, check out the Javadocs.

Working With Forms

Now that we can access the Login page, we can use JWebUnit to fill out the form and assert that it works as expected.

    @Test
    public void testFormSubmission() {
        beginAt("login.html");
        assertTitleEquals("Login");    // we should be on the login page
        
        // fill out the form
        assertLinkNotPresent("Logout");		// we should not be logged in
        assertFormPresent("login_form");
        assertFormElementPresent("username");
        assertFormElementPresent("password");
        setTextField("username", "test");
        setTextField("password", "test123");
        assertFormElementEquals("username", "test");
        submit();
        
        // now that we have filled out the form,
        // we can assert that we can logout
        assertLinkPresent("Logout");		// we should now be logged in
    }

JWebUnit, through HtmlUnit/Selenium, automatically keeps track of cookies and session variables specified by the web application, allowing you to traverse through your site as if you were a normal user.

For pages with more than one form, JWebUnit will usually establish which form is being worked with implicitly from the form elements being accessed. You can also set the form explicitly by form ID or name:

    @Test
    public void testBottomFormSubmission() {
        beginAt("twoForm.html");
        setWorkingForm("bottomForm");
        submit();
    }
You can work with non-submit (type='button') buttons as well:
    @Test
    public void testPopupButton() {
        beginAt("info.html");
        assertButtonPresent("popupButtonId"); // clickButton() will also check this
        clickButton("popupButtonId");
        assertWindowPresent("popupWindow");
    }

Working With Frames and Windows

You can assert the presence of and navigate to windows by name. For instance, if clicking on a button on the root page should open a window, you could test for this and go to the popup window as follows:

    @Test
    public void testPopupWindow() {
        beginAt("rootPage.html");
        clickLink("popupLink");
        assertWindowPresent("popupWindow):  // optional - gotoWindow will
                                            // also perform this assertion.
        gotoWindow("popupWindow");
        ...
        gotoRootWindow();  //Use this method to return to root window.
    }

You can work with frames in a similar manner:

    @Test
    public void testFrame() {
        beginAt("info.html");
        assertFramePresent("contentFrame");
        gotoFrame("contentFrame");
        ...
    }

Validating Page Content

Once you have navigated to the page you wish to test, you can call the assertions provided by JWebUnit to verify it's correctness.

    @Test
    public void testCorrectness() {
        beginAt("mainPage.xhtml");
        assertTitleEquals("Main Page");
        assertLinkPresentWithText("Add Widget");
        clickLinkWithText("Add Widget");
        setTextField("widgetName", "My Widget");
        submit();
        assertTextPresent("Widget successfully added."):
    }

Validating Table Content

A number of assertions are provided by JWebUnit to validate the contents of tables on a page. You can simply check for the presence of text within a table, or check layout of all or a portion of the table. HttpUnit is used to purge empty rows and columns from the actual table before comparison, so you may leave spacer cells and rows out of your check.

The below test validates against this html table (the table id attribute is "ageTable"):

Name Age
Jim 30ish
Wilkes 20ish
    @Test
    public void testAgeTable() {
        beginAt("agePage.html");
        // check that table is present
        assertTablePresent("ageTable");
        
        // check that a single string is present somewhere in table
        assertTextInTable("ageTable", "Jim");
        
        // check that a set of strings are present somewhere in table
        assertTextInTable("ageTable",
                          new String[] {"Jim", "Wilkes"});
                          
        // check composition of table rows/columns
        assertTableEquals("ageTable",
                          new String[][] {{"Name", "Age"},
                                          {"Jim", "30ish"},
                                          {"Wilkes", "20ish"}});
    }

If you need to validate non-blank table cells that span more than a single column, a set of classes are provided which represent expected tables, rows, and cells.

Age Table
Name Age
Jim 30ish
Wilkes 20ish
    @Test
    public void testAgeTable() {
        beginAt("agePage.html");
        ExpectedTable ageTable = new Table(new Object[][] {
            {new Cell("Age Table", 2, 1)},
            {"Name", "Age"},
            {"Jim", "30ish"},
            {"Wilkes", "20ish"}
        });
        assertTableEquals("ageTable", expectedAgeTable);
    }

Using Element IDs to Validate Content

JWebUnit allows you to check for the presence of any html element by its id, or for text in an element. This can be a useful trick to check for the presence of some logical part of the page. Even in the case of free floating text, a span element can be used to surround the text and give it a logical id:

<span id="welcomeMessage">Welcome, Joe User!</span>

    @Test
    public void testWelcomeMessage() {
        beginAt("mainPage.xhtml");
        
        // check for presence of welcome message by text
        assertTextPresent("Welcome, Joe User!");
        
        // check for presence of welcome message by element id
        assertElementPresent("welcomeMessage");
        
        // check for text within an element
        assertTextInElement("welcomeMessage", "Joe User");
    }

Using Property Files to Validate Content

Another useful testing trick is to use property files for your expected values rather than hard-coded strings. This is especially useful if your application uses property files as a source for static text and messages. The same files can be used to provide the expected values for the tests.

For convenience, most of the JWebUnit assertions that take strings for the expected have an equivalent assertion that will take a property file key. You can use the TestContext to set the bundle to be used as well as the Locale (default is Locale.getDefault()).

    @Before
    public void prepare() {
        setbaseUrl("http://myserver:8080/myapp");
        getTestContext().setResourceBundleName("ApplicationResources");
    }

    @Test
    public void testMainPage() {
        beginAt("mainPage.html");
        assertTitleEqualsKey("title.mainPage");
        assertKeyPresent("message.welcome");
        assertKeyInTable("mainPageTable", "header.mainPageTable");
    }
There is also a getMessage() method on WebTester, WebTestCase and JWebUnit that can be used to access resource bundle messages directly in your tests.

Whether to check for a given logical chunk of text by hard-coded string, property file lookup, or by use of an element id is up to you.

For more information, consult the Javadocs.