Sunday, December 13, 2009

FoneMonkey: Open Source, Testing Tool for iPhone Applications

This blog post is the first announcement to the world of FoneMonkey, an open source iPhone testing tool that I've been developing for the last several months. FoneMonkey automates iPhone application testing by recording and playing back user interactions, and verifying the results. FoneMonkey was inspired by FlexMonkey, the open source Flex testing tool I wrote a little more than a year ago, and which has subsequently been significantly enhanced by my colleagues at Gorilla Logic, especially Eric Owens. Today FlexMonkey has more than 4,000 registered users and an active community.

We plan to release FoneMonkey source and binaries (with attendant fanfare) in early January. Here's a sneak preview of what's coming.

Some Technical Background

FoneMonkey has been more challenging than FlexMonkey to create because the iPhone SDK, unlike the Flex SDK, provides no Automation API. Before I could develop FoneMonkey, I had to develop an automation framework. The resulting FoneMonkey API is simple, extensible and initially supports nearly all native iPhone (ie, Cocoa Touch) components.

Like FlexMonkey, FoneMonkey is designed to be used by both programmers and QA testers. Rather than simply recording and playing back low-level events, FoneMonkey records "semantic" events. In other words, FoneMonkey doesn't record that you touched a pixel at coordinate (125, 210), but instead records that you selected table row 5. The resulting scripts are relatively forgiving with respect to cosmetic UI changes. They can also be composed from scratch by directly specifying sequences of commands. (FoneMonkey Command Guide coming soon....).

Each FoneMonkey command is composed of a command name, a component identifier, and a set of command-specific arguments. For example:

Touch UIButton Send (touches the UIButton labeled "Send")
InputText UITextField, your name, Fred (types "Fred" into the UITextField with a field prompt of "your name")

The Flex Automation API provides an AutomatDelegate corresponding to each Flex UIComponent, and a delegate instance is created for each UIComponent instance created at run-time. Automation delegates subscribe to their component counterparts for all UI events, and translate these low-level keyboard and mouse events into high-level component events. FoneMonkey uses a logically similar mechanism, but is instead implemented with Objective-C categories that extend UI component classes with record and playback logic.

While recording, the FoneMonkey framework monitors all UI events and forwards them to the FoneMonkey category methods that provide recording for each component class. During playback, FoneMonkey sends each command to the playback methods also provided by the class's FoneMonkey extension category.

The FoneMonkey framework provides categories that record and play back events for instances of the UIView class and all UIView subclasses. It is straightforward to create a category for any custom UI class that requires custom recording and playback logic, or to further enhance the recording and playback logic provided out of the box by the FoneMonkey framework. (FoneMonkey Extension Guide coming soon....)

Using FoneMonkey

To test an application, you simply statically link it with the FoneMonkey library. (FoneMonkey Setup Guide coming soon....) Upon starting your application, the FoneMonkey Console "drops down" over your application window, displaying the recording and playback controls at the bottom of the screen.


The Elements application



The Elements application with FoneMonkey controls (at the bottom).


The video below shows FoneMonkey being used to test Apple's "The Elements" sample application.

In the video, we touch the record button to hide the FoneMonkey Console and begin recording our interactions with "The Elements" application. FoneMonkey monitors for periods of inactivity and drops back down over the application if we stop interacting with it for more than the current inactivity timeout setting (by default, 2.5 seconds). Touching the play button replays the recorded script.

You might need to view this video in a new window.


FoneMonkey provides the ability to edit scripts and save them for later replaying.


The FoneMonkey script editor

You can add Verify commands to a script to test the values UI component properties or the values of associated object properties (ie, you can use a key-value encoded key path) . In The Elements sample application, a custom class called AtomicElementView is used to display data for the currently selected element. The AtomicElementView has a property called element that references an instance of the AtomicElement class, which in turn as a property called name. In the Verify command below, we test that the current AtomicElementView's element.name has a value of "Lead".

Adding a Verify command to a script

Script results with failed Verify (in red)

The next video shows how to edit a script, add a verify command, save the modified script, and then replay it.

You might need to view this video in a new window.



Over the next several weeks I'll be continuing to update the doc in preparation for our putative January launch. Stay tuned.

No comments: