FunFX is a framework that is composed of two parts, one adapter (the last post talked about this part) that enables the Flex application to be tested, and one Ruby framework that enables you to drive an Internet Explorer instance with the Flex application.
Some people ask me if there is an easy way to implement support for either FireFox or other browsers, and the answer to this is both yes and no. It depends, there are currently only IE that is implemented and the reason for this is IE's support for COM objects. I will explain this implementation in a bit more detail in another post.
This post will talk about the Ruby framework mentioned in the beginning. This Ruby framework is a Ruby gem. This framework creates an instance of a Internet Explorer window. Then with some initializing methods you will direct the IE window to the address of the Flex application.
This is shown in the follwoing table. The first sentance creates an instance of FunFX. When executing the second line with the start method FunFX creates an instance of IE in the background with the help of Win32OLE. The argument tells FunFX if you want the IE to be visible or not.
@ie = Funfx.instance
@ie.start(true)
@ie.speed = 1
@ie.goto("http://localhost/flexapplication.html", "flexapplication")
@ie.start(true)
@ie.speed = 1
@ie.goto("http://localhost/flexapplication.html", "flexapplication")
The last sentance in the initialization is the method that directs the browser to the Flex application and hooks on to the actual Flex object with the help from Win32OLE, and the name of the swf file. If you have an html file named index.html that contains a swf file that is named flexApp.swf and is located at http://localhost/flexapplication/index.html. The
@ie.goto("http://localhost/flexapplication/index.html", "flexApp")
After this initialization, the @ie variable (which is an instance of FunFX) is ready to interact with the Flex application.
The FunFX in itself does not test Flex applications in the sence of asserts, it just enables you to drive an Flex application programmatically and get the state and text of all display objects. To make assertions and create test scripts you will need to use FunFX together with a testing framework of your choice. A couple of examples are RSpec, and Test::Unit. FunFX together with any of these tools make up an automated functional testing tool.
Before I will show you an example of FunFX together with these tools, I will explain in short how to use FunFX in the sence of driving the Flex application programmatically.
A Flex application is built as an hierarchy of different display objects, with the Application object as the root node. With FunFX you can think of @ie the root node of the Application object.
An example of interacting with a display object is shown in the box below.
@ie.button("buttonName").click
This line of code will click the button with id or label named "buttonName". This button can be located anywhere in the Flex hierarchy. In version 0.0.1 FunFX only supported single elements, and then it stopped when it found a object matching this signature. But this was a problem with repeaters, which creates children with the same id's.
So in 0.0.2 it finds all objects that matches that type and name, and delivers them as an array, as shown below:
@ie.button("buttonName")[0].click
To interact with a display obejct you must provide the label or id.
Some flex event needs arguments as when inserting text into a textbox. This is done as follows:
@ie.text_area("price").input(:text => "This is the new text")
@ie.data_grid("gridName").drag_start(:dragged_item => "Name of item")
@ie.data_grid("gridName").drag_drop
@ie.data_grid("gridName").drag_drop
There are many more methods. Unfortunately there are no good overview of all the methods and their arguments. But you should look at the AutomationGenericEnv.xml, which describes all the display object types and their events and arguments.
When testing the functionality of an application it does not help being just able to drive the application. It must be possible to extract some information to assert with a testing tool such as RSpec or Test::Unit.
You can get information about alot of thing, such as visibility, text, rows in a datagrid, enabled etc. These are called properties and are also described in the AutomationGenericEnv.xml.
The following displays some examples of extracting data. It is possible to extract the selected index of an data grid, making it possible to extract information about that grid line with the tabular_data property. This creates a comma separated string containing the row information. If there are images in the row, the name of the images will be displayed.
pos = @ie.data_grid("gridName").selected_index
@ie.data_grid("gridName").tabular_data(:start => pos)
@ie.label("labelName").text
@ie.application("applicationName").current_state
@ie.data_grid("gridName").tabular_data(:start => pos)
@ie.label("labelName").text
@ie.application("applicationName").current_state
I have not yet tried how this works with the new upgraded grid in Flex 3.
The following is an example test that tests an flex application that adds a product to a datagrid with the use of an popup window. This test is test nr 1 at the bottom of this post.
require 'test/unit'
require 'funfx'
class TestProductOne <>
def setup
@ie = Funfx.instance
@ie.start(true)
@ie.speed = 1
@ie.goto("http://funfx.rubyforge.org/Flex/FlexRepeater.html", "FlexRepeater")
end
def teardown
@ie.unload
end
def test_insert_product
assert_equal(0, @ie.data_grid("dgOffer").num_rows)
add_product("Shirt", "Tennis")
@ie.button("bOk").click
assert_equal(1, @ie.data_grid("dgOffer").num_rows)
end
def add_product(name, category)
@ie.button("bAddProduct").click
@ie.text_area("tName").input(:text => name)
@ie.text_area("tCategory").input(:text => category)
end
end
require 'funfx'
class TestProductOne <>
def setup
@ie = Funfx.instance
@ie.start(true)
@ie.speed = 1
@ie.goto("http://funfx.rubyforge.org/Flex/FlexRepeater.html", "FlexRepeater")
end
def teardown
@ie.unload
end
def test_insert_product
assert_equal(0, @ie.data_grid("dgOffer").num_rows)
add_product("Shirt", "Tennis")
@ie.button("bOk").click
assert_equal(1, @ie.data_grid("dgOffer").num_rows)
end
def add_product(name, category)
@ie.button("bAddProduct").click
@ie.text_area("tName").input(:text => name)
@ie.text_area("tCategory").input(:text => category)
end
end
This post is a bit messy, but i tries to explain some of the basic elements. The following post will try to explain other concepts in more detail.
I have put out an test application that set up for testing with a couple of simple actions to perform at TestApplication. At the following links I have also written a couple of tests that test this application. Please try them out and alter them to see if you get it going (the source code of the view files are available at view source, or this address source-code).
I hope this test application and test scripts help you to get going.