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.

The App-Under-Test

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
Main screen Settings screen Goal achieved

 

Prepare App for Automation

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.

Text Field tag

Add Testing Extension

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.

Download Companion App

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.

Create a Test Plan

There are four functional scenarios I want to test through automation.

  1. Set a new goal and verify it saves.
  2. Enter a value and verify the total updates.
  3. Enter a value that exceeds the goal, reset the data, and verify the total is zero.
  4. Enter a value that exceeds the goal, do not reest the data, and verify the total remains the same.

Write Tests

Create JavaScript File

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(){
 
});

 

Query Repository

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";

 

Step Repository

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");
            })
        ]
    }
 
};

 

Test Suite

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);

 

Execute Tests

It's time to execute the tests via the Test Runner.

  1. Click Settings and change the Spec Folder path to where the test resides.
  2. Click Save. Notice the suite and tests are displayed by their friendly names.
  3. Launch the Mobile Testing app on the device and simulator and connect them.
  4. Click Refresh Agents.
  5. Click Run Tests.

Tests

Publish Results

The Results tab loads when execution finishes. All tests passed!

Results

I can additionally publish results to the Telerik Platform for storage and to share with colleagues, managers, and stakeholders.

Conclusion

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.


About the Author

Anthony Rinaldi

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.

Related Posts

Comments

Comments are disabled in preview mode.