FONEMONKEY

63
FONEMONKEY QUICK TUTORIAL This QuickStart demonstrates using FoneMonkey with Apple's sample application, TheElements . By following along, you should be you up and running with FoneMonkey in a matter of minutes! Preparing Your Application For Testing Before you can begin using FoneMonkey, you must link the FoneMonkey framework into your application. Starting FoneMonkey with Your Application Once your application has been linked with the framework, whenever you launch your application the FoneMonkey console will "drop down" in front. Recording Click the Record button to hide the console and begin recording. FoneMonkey will record most user interface event types including touching, dragging, scrolling, and

Transcript of FONEMONKEY

Page 1: FONEMONKEY

FONEMONKEY

QUICK TUTORIAL

This QuickStart demonstrates using FoneMonkey with Apple's sample application, TheElements. By following along,

you should be you up and running with FoneMonkey in a matter of minutes!Preparing Your Appl icat ion For Test ing

Before you can begin using FoneMonkey, you must link the FoneMonkey framework into your application.Start ing FoneMonkey with Your Appl icat ion

Once your application has been linked with the framework, whenever you launch your application the FoneMonkey

console will "drop down" in front.

Recording

Click the Record button to hide the console and begin recording. FoneMonkey will record most user interface event

types including touching, dragging, scrolling, and typing. If you stop interacting with the application for more than the

timeout interval (2.5 seconds by default), the FoneMonkey console will again be displayed.

Touch the More button to display the recorded commands.

Page 2: FONEMONKEY

Playing

Touch the Play button to play the script. The FoneMonkey console will hide and FoneMonkey will generate user

interactions corresponding to each recorded command. It is important to note that FoneMonkey will not automatically

restore your application to its starting state before playing a script. The application must be in a state such that the

script makes sense. For example,TheElements has tabs that display the table sorted by element name or symbol. If

Page 3: FONEMONKEY

you record a script that assumes the application is displaying the the Name tab when it begins, you must ensure

the Name tab is being displayed before playing the recorded script. One way to do this is to record touching

the Name tab as the first action in the script.

You can touch the Pause button to hide the console and manipulate your application without recording.Video of Recording and PlaybackAdding Ver i f icat ion to The Scr ipt

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) . To insert a Verify command, touch the More button

to display the current script and then touch the Insert (+) button on the toolbar. Next touch the Insert (+) button on a

row to insert a new Verify command and display it in the command editor.

In TheElements 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".

Page 4: FONEMONKEY

Touch the Play button to run the script. When the script finishes running, any faiiled verifications will be displayed in

red with along with explanatory text.

Page 5: FONEMONKEY

You can save a script for later replay by clicking on the Save button (the downarrow) on the toolbar.Video of Insert ing a Ver i f icat ion Command And Saving a Scr ipt

 Wait ing for Some Condit ion to Become True

Page 6: FONEMONKEY

The WaitFor command is similar to the Verify command, except it pauses script execution until the specified condition

becomes true.

SET UP AND BUILD

Add FoneMonkey to project

1. Download and unzip the FoneMonkey.zip file.

2. Open your application's project in xcode.

3. Duplicate your application's build target by right-clicking on it and selecting Duplicate from the menu. A

new target will be created called YourApp copy.

Rename YourApp copy to something like YourAppMonkey.

Page 7: FONEMONKEY

so it looks like this:

4. Add the downloaded FoneMonkey folder to your project by right-clicking on the project and

selecting Add > Existing Files...from the menu.

Page 8: FONEMONKEY

 

5. When the dialog box appears, navigate to the directory where you unzipped the FoneMonkey.zip file,

and select the FoneMonkey directory.

6. Recursively create groups for any added folders option. Note: It is up to you whether or not you

want to Copy items into destination group's folder.

7. In the Add to Targets box, deselect YourApp and select YourAppMonkey.

Page 9: FONEMONKEY

8. Click Add.

9. The FoneMonkey folder should now be visible in your project.

Configure library and build setting

1. Right-click on the YourAppMonkey build target, and select the Build Phases tab.

2. On the Link Binaries With Libraries tab, you will need to

add CoreGraphics.framework and QuartzCore.framework if your application is not already using them. (These

frameworks are required by the FoneMonkey console.) 

Page 10: FONEMONKEY

 

3. XCode will have added references to the libFoneMonkey.a and libFoneMonkeyOCUnit.a library. If you do not plan to

use OCUnit for automated testing, you can remove the libFoneMonkeyOCUnit..a library.

If you do not remove libFoneMonkeyOCUnit.a, you will also need to

include libxml2.dylib and SenTestingKitFramework. SenTestingKitFramework is included with Xcode but will not

be listed in the dialog where you add frameworks and libs to your project. You must instead click "Add Other..." and

navigate to /Developer/Library/Frameworks where you can select the SenTestingKitFramework folder.

 

Page 11: FONEMONKEY

4. On the Build Settings tab, scroll down to the Linking section and set Other Linker Flags to:

            -all_load

Build and go

Select the YourAppMonkey Scheme for building in the drop-down. (If you did not rename this scheme, it may still be

calledYourApp copy)

Page 12: FONEMONKEY

Right-click on YourAppMonkey build target and select Clean from the menu.

Right-click on YourAppMonkey build target again and select the Run button (or Build and Run or Build and

Debug from the menu). FoneMonkey can be launched in either the simulator or on an iPhone device.

Page 13: FONEMONKEY

Your application should start. Immediately after it displays, the FoneMonkey console should drop down in front of

your application's window.

Page 14: FONEMONKEY

Start testing!

USER GUIDE

You use the FoneMonkey Console to create, manage, and run FoneMonkey tests.

Page 15: FONEMONKEY

When you launch an application that has been linked with FoneMonkey, the FoneMonkey Console is displayed on

top of the application’s window.

RECORDING AND PLAYBACK

You use the FoneMonkey console to create, manage and run test scripts.

Record

Page 16: FONEMONKEY

To begin recording, touch the Record button. The FoneMonkey console will hide and you can manually test your

application. As you interact with it, FoneMonkey records FoneMonkey commands corresponding to each user

interface gesture.

Pause

If you stop interacting with the application for longer than the timeout interval (by default, 2.5 seconds), the

FoneMonkey console will reappear on top of your application window.

If you are not yet done recording, click any where over the application to hide the FoneMonkey console and resume

recording.

Touching the Pause button hides the FoneMonkey window and lets you interact with your application without

recording. The console will reappear after the timeout interval. Touch anywhere on your application to re-hide the

console and continue without recording.

Playback

Touch the Play button to play back a script. The console will hide and FoneMonkey will generate user interface

interactions corresponding to each command. When playback is complete, the console will be redisplayed.

Adding verification

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) . To insert a Verify command, touch the More button

to display the current script and then touch the Insert (+) button on the toolbar. Next touch the Insert (+) button on a

row to insert a new Verify command and display it in the command editor.

Use the first argument to specify a string-valued property expression and the second argument to specify the

expected value.

Page 17: FONEMONKEY

Playback option

Page 18: FONEMONKEY

To manage your playback options, simply tap on the “Playback Options” button from within the console.  The default

selection is “Recorded Speed”, which uses per command values as a guide to the rate of playback.  Once you have

set your playback options, they will be remembered for future tests.Recorded Speed

When you record your scripts with FoneMonkey, we timestamp each command and set the playback speed of each

command based on the timestamp.   You can specify a percentage value and the script will playback at that speed.  If

no value is specified, the script will play at 100%. Fixed Speed

“Fixed Speed” overrides per command options, therefore per command playback options are only used when using

the “Recorded Speed” playback option.  When you choose Fixed Speed playback, your script will playback with a set

interval between commands (fixed speed) with a set timeout before failure.  Values are set in milliseconds and if you

do not set a value, fixed speed defaults to 500 milliseconds with a 0 millisecond timeout.

Page 19: FONEMONKEY

 

Page 20: FONEMONKEY
Page 21: FONEMONKEY

 

Wait for True condition

The WaitFor command will pause execution until some condition becomes true. For example, if your application

makes a requests remote data, and when that remote data is returned a Done button appears on the screen, you

could force your script to wait for the button to appear before continuing execution with a command such as:

WaitFor UIButton "Done"

You can add a WaitFor by adding a Verify command, and then change the command name from Verify to WaitFor.

The first and second arguments specify a property-value pair . The third argument is optional and specifies a timeout

in milliseconds. The default timeout is 500 milliseconds. If you are waiting for some component to appear without

regard for any particular property-value pair, you can specify no arguments, or just the first argument if you wish to

set a timeout value.

SCRIPT EDITTING

Page 22: FONEMONKEY

Touch the More button to view the list of recorded commands.

Commands are displayed in the Command List table.

Set timeout interval

When recording or pausing, FoneMonkey waits for a period of inactivity equal to the timeout interval before

redisplaying the FoneMonkey console.

The Timeout slider can be used to set the timeout interval anywhere from 2 to 10 seconds. If the console is

reappearing more quickly than you want it to while the console is recording or paused, make the timeout longer.

Edit commands

To edit a command, touch the Edit button on the row in the command list to be edited. The Command Editor will be

displayed.

Page 23: FONEMONKEY

Using the command editor, you can change the Command, Component Class, Monkey ID, or any of the associated

parameters. When you’re finished editing, touch the Done button.

Insert & Edit commands

Commands can be inserted and deleted using the Insert and Delete toolbar buttons, which display the Insert or Delete buttons in each row of the displayed script.

Save a script

To save a script, touch the Save Script button. The Save Script dialog will be displayed.

Page 24: FONEMONKEY

Enter a name for the script and hit the Save button. Scripts are saved in the application's Documents directory.

Run a saved script

To run a saved script, touch the Open Script button. The Saved Script List will open displaying all saved scripts.

To open a script, touch its name in the list. The script will open in the console and can be played and edited.

Record new script

To clear the currently opened script and begin creating a new one, click the Open Script button and then touch the New button displayed above the Saved Script List.

Page 25: FONEMONKEY

Delete a saved script

To delete a saved script, touch the Open Script button and then click the Edit button displayed above the Saved Script List. You may then delete a saved script by touching the associated Delete Icon.

RUNING FONEMONKEY WITH OCUNIT

OCUnit (also known as SenTestingKit) is a unit testing framework for Objective-C that's bundled with the XCode

IDE. As a member of the xUnit family of testing frameworks, OCUnit is similar to other popular frameworks such as

JUnit (for Java), and FlexUnit (for Adobe Flex).

Using OCUnit, you can combine FoneMonkey- and non-FoneMonkey-based tests into comprehensive test suites that

can be invoked interactively, as well as from build scripts, and from continuous integration frameworks such

as Hudson or Cruise Control. It is also possible to combine OCUnit tests with non-OCUnit (for example, JUnit) tests,

and combine the output so as to provide considated test reporting across all front- and back-end components of your

application.

Please note that to run FoneMonkey with OCUnit, you should not create a testing bundle. Instead, you use

the FoneMonkeyOCUnitplug-in to launch your OCUnit tests cases, as described later in this section.

OCUnit test output will be written to the console. You can optionally write out the results in XML format.

Adding OCUnit to project

You add OCUnit to your project much in the same way you add any framework.

Right click on the target that includes FoneMonkey, and select Get Info from the menu. The Target Info dialog will

be displayed.

Add a new entry to the Linked Libraries by clicking the add (+) button at the bottom of the dialog window. A

selection dialog will open.

Click the Add Other... button. A file selection dialog will open.

Navigate to the  /Developer/Library/Frameworks folder. Select SenTestingKit.framework.

Click the Add button.

Add FoneMonkeyOCUnit plug-in

The FoneMonkey distribution includes libFoneMonkeyOCUnit.a which is a static library that extends FoneMonkey with an OCUnit test launcher. To run tests under OCUnit, add this library to your project's linked libraries. You will also need to add SenTestingKit.framework to your project.

Write a test case

Page 26: FONEMONKEY

You write your test cases for FoneMonkey in the same way you write any OCUnit test. To create a test case, simply

subclass SenTestCase and use STAssertions to test for expected results. For more information on OCUnit

(SenTestingKit), see Apple's Documentation.

Using the FoneMonkey API, you can run FoneMonkey commands from within your test case, and you use OCUnit

Let's look at an example:

#import <SenTestingKit/SenTestingKit.h> #import <UIKit/UIKit.h>#import "FoneMonkeyAPI.h"

@interface SampleTest : SenTestCase

- (void) testSample;

@end

@implementation SampleTest

- (void) testSample { NSString* lastResult = [FoneMonkeyAPI playFile:@"Test1"]; STAssertNil(lastResult, lastResult);}

@end

FoneMonkeyAPI.h can be found in the include folder of the FoneMonkey distribution download.

You run a FoneMonkey script from a test case by calling runScript:(NSString*)script, where script is the name of a 

FoneMonkey script stored in your application's Documents directory. runScript: returns nil if the script runs

successfully. For example, in the script above we call: NSString* lastResult = [FoneMonkeyAPI playFile:@"Test1"];

If the script fails for any reason, runScript: returns the message generated from a failed Verify command, or other

error message. You need to explicitly add an assertion to test for a non-nil result, and display the returned message if

it's non-nil as follows:

    STAssertNil(lastResult, lastResult);

You can of course do more in your test case than simply run a script and test its result. You can include addition

programming logic and assertions, and run multiple scripts.

Using the FoneMonkey API, It is also possible to build scripts programatically at run time, rather than running a script

previously saved.

Create XML result files and screenshots

When running FoneMonkey under OCUnit, test results will be written to the console. You can also create XML

formatted test results and save screenshots of your running tests as described below.Saving Test Results as XML

Page 27: FONEMONKEY

Setting the FM_ENABLE_XML_REPORT environment variable will result in FoneMonkey saving test results in XML

format to your application's Documents directory.Saving Screenshots of Running Tests

FoneMonkey will write out screenshots of your running application by setting the FM_ENABLE_SCREENSHOT

environment variable. Three values are currently supported:

FAILURE - writes out a screenshot each time a script failure occurs

ALL - writes out a screeshot after each command is executed

NONE - no screenshots will be written

Create test runner target

You can create an Xcode target that builds your app and then runs your FoneMonkey OCUnit tests. You can run this

target from the command line within external build management systems or continuous integration environments

without having to start Xcode.

Create a duplicate target of your FoneMonkey test target. If your test target did not already include

libFoneMonkeyOCunit.a, you must add it to the new target as described here.

Name the new target something like MyAppTestRunner.

Open the Build Phases tab for the newly created target.

Click on Add Build Phase and then Add Run Script.

 

Page 28: FONEMONKEY

'

Copy the following into the new script body:

 export FONEMONKEY_HOME=~/Documents/Projects/fonemonkey/FoneMonkey/Dist/FoneMonkey export FAMILY=ipad export LOG_FILE="$PROJECT_DIR/$TARGETNAME.log"export FONEMONKEY_ENV=$FONEMONKEY_HOME/FoneMonkeyRunner.plist

rm -f "$LOG_FILE" 

$FONEMONKEY_HOME/bin/iphonesim launch "$CODESIGNING_FOLDER_PATH" -verbose -sdk

$IPHONEOS_DEPLOYMENT_TARGET -family $FAMILY -stderr "$LOG_FILE" -env "$FONEMONKEY_ENV"

 

 

 

Page 29: FONEMONKEY

 

 

Change FONEMONKEY_HOME to point to your unzipped FoneMonkey.zip folder

The results will be written a file called YourTargetName.log in your project's root directory. You can change

LOG_FILE to point to any preferred name or location for the output results.

Build (don't Run) the target

Your application will build, and then the new script step will invoke the open source utility iphonesim to install and run

your app in the simulator. Your tests will run immediately after the app is opened in the simulator.

 

If you want the application to terminate after the tests have run, define the environment variable

FM_ENABLE_AUTOEXIT. Although this won't terminate the simulator, it will terminate the build step so that you can

rerun without having to stop the previous build first. Environment variables are set via the plist file specified by

FONEMONKEY_ENV. The script above points to a plist file located in the FoneMonkey distribution directory. You can

edit this file directly using Xcode's plist editor, and you can of course change the name or location of the file and then

update the environment variable in the script accordingly.

Environment variables must be set by using Xcode's property list editor to modify the FoneMonkeyRunner.plist file

located in the root of FONEMONKEY_HOME. If you'd prefer a different plist name or location, modify the location

Page 30: FONEMONKEY

referenced by the -env argument in the above script. Setting FM_ENABLE_XML_REPORT will save the test results

in XML format in your application's Documents directory.

In addition to running the target from within xcode, you can also run the target from the command line using

the xcodebuild command.

Running with QUnit

QUnit is a JavaScript test suite similar to JUnit with distinguishing functionality allowing FoneMonkey to execute tests

written in JavaScript from a UIWebView.

QUnit facilitates the ability to create comprehensive test suites in JavaScript that can be attached to build targets and

invoked interactively, via build scripts or from continuous integration frameworks (Hudson or Cruise Control).

Test output from QUnit tests is written to the console. Setting the FM_ENABLE_XML_REPORT environment variable

to YES will write out the results in XML format.

When the QUnit test is completed on the device or in the simulator, results from the test will be presented in the

console. A script button will also be added to the timer toolbar to access those results from the console.

Page 31: FONEMONKEY
Page 32: FONEMONKEY

Writing a QUnit test case

You write QUnit tests for FoneMonkey the same way you would write any other QUnit test.  Using the FoneMonkey

QUnit API, you can run FoneMonkey commands from within test cases.  For simplicity, the API will handle assertions

associated with the results from playing commands.  Here is an example:$(document).ready(function(){module("SampleTest");asyncTest('testSomething', function() {    commandList = new CommandList();    commandList.add("Touch", "UITableViewCell", "Buttons", "5", "20");    commandList.add("TouchLeft", "UINavigationBar", "Buttons", null);    commandList.play();})});

 

In this example:commandList = new CommandList();

- creates a new CommandList object to add commands to / play those commandscommandList.add("Touch", "UITableViewCell", "Buttons", "5", "20");

- adds "Touch" command to the "UITableViewCell" with the MonkeyID "Buttons" with arguments  "5" and  "20"commandList.play();

-  plays the list of commands in the commandList  object

 

A continuation function can be added to commandList.play() as an argument which will be played once the

commands are done playing.  As an example:// Within asyncTestcommandList.play(playAnotherList);function playAnotherList(){    newList = new CommandList();    newList.add("Touch", "UITableViewCell", "NotButtons", null);    newList.add("TouchLeft", "UINavigationBar", " NotButtons ", null);    newList.play();}

 

You can also get property values of objects in your command list at specific points during playback, specifying a

variable that can be used later in your command list.  Continue to the next section for more information. 

Running QUnit tests

Adding your JavaScript test to your test target is simple and does not require adding any additional frameworks. 

First, make sure you place your JavaScript file in the Documents directory of your application (FoneMonkey logs the

path to this directory when your test target runs) 

Add the environment variable FM_ENABLE_QUNIT to your test target and set the file name as the value, including

the file extension: example.js

Page 33: FONEMONKEY

Your test target will now run the tests within example.js

CREATING A SCRIPT PROGRAMMATICALLY

You can use the FoneMonkey API to create a script. Use the FoneMonkeyAPI static playCommands method to add

commands to the current script.

/**

 Play the supplied array of FMCommandEvents.

 @return nil if all comamnds run successfully and an error or failure message otherwise.

 */

+ (NSString*) playCommands:(NSArray*)commands;

You can create an FMCommandEvent with following FMCommandEvent static method.

/**

 Create a new FMCommandEvent

*/

+ (FMCommandEvent*) command:(NSString*)cmd className:(NSString*)name monkeyID:(NSString*)id args:

(NSArray*)array;Example

- (void) testSomething {

    NSMutableArray* array = [NSMutableArray array];

    [array addObject:[FMCommandEvent command:@"Touch" className:@"UITabBarButton"

monkeyID:@"GLPaint" args:nil]];

    NSString* lastResult = [FoneMonkeyAPI playCommands:array];

    STAssertNil(lastResult, lastResult);    

}

UNDERSTAND FONEMONKEY COMMANDS

FoneMonkey records and plays FoneMonkey commands. For each kind of user interface action there is a

corresponding command. Some examples of commands are Touch, Scroll, and Shake. FoneMonkey commands

can be stored and run from script files, or can be created programatically via the FoneMonkey API.

Commands are written as:

CommandName ComponentType "MonkeyID" Parameters, ...

where

CommandName identifies the command to be executed.

ComponentType is the Objective-C class name (or any super class name) of the component to receive the

Page 34: FONEMONKEY

command. If componentType is omitted, it defaults to UIView (ie, any component).

"MonkeyID" is a quoted string that uniquely identifies which instance of the component's class should receive the

command. If there is only one instance of a particular type, monkeyID may be omitted.

Parameters, .... are zero or more command-specific parameter values in CSV format.

Parameters are often optional for a particular command. For example, the Touch command takes 2 arguments

corresponding to the x,y coordinate of the touch event within the view. If you specify a Touch command without any

parameters, the Touch will be located in the center of the view.

If you're unsure of what command to use to generate a desired UI operation, simply start the FoneMonkey recorder

and record the action.

By overriding recording and playback methods, it's easy to add your own commands to FoneMonkey or customize

existing commands. See the FoneMonkey Extension Guide for more information.

Some Command Examples

Touch the "Done" button:

Touch UIButton "Done"

Touch the PaintingView at coordinate (25, 75):

Touch PaintingView 25, 75

Enter fred into the "First Name" field:

InputText UITextField "First Name" fred

Identify components in commands

Commands correspond to user interface actions, and actions are directed to components. For example, a command

might specify toTouch a UIButton. If there is only one UIButton on the screen, FoneMonkey knows which button the

command is referring to. If there are multiple buttons, however, we must tell FoneMonkey which one we mean. In

addition to the component's Objective-C class name, and a unique identifier called a monkeyID (generated by

FoneMonkey). For any command, you can specify just a className or a monkeyID, or you can specify both.

Component Identification Examples

If there are multiple buttons on the screen:

Touch UIButton "Done"

If there is just one button on the screen:

Touch UIButton

If threre is just one button on the screen with a monkeyID of "Done":

Touch "Done"

Understanding MonkeyID's

FoneMonkey's UIView extensions provide the default monkeyID for all components. By default, the monkeyID of a

component is the value of its:

Page 35: FONEMONKEY

accessbilityLabel property, if one exists

its tag property, if it's non-zero

and otherwise FoneMonkey generates a unique identifier as explained below.

Many component types provide specialized monkeyID's. For example, UIButton returns its titleLabel.text as its

monkeyID, and UITextField returns its placeholder value.

See the FoneMonkey Command Reference for a description of the monkeyID's returned by each component type.

If a component provides no monkeyID, FoneMoney generates an identifier by assigning an ordinal to each instance

of each class on the screen. FoneMonkey generated monkeyID's are prefix with a #-sign.

Examples of Generated MonkeyID's

Touch the first button:

Touch UIButton #0

Touch the second button:

Touch UIButton #1

Understanding MonkeyID’s

FoneMonkey's UIView extensions provide the default monkeyID for all components. By default, the monkeyID of a

component is the value of its:

accessbilityLabel property, if one exists

its tag property, if it's less than 0

and otherwise FoneMonkey generates a unique identifier as explained below.

Many component types provide specialized monkeyID's. For example, UIButton returns its titleLabel.text as its

monkeyID, and UITextField returns its placeholder value.

Please note that for the accessibilityLabel to be recognized, you must enable accessibility by editing the

file ~/Library/Application Support/iPhone

Simulator/User/Library/Preferences/com.apple.Accessibility.plist and setting

the AccessibilityEnabled andApplicationAccessibilityEnabled properties to true. You also need to edit the same

settings in ~/Library/Application Support/iPhone

Simulator/<YourSDKVersion>/Library/Preferences/com.apple.Accessibility.plist. Some users have additionally

reported needing to open the Settings application on the simulator and set General>>Accessibility>Accessibility

Inspector to On.

If setting the accessibility label programmatically, you also need to enable accessibiility for the element, for example:

myTextField.accessibilityLabel = @"someID";

myTextField.isAccessibilityElement = YES;

Page 36: FONEMONKEY

See the FoneMonkey Command Reference for a description of the monkeyID's returned by each component type.

If a component provides no monkeyID, FoneMoney generates an identifier by assigning an ordinal to each instance

of each class on the screen. FoneMonkey generated monkeyID's are prefix with a #-sign. The generated ordinal of a

component does not necessarily correspond to its sequential position on the screen.

Generated id's are dependent on the order in which a particular component type is added to a view, and so can

change across application runs if you rebuild your application with a modified view after recording a script. For this

reason, you should try to avoid saving scripts with generated monkeyID's. You should instead specify an

accessibilityLabel, a non-zero tag value, or override the monkeyID method as described in the next section.

Examples of Generated MonkeyID's

Touch a button:

Touch UIButton #2

Touch another button:

Touch UIButton #4

Overriding a class’s monkeyID

If a component's monkeyID is non-unique or FoneMonkey-generated (begins with a #), or if a different identifier will

make commands more readable, you can customize the monkeyID returned by a component by overriding

the monkeyID method.

For example, if your application has a custom view class, you can add a monkeyID method in a category extension

like this one:#import <UIKit/UIEvent.h>#import "FoneMonkey.h""#import "MyCustomView.h"

@implementation MyCustomerView (FoneMonkey)

- (NSString*) monkeyID { return self.lastName;}

@end

By locating the method in a class category, you can compile it into your your application's FoneMonkey test build, and

omit it from your release build.

Understanding Command Recording and Playback

Commands are sent to UI components to be executed (by the component's FoneMonkey extensions). When a

UI component receives a command, it will either handle it or send it to its superclass for handling.

Page 37: FONEMONKEY

UIView extensions provide the default implementations of recording and playback for common gestures, such as

Touch and Move, for all subclasses. Because all Cocoa Touch components inherit from UIView, its implementations

provide default recording and playback functionality for most UIKit UI components. In addition, various classes

override command implementations to specialize recording and playback for their component types. 

A particular command can be implemented by mutliple component classes. During playback a command is sent to

the component identified by a supplied class name and monkeyID. The receiving component either handles the

command itself or sends it to its superclass for execution, with the default for all components being provided

by UIView Commands.

Argument interpretation is made by the component that executes the command, and so the number and purpose of

arguments can differ according to what component the command is being sent to. For example, when used with most

types of UIViews, the Touch command takes x and y parameters. When used with a UISegmentControl, however, the

Touch command takes just one argument, which specifies the label of the segment to be touched.

You can customize command processing for some component class or add entirely new commands by implementing

one or moreFoneMonkey extensions for the class.

ENABLING RECORDING OF IGNORE EVENTS

In order to prevent the recording of spurious events, FoneMonkey, by default, filters various types of events for

various components. For example, UIView by default only records UITouchPhaseEnded events.

To enable recording of additional events for a particular class, add a shouldRecordMonkeyTouch method to the class

(or category).

For example, let's say you have a subclass of UIView called PaintingView that requires recording TouchBegin and

TouchMoved events. You could add a category method to the class as follows:#import "PaintingView.h"@interface PaintingView (FMReady)

@end

@implementation PaintingView (FMReady)

- (BOOL) shouldRecordMonkeyTouch:(UITouch*)touch {    return ([touch phase] && (UITouchPhaseBegan | UITouchPhaseMoved));}

@end

GENERATING TESTS

Whenever you save a script from the FoneMonkey console, three files are created:

Page 38: FONEMONKEY

Native FoneMonkey script file - A Cocoa Property List XML file called YourScriptName.fm that can be open and run

with the FoneMonkey console.

OCUnit source file - An Objective-C source file called YourScriptName.m that can be executed with

an OCUnit runner. You can extend the generated code with Objective-C logic to do things like looping, conditional

branching, or data-driving of your tests.

QUnit source file – A JavaScript source file called YourScriptName.js that can be executed by setting

FM_ENABLE_QUNIT environment variable with the value: YourScriptName.js – As with the OCUnit source file, you

can extend the generated code with JavaScript logic.

UIAutomation source file (DEPRECATED in FoneMonkey 5.2a – Set the FM_ENABLE_UIAUTOMATION

environment variable to generate this source file instead of the QUnit source file) - A generated JavaScript source file

called YourScriptName.js that can be executed with Apple's Automation Instrument. As with OCUnit tests,

UIAutomation tests can be customized and extended with additional control or data-driven logic. Executing

FoneMonkey's generated UIAutomation scripts does not require linking any of the FoneMonkey or OCUnit libraries

into your iOS app, so UIAutomation scripts can be run directly against applications built for release.

In addition to the three script files, FoneMonkey also copies the FoneMonkey UIAutomation support library,

FoneMonkey.js to your documents directory. This file is required for running generated UIAutomation scripts.

Please note that the FoneMonkey console can only read and run native FoneMonkey (.fm) files. Any changes you

make to generated (.m or .js) source files are invisible to the FoneMonkey console. You can however modify the .fm

file directly with a text, xml, or property list editor, and then open and run the resulting script in the FoneMonkey

console.

The three scripts are saved under your application's Documents directory.

The names and locations of the files being written when you save a script are displayed in the XCode console, for

example:2011-02-03 19:22:42.611 FoneMonkeyTestApp[35019:207] saving script "sampletest" to /Users/sstern/Library/Application Support/iPhone Simulator/4.2/Applications/C8875700-37D8-47C2-ABFC-B01B7CF3DE2C/Documents

2011-02-03 19:22:42.612 FoneMonkeyTestApp[35019:207] Writing /Users/sstern/Library/Application Support/iPhone Simulator/4.2/Applications/C8875700-37D8-47C2-ABFC-B01B7CF3DE2C/Documents/FoneMonkey.js

2011-02-03 19:22:42.614 FoneMonkeyTestApp[35019:207] Writing /Users/sstern/Library/Application Support/iPhone Simulator/4.2/Applications/C8875700-37D8-47C2-ABFC-B01B7CF3DE2C/Documents/sampletest.js

2011-02-03 19:22:42.616 FoneMonkeyTestApp[35019:207] Writing /Users/sstern/Library/Application Support/iPhone Simulator/4.2/Applications/C8875700-37D8-47C2-ABFC-B01B7CF3DE2C/Documents/sampletest.m

 

Although the Property List XML files can be easily edited by hand in any text or XML editor, it is not possible to

specify anything but sequential logic in this format. If you need to create more complex testing flows or read data from

a file or database to drive your test scripts, you need to extend your scripts by editing the generated Objective-C or

JavaScript source files.

Script Language File RunnerCan be data-driven or

extended with control logicRequires FoneMonkey Libraries for Execution

Page 39: FONEMONKEY

XMLYourScriptName.fm

Console No Yes

Objective-C YourScriptName.m OCUnit Yes YesJavaScript YourScriptName.js QUnit Yes Yes

JavaScriptDEPRECATED YourScriptName.jsInstruments

Yes No

 

Understanding generated Object-C code

Here is a sample of a FoneMonkey-generated OCUnit test:#import <SenTestingKit/SenTestingKit.h>#import <UIKit/UIKit.h>#import "FoneMonkeyAPI.h"

@interface SomeScript : SenTestCase {}- (void) testSomething; @end

@implementation SomeScript- (void) testSomething {// NSString* lastResult = [FoneMonkeyAPI playFile:@"SomeScript"];

NSMutableArray* array = [NSMutableArray array];[array addObject:[FMCommandEvent command:@"Touch" className:@"UITableViewCell"

monkeyID:@"Buttons" delay:@"500" timeout:@"0" args:[NSArray arrayWithObjects:@"98", @"21", nil]]];

[array addObject:[FMCommandEvent command:@"Touch" className:@"FunkyButton" monkeyID:@"Gray" delay:@"1182" timeout:@"0" args:[NSArray arrayWithObjects:@"40", @"24", nil]]];

[array addObject:[FMCommandEvent command:@"Verify" className:@"FunkyButton" monkeyID:@"GRAY!" delay:@"1546" timeout:@"0" args:[NSArray arrayWithObjects:nil]]];

[array addObject:[FMCommandEvent command:@"Touch" className:@"FunkyButton" monkeyID:@"GRAY!" delay:@"675" timeout:@"0" args:[NSArray arrayWithObjects:@"40", @"24", nil]]];

[array addObject:[FMCommandEvent command:@"TouchLeft" className:@"UINavigationBar" monkeyID:@"Buttons" delay:@"1443" timeout:@"0" args:nil]];

NSString* lastResult = [FoneMonkeyAPI playCommands:array];STAssertNil(lastResult, lastResult);

}@end

The script was generated when saving the script, SomeScript.fm. The generated code includes a commented out line

that, if uncommented, would run SomeScript.fm directly:// NSString* lastResult = [FoneMonkeyAPI playFile:@"SomeScript"];

The following lines creates an array of FMCommandEvents. One FMCommandEvent is created for each command

contained SomeScript.fm.NSMutableArray* array = [NSMutableArray array];[array addObject:[FMCommandEvent command:@"Touch" className:@"UITableViewCell"

monkeyID:@"Buttons" speed:@"500" timeout:@"0" args:[NSArray arrayWithObjects:@"98", @"21", nil]]];

[array addObject:[FMCommandEvent command:@"Touch" className:@"FunkyButton" monkeyID:@"Gray" speed:@"1182" timeout:@"0" args:[NSArray arrayWithObjects:@"40", @"24", nil]]];

Page 40: FONEMONKEY

[array addObject:[FMCommandEvent command:@"Verify" className:@"FunkyButton" monkeyID:@"GRAY!" speed:@"1546" timeout:@"0" args:[NSArray arrayWithObjects:nil]]];

[array addObject:[FMCommandEvent command:@"Touch" className:@"FunkyButton" monkeyID:@"GRAY!" speed:@"675" timeout:@"0" args:[NSArray arrayWithObjects:@"40", @"24", nil]]];

[array addObject:[FMCommandEvent command:@"TouchLeft" className:@"UINavigationBar" monkeyID:@"Buttons" speed:@"1443" timeout:@"0" args:nil]];

The next line runs the commands:    NSString* lastResult = [FoneMonkeyAPI playCommands:array];

The playCommands method returns nil if the test completes successfully. The next line of code tests for a nil return

value:    STAssertNil(lastResult, lastResult);

Running generated Object-C

 To run the generated .m file, simply drag and drop it into your Xcode project, being sure to add it to your test target

when prompted.

The tests will run automatically under OCUnit whenever you start up your app. You can find more information about

running OCUnit-based tests here.

Understand generated JavaScript (QUnit)

Here is an example of a FoneMonkey-generated QUnit test: $(document).ready(function(){module("SampleTest")asyncTest('testSomething', function() {    // myCommandList = new CommandList();    FM.commandList.addRetry("Touch", "UITableViewCell", "Buttons", "500", "0", "5", "20");    FM.commandList.addRetry("Touch", "UIRoundedRectButton", "BUTTON", "1872", "0", "130", "22");    FM.commandList.addRetry("TouchLeft", "UINavigationBar", "Buttons", "771", "0", null);    FM.commandList.play();}) function continuationFunction(){    // Additional logic after commands are done playing

Page 41: FONEMONKEY

}});

 

In this example:

FM.commandList is a CommandList object created by the FoneMonkey QUnit API.FM.commandList.addRetry("Touch", "UITableViewCell", "Buttons", "500", "0", "5", "20");

- adds "Touch" command to the "UITableViewCell" with the MonkeyID "Buttons" with speed "500" (milliseconds) and

a timeout of "0" (milliseconds) with arguments  "5" and  "20" FM.commandList.play();

-  plays the list of commands in the commandList  objectcontinuationFunction()

- is a continuation function that simply replays the FM.commandList

- pass continuationFunction as an argument in FM.commandList.play to add additional logic to be run once the

commands are done playing: FM.commandList.play(continuationFunction);

Running generated JavaScript (QUnit)

Add the environment variable FM_ENABLE_QUNIT to your test target and set the file name as the value, including

the file extension:YourScriptName.js

Your test target will now run the tests within YourScriptName.js

Understanding generated JavaScript (UIAutomation)

FoneMonkey generates JavaScript code that scripts application interactions via Apple's UIAutomation Framework,

and which can be run using Apple's Automation Instrument.

It's important to note that Apple's UIAutomation Framework requires that all application components you plan to

automate can be identified via accessibility labels. Like UIAutomation, FoneMonkey will identify a UIComponent by

using it's accessibility label if one is present. Unlike UIAutomation, FoneMonkey generates an identifier if no

accessibility label is available. These generated identifiersare not valid for use with UIAutomation.

Ideally, you should add all required accessibility labels to your application components prior to recording a test script.

If you record a script and find that some component is missing a good identifier, you can give it an accessibility label

and then, rather than re-record your script, you can edit the script to replace the generated identifier with the newly

specified label.

Another difference between UIAutomation and FoneMonkey is that UIAutomation accessess elements via

hierarchically traversing your application's component tree, whereas FoneMonkey accesses a component via

its monkeyID. In addition, FoneMonkey commands are not always semantically equivalent to their UIAutomation

counterparts, For example, the FoneMonkey command for scrolling a UITableView specifies the section and row

Page 42: FONEMONKEY

number to which you wish to scroll, while UIAutomation specifies instead the accessibility label of the cell you wish to

scroll to.

To accomodte these differences, FoneMonkey-generated scripts depend on the FoneMonkey.js script which defines

an API that adapts FoneMonkey commands for execution by UIAutomation. Whenever you create a script with

FoneMonkey, the FoneMonkey.js script is added to the application's Documents directory, from where it can be easily

imported into the generated script.

Let's look at an example of a generated script. The script below enters values into the UserID and Password fields of

the application being tested, and then taps a button labeled "OK". It then verifies thsat the LoginResponseMsg field

contains the value "Welcome, User123".#import "FoneMonkey.js"

FoneMonkey.elementNamed("UserID").setValue("User123");FoneMonkey.elementNamed("Password").setValue("password123");FoneMonkey.elementNamed("OK").tap();FoneMonkey.assertElementValue("LoginResponseMsg", "Welcome, User123", 5);

The line#import "FoneMonkey.js"

imports the FoneMonkey UIAutomation JavaScript library that provides various UIAutomation helper functions. You

invoke functions from the library by qualifying the function names with the "FoneMonkey" namespace identifier. For

example, the next line of the script is:FoneMonkey.elementNamed("UserID").setValue("User123");

Here, we are invoking the library's elementNamed function. This function searches the component tree for an

element named "UserID". The elementNamed function returns a UIAElement, and we use the UIAElement setValue

method to set the component's value to "User123".Ident i fy ing Elements

Note that elementNamed provides the ability to reference a component by name, directly, regardless of where it

resides in the component hierarchy. This is in contrast to how elements are identified in the native UIAutomation API,

where it is necessary to navigte the component hierarchy to identify an element.

For example, with native UIAutomation, if the UserID field were contained within a cell of the application window's first

table, you would need to specify something similar to the following:

UIATarget.UIALocal().tableViews[0].cells["Login"].textFields["UserID"].setValue("User123");Interact ing With Components

After setting values for the UserID and Password fields, the script taps on the application's OK button with the script

line:FoneMonkey.elementNamed("OK").tap();

Here again, elementNamed returns a UIAElement, so we can use any method from the UIAElement API to interact

with the component. In this case, we use the tap method to simulate tapping a UIButton.Veri fy ing Expected Results

The next line of the script is:FoneMonkey.assertElementValue("LoginResponseMsg", "Welcome, User123", 5);

Page 43: FONEMONKEY

This assertElementValue function tests that a component with the supplied name, in this case

"LoginResponseMsg", matches the supplied value, "User123". If the expected value is found, the script will log a

successful test. If not, it will log a test failure. The last argument in the example assertElementValue call above, "5",

specifies a timeout, in seconds, and causes the script to wait for a maximum period of time for the element with the

expected name and value to appear in the application.Wait ing For Expected Results

Most FoneMonkey UIAutomation helper functions accept a timeout value. Specifying a value for this argument

causes the script to wait for the corresponding number of seconds. For example, we can cause our script to wait a

maximum of 10 seconds for a Button named "OK" to appear by specifying:FoneMonkey.assertElement("OK", 10);

The elementNamed function accepts a timeout value, so we can specify statements like:FoneMonkey.elementNamed("OK", 10).tap();

The above statement waits a maximum of 10 seconds for the "OK" button to appear, and then taps the returned

button. If the button is not found in the allotted time, then the script logs a test failure.

If no timeout value is specified, FoneMonkey will use the current value of UIATarget.UIALocal().timeout().Running UIAutomation Scr ipts

See Apple's documentation on Running the Automation Instrument.

GETTING OBJECT PROPERTY DURING PLAYBACK

To get the property of an object during playback, use the CommandList.addGet function.  As an example:

commandList.addGet("UITextField", "OneField", "text", "changeVar");

- gets the "text" property for "UITextField" with the MonkeyID " OneField" and creates the variable "changeVar"

 

You can reference changeVar in the continuation function as a JavaScript variable:

// JavaScript

if (changeVar == "ExpectedText")

    // Do something

 

Or later during playback as a MonkeyID or an argument for the command using ${ } delimiters:

commandList.add("Return", "UITextField", "AnotherField", " ${changeVar}");

MANAGING SCRIPT FILES

FoneMonkey scripts and generated code files are stored within your application's Documents Directory. (Learn more

aboutgenerated script files.)Running in the Simulator

When running in the simulator, the Documents directory is located in your Application Home directory located at:

Page 44: FONEMONKEY

~/Library/Application Support/iPhone Simulator/<SDK

Version>/Applications/<ApplicationID>

where SDK Version is the version of the SDK you're running with, and ApplicationID is the unique identifier created

for you when you install your application in the simulator. For example:

~/Library/Application Support/iPhone Simulator/4.2/Applications/16F183BB-A209-408A-

A91D-E4DF99DD42F4/Documents

Each time you re-install your app, a new ApplicationID will be assigned and a new Application Home directory will be

created. Anything stored in your previous Documents directory should be copied to a newly created one in the new

Application Home.Editing Script Files Directly

FoneMonkey currently stores "native" scripts as standard Mac Property List (.plist) files. You can edit a script as you

would any other .plist by using the Mac Property List Editor.Transferring Scripts Between the Simulator and Device

Scripts files can be transfered back and forth from an iOS device in the same way you would share any application

data file.

FONEMONKEY ENVIRONMENT VARIABLES

Environment Variable Value Description

FM_ENABLE_AUTOEXIT YES Set application to terminate after OCUnit tests have run

FM_ENABLE_XML_REPORT YESSave test results in XML format to application's Documents Directory

FM_ENABLE_SCREENSHOT

FAILURE

ALL

NONE

Writes out a screenshot each time a script failure occurs

Writes out a screenshot after each command is executed

No screenshots will be written

FM_ENABLE_QUNIT ScriptName.js Set application to run QUnit test in ScriptName.js

FM_ENABLE_UIAUTOMATION

YES Generate UIAutomation JavaScript file instead

 

Page 45: FONEMONKEY

DATA DRIVE WITH FONEMONKEY

Using the DataDrive command introduced in FoneMonkey 5.3a, you can specify a CSV (Comma Separated Value)

file containing data you would like to drive your tests with.  The CSV file must be located within your

application's Documents Directory and must be saved as Windows Comma Seperated (.csv) in Excel.  Values in the

first row of your CSV file will serve as variables that can be referenced later in your command list using the syntax $

{variable}.  By specifying your CSV file at the beginning of your command list, your test will run for each row in the

file.  Screenshots below will help you to understand how to implement a data driver into your tests.

Page 47: FONEMONKEY

     

Page 48: FONEMONKEY

 

JS Sample Test:

$(document).ready(function(){     module("Simple Module");     asyncTest("Simple Test", function() {                // Add a data driver to the command list        // CSVdemo.csv is located in documents directory        FM.commandList.addDriver("CSVdemo");                // Build the command list        // FM.commandList.addRetry("Command", "Class Name", "Monkey ID", "Delay (ms)", "Timeout (ms)", "Arg1", "Arg2", "ArgX");

FM.commandList.addRetry("Touch", "UITableViewCell", "TextFields", "500", "100", "99", "31");

FM.commandList.addRetry("Touch", "UITextField", "Normal", "1094.26", "100", "142", "20");FM.commandList.addRetry("InputText", "UITextField", "Normal", "84.458", "100", "$

{firstVar} ${secVar}");FM.commandList.addRetry("Clear", "UITextField", "Normal", "1188.06", "100", null);FM.commandList.addRetry("Return", "UITextField", "Normal", "1425.48", "100", "");FM.commandList.addRetry("TouchLeft", "UINavigationBar", "TextFields", "1192.54", "100", n

ull);                // Play commandList with CSVdemo data driver

Page 49: FONEMONKEY

        FM.commandList.play();            })

FONEMONKEY COMMAND REFERENCE

This reference organizes commands by component class. FoneMonkey commands are implemented by various class

extensions and those implementations are inherited by subclasses. If a particular component type is not listed here, it

is because it inherits its recording and playback behavior from one or more of its superclasses.

A command can specify either the class that should receive the command or any if its superclasses. For example, to

push a UIButton subclass called CustomButton you could specify:

Touch CustomButton

or

Touch UIButton

The specified class is used by FoneMonkey at runtime in conjunction with an optional monkeyID to identify a

component to receive a command. The command will be executed the same way by the receiving component

regardless of what class name was actually specified on the command itself.

GLOBAL COMMANDS

DataDrive fileName:stringSets the data driver for a set of commands.  Add the DataDrive command to the beginning of your list of commands

and your test will iterate through the rows in your Comma Separated Value file you specify.  Values in the first row of

the CSV file will serve as variables and can be accessed from command arguments and MonkeyID's later within the

command list using ${variable} syntax.Arguments

fileName:string (Required) - Filename of CSV file to data drive your test (must be in your application's Documents

Directory).Examples

DataDrive myCsvFile

Page 50: FONEMONKEY

Pause milliseconds:integerPauses playback for the specified number of milliseconds. You can use this command if you need to increase the

delay between the execution of two commands. This is a global command. If a class name or monkeyID is specified,

it will be ignored.Arguments

milliseconds:integer (Required) - The number of milliseconds to pause playback.Examples

Pause 1000

RotateShakes the phone. This is a global command. If a class name or monkeyID is specified, it will be ignored.Arguments

orientation:integer (Optional)- The integer value corresponding to the UIDeviceOrientation enumeration.Examples

The following example rotates the phone orientation right to landscape and left back to portrait.

Rotate 4

Rotate 0

ShakeShakes the phone. This is a global command. If a class name or monkeyID is specified, it will be ignored.Arguments

None.Examples

Shake

UIBUTTON COMMANDS

UIButton adds no new command handling, but overrides monkeyID.

Page 51: FONEMONKEY

MonkeyID

UIButton's monkeyID is its titleLabel property (the button's display text) value if it exists, otherwise it is the default

monkeyID.

UINAVIGATION COMMANDS

MonkeyID

UINavigationBar's monkeyID is its topItem.title property, if it exists. Otherwise it is the default monkeyID.

TouchLeft UINavigationBar

TouchRight UINavigationBar

TouchLeft UINavigationBar ["monkeyID"] Touches the left side of the navigation bar, which will touch the leftside (or back) button if one is present.Arguments

None.

TouchRight UINavigationBar ["monkeyID"] Touches the right side of the navigation bar, which will touch the rightside button if one is present.Arguments

None.

UISCROLLVIEW COMMANDS

UIScrollView records the upper-left coordinate visible within a view whenever scrolling comes to a stop. 

Scroll UIScrollView ["monkeyID"] x:integer, y:integerScrolls the specified coordinate to the upper left corner of the view.Arguments

x:integer (Required)- The x coordinate to scroll to.

y:integer (Required) - The y coordinate to scroll to.

UISEGMENTED CONTROL COMMANDS

UISegmentedControl specializes the Touch command and the monkeyID.MonkeyID

A UISegmentedControl's monkeyID is the concatenation of its segment labels if it has any. Otherwise it's the default

monkeyID.

Touch UISegmentedControl ["monkeyID"] label:string

Page 52: FONEMONKEY

Touches the segment with the specified label.Arguments

label:string (Required)- The label of the segment to touch. If the segmented control displays images rather than text

labels, the label is interpreted as the ordinal position (beginning with zero) of the segment to touch.Examples

To touch a segment called "Settings":

Touch UISegmentedControl Settings

To touch the third segment (if it's an image):

Touch UISegmentedControl 2

UISLIDER COMMANDS

Slide UISlider ["monkeyID"] value:floatSlide the slider to the specified value.Arguments

value:float (Required)- The value to slide to.

UISWITCH COMMANDS

Switch UISwitch ["monkeyID"] Toggle the slider on or off from its present state.Arguments

 

None.

UITABLEVIEW COMMANDS

UITableView defines the VScroll command for table scrolling.

VScroll UITableView ["monkeyID"] [row:integer, section:integer]Scrolls the table to the specified row and section.Arguments

row:integer (Optional)- The row to scroll to. Defaults to 0.

section:integer (Optional) - The section to scroll to. Defaults to 0.

UITABLEVIEWCELL COMMANDS

UITableViewCell adds no new commands, but customizes monkeyID.

Page 53: FONEMONKEY

MonkeyID

A UITableViewCell's monkeyID is:

its textLabel.text property value, if one exits, else

its detailTextLabel.text property value, if one exists, else

its text property value, if one exists, of a child of the cell's contentView, else

its default monkieyID.

Note - You cannot "touch" a UITableViewCell unless it's visible on the screen. In other words, you can't "touch" a cell

that is currently scrolleld off the display. You must scroll to it into view first with the Scroll UITableView command.Example

Touch UITableViewCell "Playlists"

UITEXTFIELD COMMANDS

UITextField records touch and input events. Input value recording occurs whenever a textfield edit is completed. The

value recorded is the updated field value.MonkeyID

UITextField's monkeyID is its placeholder property value (the field's prompt text) if it has one. Otherwise it is the

default monkeyID.

InputText UITextField ["monkeyID"] value:stringEnters the specified text value into the field.Arguments

value:string (Required)- The string value to enter into the text field.Examples

InputText UITextField "Last Name" Smith

Touch UITextField ["monkeyID"] Sets input focus (firstResponder) to the text field.Arguments

noneExamples

Touch UITextField "First Name"

UITOOLBAR COMMANDS

UIToolBar adds no new commands or monkeyID customization.

Although you add UIBarButtonItems for each button to display on a toolbar, each UIBarButtonItem is actually

implemented by by an undocumented Cocoa Touch class called UIToolBarTextButton. For this reason, when you

record touching a UIBarButtonItem, the command will be recorded with a class of UIToolBarTextButton rather than

UIBarButtonItem.For example, to touch the "Settings" button on a toolbar:

Page 54: FONEMONKEY

Touch UIToolBarTextButton "Settings"

UITOOLBARTEXTBUTTON COMMANDS

UIToolBarTextButton is an undocumented Cocoa Touch class that provides the implementation of UIBarButtonItems

within a UIToolBar. UIToolBarTextButton adds no new commands, but it does override monkeyID.MonkeyID

The text property value from the UIToolBarTextButton's corresponding UIBarButtonItem.

UIVIEW COMMANDS

All Cocoa Touch UI components inherit from UIView, and UIView provides the default handling for the most common

FoneMonkey commands including Touch, Move, Scroll, Shake, and Verify. While most component classes forward

commands to UIView for handling, many component classes do override or specialize the handling of these

commands.MonkeyID

UIView also provides the default implementation of monkeyID for all components, although again, many subclasses

override to provide their own, and you can easily do so for your own custom components.

The default monkeyID for a component is:

its accessibilityLabel if it exists (and accessibility is enabled),

its tag if it is less than zero and there is no accessbilityLabel,

and otherwise a unique identifier generated by FoneMonkey.

FoneMoney generates a monkeyID by assigning an ordinal to each instance of each class on the screen.

FoneMonkey generated monkeyID's are prefix with a #-sign.

Generated id's are dependent on the order in which a particular component type is added to a view, and so can

change across application runs if you rebuild your application with a modified view after recording a script. For this

reason, you should try to avoid saving scripts with generated monkeyID's. You should instead specify an

accessibilityLabel, a negative tag value, or override the monkeyID method.

Touch UIView ["monkeyID"] [x:integer, y:integer][, tapCount:integer]Touches the view at the specified coordinate, or in the center if no coordinate is specified.Arguments

x:integer (Optional)- The x coordinate of the touch in the view.

y:integer (Required if x is specified) - The y coordinate of the touch in the view.

tapCount:integer (Optional) - The number of taps (eg,1 = single tap, 2 = double tap). Defaults to 1.

tapCount:

Page 55: FONEMONKEY

Examples

Touch UIButton "Done"

Touch UIPaintingView 100,100

Double touch:

Touch UIPaintingView 100,100,2

Move UIView ["monkeyID"] x0:integer, y0:integer[, x1,y1:integer...]

 

Generates a touch that drags along the path specified by the supplied sequence of x,y coordinate pairs.Arguments

A sequence of one-or-more points specified as x,y coordinate pairs.

xn:integer (At least one required)- The x coordinate of a point along the path.

yn:integer (A corresponding y must be specified for each x) - The x coordinate of a point along the path.Examples

Move PaintingView 0,0,1,1,2,2,3,3,44

Verify UIView ["monkeyID"] [property:string, expectedValue:string]Tests whether the component exists and wether the specified property is equal to some expected value.Arguments

property:string (Optional)- The name or path of the property whose value is to be verified.If no property is specified,

Verify tests only for the existence of the specified component.

expected:string (Required if property is specified) - The expected string value of the specified property.Examples

Verify UILabel "message" text, Welcome

Verify UITableViewCell "Songs" detailTextLabel.text, "Total time: More than 9 Days"

WaitFor UIView ["monkeyID"] [timeout:integer property:string,expectedValue:string]Pauses script execution until the specified view is found.Arguments

timeount:integer (Required)- Maximum time to wait for the view to be found.

property:string (Optional)- The name or path of the property whose value is to be verified.If no property is specified,

WaitFor waits only for the existence of the specified component.

expected:string (Required if property is specified) - The expected string value of the specified property.Examples

WaitFor UILabel "message" 5000

WaitFor UITableViewCell "Songs" 5000, detailTextLabel.text, "Total time: More than 9 Days"

Page 56: FONEMONKEY

UIWEBVIEWS COMMANDS

New in FoneMonkey 5.5a, you can now run HTML Selenese scripts to test your UIWebView implementation.  To

enable this functionality, you will need to:

1. Unzip the extralibs folder within the FoneMonkey folder

2. If you are not using MediaPlayer in your app, you can remove libFoneMonkeyMediaPlayer from the extralibs folder

3. Drag the FoneMonkey folder into your project (if you already have FoneMonkey linked into your project, remove the

folder and then drag the new version in)

4. Continue basic setup steps (add QuartzCore and libxml)

5. Add the following frameworks/libs to your test target (if not already linked)

1. CFNetwork.framework

2. CoreLocation.framework

3. Foundation.framework

4. Libsqlite3.dylib

5. From the Build Settings tab in your test target, add -lstdc++ to your Other Linker Flags

6. Build your test target

 Run (Scr ipt ) Command

The WebDriver command is the command used to link your Selenese HTML test to a UIWebView in your application. 

You can use the Firefox Selenium IDE plugin to record your HTML test, or you can write it from scratch.  To set up

your test:

1. Make sure the HTML file is in your applications Document Directory

2. Record a script to navigate to your UIWebView (if it is not within the default view)

3. Add the Run command (from the console you can do this by pressing the “+” button in the top right)

4. See screenshot for an example of the a complete command

5. Add the HTML file as the first argument for the command

6. Run your test

Page 57: FONEMONKEY

 

Page 58: FONEMONKEY
Page 59: FONEMONKEY