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 user name 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.
P.S. Here's the SeleniumFlexAPI.as file of ActionScript code that I included in my Flex mxml code.

Excellent post. Seems to be the best Flex app integration testing plan out there now and could close a serious continuous integration testing hole we've got when developing BlazeDS/Spring applications. It would be nice if Selenium Flex API got their recording feature out the door soon, though :) No complaints and good work all around :)
You might also want to check out FlexMonkey, an open source Flex GUI testing tool just open sourced by Gorilla Logic. It provides comprehensive record/playback and generates Action-script based tests that can be managed from xUnit frameworks such as FlexUnit.
http://flexmonkey.googlecode.com
Excellent post indeed!
We are using Selenium-RC's ruby client driver. Any idea how we can integrate the Selenium Flex API to it?
In this example, the SeleniumFlash object is calling the methods/functions from Selenium Flex which is a user extension for Selenium IDE. How did you integrate the javascript file to your JUnit test class? import maybe? Any idea how it can be integrated with ruby's test unit?
Great post!
I noticed in your SeleniumFlexAPI.as that you added some support for DataGrids which is great, but I was wondering if anyone has solved the problem of getting the UIComponents of a DataGrid. I've been trying for the last couple of days without success.
The example in the SeleniumFlexAPI.as only gets the data which is helpful, but the ItemRenderer of the DataGridColumns might do something with the data and a tester might want to verify the rederered value.
Thanks in advance for any suggestions!
Hi.. I found it to be very useful information.
I have query. please if anyone can help on it..its urgent..
i ahve to test Flex application using selenium.
I have downloded both FlashSelenium and Selenium Flex API .
but to get Flex objects identified by selenium, we have to add some special code to flex . What is this code , can anyone tell .

