This site uses cookies. Continue to use the site as normal if you are happy with this, or read more about cookies and how to manage them.

×

This site uses cookies. Continue to use the site as normal if you are happy with this, or read more about cookies and how to manage them.

×

Flex Acceptance Testing and Continuous Integration

The problem I had is how to automate acceptance or functional testing of a web application with a Flex front end. I wanted to solve this problem because functional testing increases confidence that the software meets customers' requirements. Automating the tests - coding tests and running them as part of the build - pays dividends over and over, as agile developers well know. We're able to check that user stories are implemented and catch bugs early in the lifecycle.

Kieran's blog entry unit testing Flex tells how he solved the problem of writing and automating unit tests for Flex front-ends. He found there was little available material on unit testing for Flex - and I found even less on acceptance testing for Flex. However, we had done automated acceptance testing for non-Flex web apps.

Selenium is a popular tool in the open source community for automating functional tests for web applications. It allows developers to write tests that drive your web application via the browser. You can write tests in various languages, including Java and JavaScript, and in the test you can manipulate web page components using XPath or JavaScript. So for example I can write a test to enter text into an input element of an HTML form, click the submit button, and verify data on the response page. But how can I do the same sort of thing for a Flex front-end?

I need to be able to manipulate the Flex components of the application. I found two software tools which should help, FlashSelenium and Selenium Flex API.

FlashSelenium is an extension to the Selenium client Java driver that allows a Java test class to call ActionScript methods of the Flex application. These ActionScript methods must be exposed by the Flex developer using the Flex ExternalInterface API to write explicit callbacks into the Flex code under test. The ExternalInterface API allows two-way interaction between JavaScript and ActionScript. FlashSelenium converts the developer's Java test code into JavaScript which the Selenium Remote Control server fires at the Flex application. This looks promising. But there is a big drawback to this approach: I'd have to write extra Flex code for all the callbacks that I want to make, and maybe even extra custom ActionScript methods to support the testing. I'd really like to be able to call general methods to manipulate UI components and inspect values.

Selenium Flex API is an extension to Selenium IDE, a Firefox plug-in which allows interactive testing of web applications. It consists of two parts, ActionScript methods that access MXML components and JavaScript extensions to Selenium IDE to call those ActionScript methods. The developer includes the ActionScript methods in the Flex code under test. The JavaScript extensions then allow a tester to interact via Selenium IDE with the Flex app. Selenium Flex API, like FlashSelenium, uses the Flex ExternalInterface API to facilitate interaction between JavaScript and ActionScript. It exposes a limited number of ActionScript methods for interaction and requires fewer intrusive additions to the code under test: no custom Flex code for testing has to be written. But the major drawback from my point of view is that the testing is not automated, but performed using Selenium IDE. I want to be able to use Selenium Remote Control to run my tests for me.

What I'd like to be able to do is:

  • to write functional tests in Java
  • to run those tests automatically
  • to minimize additions to the application code

If I can integrate FlashSelenium with the Selenium Flex API ActionScript methods, I have a solution. I'll be able to write JUnit test classes using FlashSelenium that call the Selenium Flex API ActionScript methods to manipulate my Flex app. Then I can use Selenium Remote Control to drive my tests. And I will be able to run the whole lot with ant.

JUnit test class --> FlashSelenium --> Selenium-RC Java client --> Selenium-RC server --> Flex app + Selenium Flex API

Here's the JUnit set up code of my test class.

private final static String URL = "http://localhost:8080/MyFlexApp.html";

public void setUp() throws InterruptedException
{
    selenium = new DefaultSelenium("localhost", 4444, "*firefox", URL);
    selenium.start();
    flashApp = new FlashSelenium(selenium, "MyFlexSWF");
    selenium.open(URL);
    while (flashApp.PercentLoaded() != 100)
    {
        Thread.sleep(1000);
    }
}

This method creates a Selenium object selenium that connects to a local tomcat instance hosting my flex app, and a FlashSelenium object flashApp that allows calls to components of the app.

Here's one of my test methods. This method uses the FlashSelenium object flashApp to make calls to the Selenium Flex API methods getFlexText() and doFlexClick().

public void testInvalidLogin() throws InterruptedException
{
    assertEquals("", flashApp.call("getFlexText", "userName", ""));
    assertEquals("", flashApp.call("getFlexText", "password", ""));
    flashApp.call("doFlexClick", "submit", "");
    Thread.sleep(2000);
    assertEquals("Invalid username or password", flashApp.call("getFlexText", "loginmesg", ""));
}

The purpose of this method is to test that an attempt to log in with no username and password will cause an "Invalid username or password" message to be shown. The Flex app contains a couple of text input fields, userName and password, a submit button submit, and a label field loginmesg for display of error messages.
The test gets the text value of the userName field with this call:

flashApp.call("getFlexText", "userName", "")

and verifies that it's empty, then does the same for the password field.
Next it clicks the submit button:

flashApp.call("doFlexClick", "submit", "");

and finally checks that the loginmesg field's text value is as expected.

Because I can now write JUnit tests, it's straightforward to automate running the tests with an ant target of the usual JUnit ant task flavour. For my app, the development environment against which to run this ant target consists of a MySQL database and an instance of tomcat hosting the (Java) web app and the Flex front end (swf and HTML). This entry covers adding the test execution to the Hudson continuous integration process. Meanwhile I'm very pleased to be able to add automated functional tests to our Flex project's quality assurance efforts.