Now that you've been introduced to Telerik Mobile Testing, it's time to dig in and start automating. Let's start with a native iOS application built using standard UIKit controls. I'll make it testable, develop a test plan, write and execute tests, and publish results to the Telerik Platform.
This case study uses a simple application called Protein Tracker that was created from a Pluralsight tutorial. Values are entered and tracked on the main screen, and a goal is set on the Settings screen. When the goal is exceeded, a prompt appears to reset the data.
Main screen | Settings screen | Goal achieved |
There are three control types I plan to interact with: buttons, text fields, and labels. I plan to identify the buttons based on their currentTitle property, so no additional steps are needed there. For the text fields and labels, however, I assign unique tag values for easier element identification later.
I created a duplicate testing target and added the Mobile Testing extension based on these instructions. Next, I deployed the new ProteinTrackerQA target to the simulator and my iPhone.
I need the Mobile Testing companion app to test a native iOS app. I downloaded it from the App Store on my iPhone, and followed these instructions to install it to the simulator.
There are four functional scenarios I want to test through automation.
I started by creating a new JavaScript file. Code may be written to that file using any IDE or text editor. I prefer Sublime Text.
Start with the main spec method:
spec(
function
(){
});
Next comes the Query Repository. I defined the iOS queries for the elements here and assigned each to a variable.
var
queries = {
settingsBtn: {
'class'
:
'UIButton'
,
'properties'
: {
'currentTitle'
:
'Settings'
} },
saveBtn: {
'class'
:
'UIButton'
, properties: {
'currentTitle'
:
'Save'
} },
enterBtn: {
'class'
:
'UIButton'
, properties: {
'currentTitle'
:
'Enter'
} },
yesBtn: {
'class'
:
'UIButton'
, properties: {
'currentTitle'
:
'Yes'
} },
noBtn: {
'class'
:
'UIButton'
, properties: {
'currentTitle'
:
'No'
} },
consumed: {
'class'
:
"UITextField"
,
'properties'
: {
'tag'
: 1} },
goalTextField: {
'class'
:
"UITextField"
,
'properties'
: {
'tag'
: 2} },
goalLabel: {
'class'
:
"UILabel"
,
'properties'
: {
'tag'
: 1} },
totalLabel: {
'class'
:
"UILabel"
,
'properties'
: {
'tag'
: 2} }
};
Here I defined a few static variables used later in the test steps.
var
proteinGoal =
"200"
;
var
proteinConsumed =
"100"
;
var
proteinOverGoal =
"300"
;
The bulk of the code comes next in the Step Repository. Each step is labeled with a friendly name, followed by platform-specific operations. This example only uses iOS operations.
These steps perform the actions and verifications against the application's elements, which are referenced via the query repository. You'll see things like launching the app, tapping buttons, setting text, and verifying labels.
var
stepRepository = {
"Launch app"
: {
'ios'
: [
ios.launch(
'ProteinTrackerQA://'
)
]
},
"Tap Settings"
: {
'ios'
: [
ios.tap(queries.settingsBtn)
]
},
"Tap Save"
: {
'ios'
: [
ios.tap(queries.saveBtn)
]
},
"Tap Enter"
: {
'ios'
: [
ios.tap(queries.enterBtn)
]
},
"Tap Yes"
: {
'ios'
: [
ios.tap(queries.yesBtn)
]
},
"Tap No"
: {
'ios'
: [
ios.tap(queries.noBtn)
]
},
"Enter goal"
: {
'ios'
: [
ios.setText(queries.goalTextField, proteinGoal)
]
},
"Enter protein"
: {
'ios'
: [
ios.setText(queries.consumed, proteinConsumed)
]
},
"Enter protein over goal"
: {
'ios'
: [
ios.setText(queries.consumed, proteinOverGoal)
]
},
"Verify new goal"
: {
'ios'
: [
ios.getPropertyValue(queries.goalLabel,
'text'
,
function
(value) {
assert(value).equals(proteinGoal);
})
]
},
"Verify new total"
: {
'ios'
: [
ios.getPropertyValue(queries.totalLabel,
'text'
,
function
(value) {
assert(value).equals(proteinConsumed);
})
]
},
"Verify same total"
: {
'ios'
: [
ios.getPropertyValue(queries.totalLabel,
'text'
,
function
(value) {
assert(value).equals(proteinOverGoal);
})
]
},
"Verify zero total"
: {
'ios'
: [
ios.getPropertyValue(queries.totalLabel,
'text'
,
function
(value) {
assert(value).equals(
"0"
);
})
]
}
};
Finally comes the Test Suite. A suite is a group of tests, labeled with a friendly name, that calls the step repository. Each test is also labeled and contains steps, referenced by their friendly names from the step repository.
Based on the test plan I created earlier, I simply mix and match steps to create each test.
describe(
"Track protein"
,
function
(){
test(
"Add goal"
,
function
(){
step(
"Launch app"
);
step(
"Tap Settings"
);
step(
"Enter goal"
);
step(
"Tap Save"
);
step(
"Verify new goal"
);
});
test(
"Enter consumption"
,
function
(){
step(
"Launch app"
);
step(
"Enter protein"
);
step(
"Tap Enter"
);
step(
"Verify new total"
);
});
test(
"Exceed goal and reset"
,
function
(){
step(
"Launch app"
);
step(
"Enter protein over goal"
);
step(
"Tap Enter"
);
step(
"Tap Yes"
);
step(
"Verify zero total"
);
});
test(
"Exceed goal and do not reset"
,
function
(){
step(
"Launch app"
);
step(
"Enter protein over goal"
);
step(
"Tap Enter"
);
step(
"Tap No"
);
step(
"Verify same total"
);
});
}, stepRepository);
It's time to execute the tests via the Test Runner.
The Results tab loads when execution finishes. All tests passed!
I can additionally publish results to the Telerik Platform for storage and to share with colleagues, managers, and stakeholders.
That's it! The handy query and step repository method makes it easy to add new queries and tests when I add new elements and features to my application.
Stay tuned for the next case study on a native Android app.
Anthony Rinaldi combines his experience in test automation and quality assurance with his passion for mobile devices and platforms. He is an avid CrossFitter, soccer player, and music fan.