Testing

The generator creates integration tests for web pages. For every web page a default integration test is created without having to add anything to the model. The purpose of a default integration test is to have a quick means to test whether the basic functionality of the page works fine. For more complex or more detailed tests, a DSL that is dedicated to the modeling of tests needs to be used. The structure of the resulting code is identical, whether you use default tests or explicit tests.

Selenium, Arquillian and JUnit

Three tools and frameworks are needed for the integration tests for web pages:

  • Selenium, a tool and SDK to automate web browsers
  • Arquillian, a framework for the development and execution of integration tests
  • JUnit, a well known framework for the development and execution of tests (unit and integration tests)

Note

Currently, Arquillian depends on JUnit 4 and cannot be used with JUnit 5. JUnit 4 is a powerful, mature framework (latest stable version is 4.12), so this is a limitation but not a problem.

The selenium server is the middle piece that is needed to communicate between the integration test and the web browser:

Selenium Server

Page Objects Pattern

For every modeled web page, the generator creates a Java source file [layout-Name]Page.java that supports the so-called page objects pattern. Those classes are being used by any integration test that gets generated, default and explicit ones. Having those classes for the abstraction of web pages significantly simplifies the writing and maintenance of integration tests.

Test-Case Structure

The JSF generators generate an elaborated mechanism that lets you import test data and implement readable, reusable and yet customizable tests.

Test-Case Structure

As usual, you can manually add code to any of the generated classes. This gives you the flexibility to implement any integration test that you can think of.

For every modeled display that is used in the web page, you get three methods in the abstract test class. Lets assume that you have modeled a display ‘PersonData’ in a layout ‘Person’. You then get the following:

...
    @InSequence(value=50)
    public void personDataPrecondition(@Page PersonPage page) {
        // add some checks here
        ...
    }

    @InSequence(value=60)    
    public void personData(@Page PersonPage page) {
        // enter some data or execute commands
        ...
    }

    @InSequence(value=70)
    public void personDataPostcondition(@Page PersonPage page) {
        // add some checks here
        ...
    }
...

At the begining of teach test, you always get a method prelude() generated. Its purpose is to do something with the web application to get to the page that you actually want to test. This could for instance be a login or search procedure that needs to be executed in order to get to the page under test.

Individual Test-Cases

In order to generate individual tests, you need to use the Test DSL. This is an example of how this can be done:

/*
 * Test to see whether the login page still does not allow a user
 * entering the application when the first attempt was unsuccessful.
 */
test LoginTwoTimesIncorrect {
    set Abstract = true;

    step IncorrectLogin1 : Login {
        link Actions = LoginData.Email ENTER,
                       LoginData.Passwort ENTER,
                       LoginData.LoginButton CLICK,
                       LoginData.LoginButton IS_ERROR_MESSAGE;
    }

    step IncorrectLogin2 : Login {
        link Actions = LoginData.Email ENTER,
                       LoginData.Passwort ENTER,
                       LoginData.LoginButton CLICK,
                       LoginData.LoginButton IS_ERROR_MESSAGE;
    }
}

This modeled test gives you the following classes in the web fragment:

  • AbstractLoginTwoTimesIncorrectTest
  • AbstractLoginTwoTimesIncorrectTest.InputData
  • AbstractLoginTwoTimesIncorrectTest.AssertData

In the web application you get the following:

  • LoginTwoTimesIncorrectTest
  • LoginPages.LoginTwoTimesIncorrect
  • LoginTwoTimesIncorrectTestInputData.json
  • LoginTwoTimesIncorrectTestAssertData.json

In contrast to the default tests, the names of the methods that hold the test implementation for explicit tests are derived from the modeled steps.

...
    @InSequence(value=50)
    public void incorrectLogin1Precondition(@Page LoginPage page) {
        // add some checks here
        ...
    }

    @InSequence(value=60)    
    public void incorrectLogin1(@Page LoginPage page) {
        // enter some data or execute commands
        ...
    }

    @InSequence(value=70)
    public void incorrectLogin1Postcondition(@Page LoginPage page) {
        // add some checks here
        ...
    }

    @InSequence(value=80)
    public void incorrectLogin2Precondition(@Page LoginPage page) {
        // add some checks here
        ...
    }

    @InSequence(value=90)    
    public void incorrectLogin2(@Page LoginPage page) {
        // enter some data or execute commands
        ...
    }

    @InSequence(value=100)
    public void incorrectLogin2Postcondition(@Page LoginPage page) {
        // add some checks here
        ...
    }
...