Automating UI Testing

Why test your app?

Every time that you change something in your code, you have to test it again, there’s a lot that can (and should) be done with OCUnit , but what should you do when you want to test the UI? It’s really boring and time-consuming doing it manually, wouldn’t it be great if you could create some script that do all this mundane job for you? Testing your app you will:
  • Avoid regressions
  • Increase your app quality, therefore your users satisfaction
  • Do something else while the script does the boring work
  • Test manually only those more interesting scenarios.

UI Automation

UI Automation is integrated with Instruments. What does it means? It means that you can use alongside other instruments and see exactly what’s happening with your app.
It’s only supported on iOS 4.x and the device must support multitasking. The simulator or the device can be used to run the tests.

Script language

UI Automation uses javascript to run the tests. I’m not sure why they choosed javascript for that, maybe there’s a lot of javascript developers around the world, compared to other script languages, but I would choose Python instead 🙂
Problem in sdk 4.0.1 and 4.0.2

There’s a bug when you try to run the test if you are using one of these sdk versions. To fix this is pretty simple, just run the following commands in the terminal
cd ~/Library/Application\ Support/iPhone\ Simulator/
ln -s 4.0.1 4.0
If you are using 4.0.2 just substitute it in the second command.

How to automate?

Every control in your application gets represented to UI Automation as an element. Some examples are:
  • Name: Accessibility labels gets translated into the name of your element
  • Value : Value of a control, text from a textfield, and so on.
  • Elements : Every element can contain zero or more elements,  like a tableview cells
  • Parent: Like elements, but one level back up

Verification

To know if the test has passed or not, use these commands :
UIALogger.logPass(“yet, it’s OK”);
UIALogger.logFail(“bummer”);

Logging

It’s very important to log everything that you are doing during the test, the more you log, the better. Every time that you interact with a control, it’s good to log what it’s being done, so when you go back to the results, it’s easier to find the problem.
To log it very simples, just call:
UIALogger.logMessage(“Log this”);
Let’s say that you want to know how your app looks like after some interactions, well, it’s pretty easy, just take a screenshot with. EDIT: This only works on the actual device.
UIATarget.localTarget().captureScreenWithName(“myScreenshot”);

Tutorial

Ok, enough talking, let’s write a very simple test case (maybe, some other time I’ll create a more complex example for UI Automation)  that will press a button and check the result in the textfield.
First, create an View-based Application project, and in the View controller, create the button and textfield, something like this:
– (void)loadView {
[super loadView];
UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self action:@selector(click) forControlEvents:UIControlEventTouchDown];
[button setTitle:@”Click me” forState:UIControlStateNormal];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, self.view.frame.size.width – 20, 30)];
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.textAlignment = UITextAlignmentCenter;
[self.view addSubview:textField];
}
– (void)click {
textField.text = @”MyTestApp”;
}
– (void)viewDidUnload {
[textField release];
textField = nil;
}
– (void)dealloc {
[textField release];
[super dealloc];
}
When you click the button, the text “MyTextApp” should appear on the textfield. Go ahead, build and run your app and see if everything is ok.
Now, create a .js file with the following content
app = UIATarget.localTarget().frontMostApp();
mainWindow = app.mainWindow();
button = mainWindow.buttons()[0];
button.tap();
var result = mainWindow.textFields()[0].value();
UIALogger.logMessage(“Will tap on button”);
if (result == “MyTestApp”) {
UIALogger.logPass(“yey, it’s OK”);
} else {
UIALogger.logFail(“bummer”);
}
UIATarget.localTarget().captureScreenWithName(“myScreenshot”);
UIALogger.logMessage(“Button tapped”);
What this script is doing is, getting the mainWindow, tapping on the button, and checking the textfield value.
Open your Instruments app (command + space, and type Instruments), and you should see this screen :
Choose the Automation template. In the next screen, on instruments, select your javascript file:
Select your application, you can find it at your project folder, inside Build->Debug-iphonesimulator (if it’s a simulator build)
Press record on the instruments,the simulador should open running your app and see how the button is clicked automatically. The result should pass and this is what you will see:

Conclusion

You can test a lot of things, like create functions in your javascript, do some  scrolling, screen rotation, pinching, and so on, even the multitask feature can be tested with this approach. So, it’s a very cool feature to have and more important, to use. Remember that it’s a good practice to restore the app to its initial state when testing, so, let’s say that you add some value, at the and of this test, remove this value and move along with the other tests (Of course, only if this value will not be used in other tests) .It’s a shame that there isn’t any recorder tool, so you could just use the app and the script would be generated automatically, but hey, it’s better than nothing, right 🙂
There’s a lot of information on the Reference Collection , you probably should take a look. This was a very simple example, just to give you a hint how the UI Testing works.
Now that you know how to create some automated tests, you can use your spare time to do something nice, like developing more apps 🙂
Advertisements

12 thoughts on “Automating UI Testing

  1. This is very good stuff!

    I remember how I got excited when Apple announced it on WWDC.

    I am not sure, but I think that someone asked about a recorder tool at that time and the guy from Apple told us that he couldn’t give us any details, but this kind of stuff they are keeping in mind 🙂

    Hopefully we will have that recorder soon.

    • Hey Cezar, Just wanted to know how would be be able to get all the elements from other windows other than the Initial Login screen. Basically, here’s the code I have for getting the elements from Login screen…app = UIATarget.localTarget().frontMostApp().mainWindow();
      app.logElementTree(); & when I execute this, I get all the existing elements from separate views on the screen. After I perform a tap on one of the buttons that were there in these elements, I get to the next screen. And now, when I have to perform the manipulations for the elements on this new screen, I get a UIAElementNil error when I use the code, secondWindow = UIATarget.localTarget.frontMostApp().windows(); Can you please help me with what’s going wrong?

      Thanks in advance….

  2. Hi!
    Can you kindly give a hint how to run a test using project and test-script that you provided? I downloaded application with test-script and as test-target chose “project.pbxproj”, but received “Target failed to run”.
    Probably I’m doing something wrong(((

    • Hello, Nika.
      – Download the zipfile
      – Open the TestProject.xcodeproj
      – On Xcode, go to Product -> Profile
      – Select Automation
      – Inside the Automation Instruments, on the left menu Scripts, click in Add
      – Select the Test.js inside the zip you just downloaded
      – Run the Automation Instrument

      I have just tested with Xcode4.2 and iOS 5.0 and worked well.
      Best,

  3. Sorry for disturbing a lot, but maybe you have idea how to receive values of elements, like logging name of button or value in text field?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s