UIAutomation is an emerging solution from Apple to allow for automation of iOS apps.
Though the framework provides many features, the API is awkward, and their is no easy way to navigate and select UI elements from the App's element tree.
Mechanic.js is a framework meant to alleviate that! Enjoy!
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
UIAutomation + Mechanic.js
1. Today I’d like to talk about UIAutomation,
how you can use it to make your iOS apps
better.
After I’ve given you the downlow on UIA,
I’m going to show you how to make it
better with a framework I’ve created called
mechanic.
mechanic.js
uiautomation++
2. So what is UIAutomation? UIAutomation is a
software tool (and its accompanying
framework) built by Apple that allows
developers to automate interacting with their
iOS apps for testing.
UIAutomation makes it easy to script clicks,
drags, location changes, etc. and allows you
to assert on the state of your UI.
what is
uiautomation?
3. play time:
1. Open your favorite project in XCode
2. Cmd-I
3. Choose “Automation” as the Trace Template and click
“Profile”
4. In the “Scripts” section, click “Add” and create a
script
5. Automate!
4) You don’t have to create a new script, you can import an
existing script in your source directory.
- Scripts can be ran from the console using the ‘instruments’
cmd line utility, as well.
- The ‘bwoken’ gem can also be used - it allows you to write
tests in coffeescript and run them from the cmd line (though I
haven’t been able to get it to work for me just yet)
* open instruments and create a simple script that logs element
tree for frontMostApp().mainWindow() and describe it *
4. * show uiautomation/jasmine demo. Explain how it is set
up (i.e. how to use #import, etc.) *
* for those of you not familiar with jasmine, it’s an
RSpec-like framework for writing Javascript specs
uiautomation and
jasmine are pretty cool..
5. UIAutomation is not without it’s blemishes. Though it’s Apple’s official tool for this
sort of automation (one reason I’d be wary of using tools like Square’s KIF and
Frankified), it’s very young
1. The API isn’t shaped like a modern JS framework like we expect (underscore,
jQuery, requireJS, Knockout, etc.)
2. The API is relatively verbose (and at times redundant)
3. The mechanisms to navigate your app’s “DOM” make it difficult to “get” the
elements you’re trying to interact with and assert on
what’s the catch?
What’s the answer to these problems? Mechanic is (or I hope it is)!
Mechanic servers as a shim to alleviate these pains.
7. So I’ve given you the elevator pitch.. Now the hard sell:
actions speak louder
than words...
8. var mainWindow =
UIATarget.localTarget().frontMostApp.mainWindow();
mainWindow.tableViews[‘members’].cells()[‘First row’].tap();
UIATarget.localTarget().delay(2);
var navBar = mainWindow.navigationBars()[‘userDetails’];
assertEquals(‘Back’, navBar.buttons()[0].label());
assertEquals(‘Close’, navBar.buttons()[1].label());
vs (describe what the code is
$(‘#members cell’).first() doing)
* # of lines is not much
.tap() different buuuutttt...
* code density
.delay(2); * law of demeter
* cheated a bit, top code
would span more lines if
var buttons = $(‘#userDetails button’); abstracted to the same level
assertEquals(‘Back’, buttons[0].label());
assertEquals(‘Close’, buttons[0].last().label());
10. // click all buttons
var mainWindow = UIATarget.localTarget().frontMostApp.mainWindow();
var i, j, k, l, m, n, o, p;
var someButtonElements = mainWindow.elements[‘some_buttons’].elements();
for (i = 0; i < someButtonElements.length; i++) {
if (someButtonElements typeof UIAButton) {
someButtonElements[i].tap();
}
}
var moreButtons = mainWindow.scrollViews()[‘first scrollview’].elements();
for (i = 0; i < moreButtons.length; i++) {
if (moreButtons typeof UIAButton) {
moreButtons[i].tap();
}
vs
}
// ...snip
(describe what the code is doing - trying to tap all
of the buttons in the app’s window)
* the non-mechanic version is intrinsically more
$(‘button’).tap(); difficult since there’s no easy mechanism for
searching the window’s “DOM”
* This example might be unfair - is it a realistic use
case?
11. * mechanic-core is the heart of
mechanic
* it’s the reason I wrote / am writing
mechanic
* gives you the DOM searching/
traversing that’s missing from
UIAutomation, similar to jQuery,
Prototype, etc.
* gives you the chaining that we
know and love and have come to
expect in selector engines.
* The other “modules” in mechanic
are really just niceties or chained
wrappers on top of the existing
UIAutomation APIs.
act i.
mechanic-core
12. selector * UIAutomation places different element
types (buttons, text, images, table cells,
shortcuts
etc.) into rather verbose classes. When
searching for elements of a certain type,
I’ve provided shorter class names to
decrease the signal-to-noise ratio.
The UIAutomation environment is
pretty minimal. Mechanic provides
functional
extensions
some simple functional-type
functions like map, each, slice,
reduce, etc.
dom
Most of the UIAutomation scripting
I’ve done, most of the work goes
into “getting” the element you’re
traversal
looking for. Mechanic provides a
number of means of filtering and
expanding sets of matched
elements.
13. find stuff:
(+ more)
$(‘#my-scroll-view image’).each(function(img) { img.log(); });
$(‘text’, aPopover).siblings(‘image’);
var names = $(‘*’).map(function() { return this.name() });
var allNonTextEls = $(‘window’).children().not(‘text’);
var el = $(‘*’).predicate(‘where label == “Some label”’);
15. device
We can change the device’s volume,
location, lock the device, etc.
manipulation
Simulate screen touches, rotations, etc.
screen
actions
element
taps, touches, rotations on
buttons, pickers, text, etc.
interaction
22. record stuff:
(+ more.. well, not really..)
$.warn(‘An element was not where it should have been!’);
$(‘text’).log();
$(‘window’).logTree();
$(‘image’).capture();
$(‘#my-button’).tap()
.parent().capture()
.message(‘tapped the button and then captured a picture!’);
25. selectors
documentation
more coverage
assertions??
Big thing is that only simple selectors are
create issues
supported, though the functions in mechanic- use it!!!
core make it easy to construct complex please...?
constructors.
Reworking mechanic-core based on Sizzle
and qwery currently, which should expose
more complex queries.