This wiki page contains the status of the „Automated webapp tests for MyFaces core and extensions” GsoC 2010 Project. Feel free to contribute with comments, issues and improvements.

Description

For now, the source code of the project can be found in a google code project:

and it will soon be available in MyFaces codebase. The API proposal followed, with small changes can be found at:

The scope of this project is to provide a complete and easy to use testing framework for MyFaces core and extensions, but for any webapp user aplication as well. Using this API you will test the real instances and resources of the webapp, assuring both unit and integration testing.

A typical usage of the testing API looks like this:

@View(id = "test.xhtml", pageBeans = @PageBean(clazz = ExampleBean.class)) // this view will be accessed and the beans will be installed
@Configuration(SomeConfiguration.class) // the configuration class contains the Dependencies
@RunWith(WebappTestRunner.class)
public class ExampleTestCase
{
    
    @Assertable
    private ExampleBean exampleBean; // specified as PageBean, thus it is a valid resource, a CGLIB proxy will be injected

    @Tester
    private WebappTester tester; // will provide all necessary methods to control the test case
    
    public void testApplyInputValue()
    {
        webappTestCase.assertThat(exampleBean.getInput()).is("default value").before(PhaseId.RENDER_RESPONSE);
        webappTestCase.input("test value").into("testForm:fieldId");
        webappTestCase.click("testForm:buttonId");

        webappTestCase.assertThat(webappTestCase.getFacesContext().getExternalContext()).is("String");
        webappTestCase.assertThat(exampleBean.getInput()).is("test value").before(PhaseId.INVOKE_APPLICATION);
        webappTestCase.assertThat("#{exampleBean.input}").is("test value").after(PhaseId.INVOKE_APPLICATION);
        webappTestCase.expectCall(exampleBean.action()).in(PhaseId.INVOKE_APPLICATION);
        exampleBean.actionListener(null);
        webappTestCase.expectLastCall().in(PhaseId.INVOKE_APPLICATION);
    }
    
}

For configuring the test case, a set of annotations are provided:

Alongside this config annotations a testing method will nead @RunWith, @Test and @Deployment annotations provided by JUnit and Arquillian. A short description of each annotation folows:

For controlling the test case, the functionality and all the necessary methods are provided using the WebappTester field. This field should be annotated with „@Tester”. By default the API will inject an WebbapTesterImpl instance. With the help of this Tester one can make assertions using:

and do actions using:

The Tester offers access to the facesContext and the viewRoot by the „getFacesContext” and „getRoot” methods.

Adding extra functionality and extending the API is very easy. The main access point where a default implementation can be customized and overridden is by replacing the WebappTestConfiguratorImpl default implementation from the services support, with the default config.

In the implementation section of the framework a metadata based solution was used. When running a test, the API just collects informations about the data under test, creating a list of assertions and actions. When the data gathering is finished, the API runs the actual test, launching an initial view request and evaluating each assertion and action.

The main technology behind the API is Arquillian which, with the help of a unit testing framework(JUnit) and ShrinkWrap, can run test cases within a container using the real resource instances. The API is using an embedded Tomcat server as the default container where the test cases will be executed, and the unit testing framework used for testing is JUnit.

The technology behind accessing pages programatically is „HtmlUnit”. With it you can be able to invoke pages, fill out forms, click links, etc. CGLIB was also heavily used for proxy-ing and managing classes by reflection.

Improvements

For now, the unit testing framework supported is JUnit. The API should be extended to add functionality and support for TestNG as well.

The current initial version of the API adds some restraints when using assertions. If a bean instance call is used as an argument for „assetThat()”, then for the given bean only one method call is supported. Ex: „exampleBean.getInput()”-SUPPORTED; „exampleBean.getProperties.getInput()” – NOT SUPPORTED

Improvements should be done for exceptions, messages and logs which are now just shallow implemented.

Weaknesses

The @Deployment annotation, that should be added in any test case is e weakness of the current version. Arquillian is looking for a method configured with this annotation, and if it is not provided it trows an exception. A workaround for this issue will be required for next versions.

For now the Tomcat container support that Arquillian provides requires a servlet-mapping for the WebappServletTestRunner, in the "web.xml" file.

Using a metadata based solution by initially creating a list of test data and doing the actual test afterward, debugging in the test class method will be disabled.

Problems

Feel free to add any problems and issues that you have encountered using the API.

Suggestions

Any feedback and suggestions are welcomed.