This website uses cookies to better the user experience of its visitors. Where applicable, this website uses a cookie control system, allowing users to allow or disallow the use of cookies on their computer/device on their first visit to the website. This complies with recent legislative requirements for websites to obtain explicit consent from users before leaving behind or reading files such as cookies on a user’s computer/device. To learn more click Cookie Policy.

Privacy preference center

Cookies are small files saved to a user’s computer/device hard drive that track, save, and store information about the user’s interactions and website use. They allow a website, through its server, to provide users with a tailored experience within the site. Users are advised to take necessary steps within their web browser security settings to block all cookies from this website and its external serving vendors if they wish to deny the use and saving of cookies from this website to their computer’s/device’s hard drive. To learn more click Cookie Policy.

Manage consent preferences

These cookies are necessary for the website to function and cannot be switched off in our systems. They are usually only set in response to actions made by you which amount to a request for services, such as setting your privacy preferences, logging in or filling in forms. You can set your browser to block or alert you about these cookies, but some parts of the site will not then work. These cookies do not store any personally identifiable information.
These cookies allow us to count visits and traffic sources so we can measure and improve the performance of our site. They help us to know which pages are the most and least popular and see how visitors move around the site. If you do not allow these cookies we will not know when you have visited our site, and will not be able to monitor its performance.
Cookies list
Name _rg_session
Provider rubygarage.org
Retention period 2 days
Type First party
Category Necessary
Description The website session cookie is set by the server to maintain the user's session state across different pages of the website. This cookie is essential for functionalities such as login persistence, ensuring a seamless and consistent user experience. The session cookie does not store personal data and is typically deleted when the browser is closed, enhancing privacy and security.
Name m
Provider m.stripe.com
Retention period 1 year 1 month
Type Third party
Category Necessary
Description The m cookie is set by Stripe and is used to help assess the risk associated with attempted transactions on the website. This cookie plays a critical role in fraud detection by identifying and analyzing patterns of behavior to distinguish between legitimate users and potentially fraudulent activity. It enhances the security of online transactions, ensuring that only authorized payments are processed while minimizing the risk of fraud.
Name __cf_bm
Provider .pipedrive.com
Retention period 1 hour
Type Third party
Category Necessary
Description The __cf_bm cookie is set by Cloudflare to support Cloudflare Bot Management. This cookie helps to identify and filter requests from bots, enhancing the security and performance of the website. By distinguishing between legitimate users and automated traffic, it ensures that the site remains protected from malicious bots and potential attacks. This functionality is crucial for maintaining the integrity and reliability of the site's operations.
Name _GRECAPTCHA
Provider .recaptcha.net
Retention period 6 months
Type Third party
Category Necessary
Description The _GRECAPTCHA cookie is set by Google reCAPTCHA to ensure that interactions with the website are from legitimate human users and not automated bots. This cookie helps protect forms, login pages, and other interactive elements from spam and abuse by analyzing user behavior. It is essential for the proper functioning of reCAPTCHA, providing a critical layer of security to maintain the integrity and reliability of the site's interactive features.
Name __cf_bm
Provider .calendly.com
Retention period 30 minutes
Type Third party
Category Necessary
Description The __cf_bm cookie is set by Cloudflare to distinguish between humans and bots. This cookie is beneficial for the website as it helps in making valid reports on the use of the website. By identifying and managing automated traffic, it ensures that analytics and performance metrics accurately reflect human user interactions, thereby enhancing site security and performance.
Name __cfruid
Provider .calendly.com
Retention period During session
Type Third party
Category Necessary
Description The __cfruid cookie is associated with websites using Cloudflare services. This cookie is used to identify trusted web traffic and enhance security. It helps Cloudflare manage and filter legitimate traffic from potentially harmful requests, thereby protecting the website from malicious activities such as DDoS attacks and ensuring reliable performance for genuine users.
Name OptanonConsent
Provider .calendly.com
Retention period 1 year
Type Third party
Category Necessary
Description The OptanonConsent cookie determines whether the visitor has accepted the cookie consent box, ensuring that the consent box will not be presented again upon re-entry to the site. This cookie helps maintain the user's consent preferences and compliance with privacy regulations by storing information about the categories of cookies the user has consented to and preventing unnecessary repetition of consent requests.
Name OptanonAlertBoxClosed
Provider .calendly.com
Retention period 1 year
Type Third party
Category Necessary
Description The OptanonAlertBoxClosed cookie is set after visitors have seen a cookie information notice and, in some cases, only when they actively close the notice. It ensures that the cookie consent message is not shown again to the user, enhancing the user experience by preventing repetitive notifications. This cookie helps manage user preferences and ensures compliance with privacy regulations by recording when the notice has been acknowledged.
Name referrer_user_id
Provider .calendly.com
Retention period 14 days
Type Third party
Category Necessary
Description The referrer_user_id cookie is set by Calendly to support the booking functionality on the website. This cookie helps track the source of referrals to the booking page, enabling Calendly to attribute bookings accurately and enhance the user experience by streamlining the scheduling process. It assists in managing user sessions and preferences during the booking workflow, ensuring efficient and reliable operation.
Name _calendly_session
Provider .calendly.com
Retention period 21 days
Type Third party
Category Necessary
Description The _calendly_session cookie is set by Calendly, a meeting scheduling tool, to enable the meeting scheduler to function within the website. This cookie facilitates the scheduling process by maintaining session information, allowing visitors to book meetings and add events to their calendars seamlessly. It ensures that the scheduling workflow operates smoothly, providing a consistent and reliable user experience.
Name _gat_UA-*
Provider rubygarage.org
Retention period 1 minute
Type First party
Category Analytics
Description The _gat_UA-* cookie is a pattern type cookie set by Google Analytics, where the pattern element in the name contains the unique identity number of the Google Analytics account or website it relates to. This cookie is a variation of the _gat cookie and is used to throttle the request rate, limiting the amount of data collected by Google Analytics on high traffic websites. It helps manage the volume of data recorded, ensuring efficient performance and accurate analytics reporting.
Name _ga
Provider rubygarage.org
Retention period 1 year 1 month 4 days
Type First party
Category Analytics
Description The _ga cookie is set by Google Analytics to calculate visitor, session, and campaign data for the site's analytics reports. It helps track how users interact with the website, providing insights into site usage and performance.
Name _ga_*
Provider rubygarage.org
Retention period 1 year 1 month 4 days
Type First party
Category Analytics
Description The _ga_* cookie is set by Google Analytics to store and count page views on the website. This cookie helps track the number of visits and interactions with the website, providing valuable data for performance and user behavior analysis. It belongs to the analytics category and plays a crucial role in generating detailed usage reports for site optimization.
Name _gid
Provider rubygarage.org
Retention period 1 day
Type First party
Category Analytics
Description The _gid cookie is set by Google Analytics to store information about how visitors use a website and to create an analytics report on the website's performance. This cookie collects data on visitor behavior, including pages visited, duration of the visit, and interactions with the website, helping site owners understand and improve user experience. It is part of the analytics category and typically expires after 24 hours.
Name _dc_gtm_UA-*
Provider rubygarage.org
Retention period 1 minute
Type First party
Category Analytics
Description The _dc_gtm_UA-* cookie is set by Google Analytics to help load the Google Analytics script tag via Google Tag Manager. This cookie facilitates the efficient loading of analytics tools, ensuring that data on user behavior and website performance is accurately collected and reported. It is categorized under analytics and assists in the seamless integration and functioning of Google Analytics on the website.

How to Test Your iOS App with Test Automation Frameworks

  • 29600 views
  • 10 min
  • Dec 12, 2017
Sergey A.

Sergey A.

IOS Developer

Daryna P.

Daryna P.

Copywriter

Share

Whereas testing has become commonplace in traditional programming, mobile developers still tend to avoid it and, by doing so, miss out on ample opportunities. Mobile app testing helps you find mistakes such as security vulnerabilities, crashes, memory leaks, and incompatibilities.

Moreover, mobile app tests enable you to identify potential bottlenecks in an app’s logic. Statistically, testing reduces the number of bugs connected to pre-release builds by 40 to 90 percent.

We’ve decided to fight this injustice and devote an article to iOS app tests. In this article, we’ll spell out the testing process and introduce our favorite frameworks.

iOS testing: automated or manual?

iOS testing involves two distinct types of tests: manual tests and automated tests. Each has its advantages and disadvantages. In our work, we prefer to use automated iOS testing tools. Why? Because automated tests are executed by tools and\or scripts, so they’re faster and more reliable than manual tests.

To top it off, automated tests can run on multiple devices and different SDKs. This means that automated tests can boost your testing productivity, save time, and lower development costs.

There are two main types of automated tests for iOS: the unit tests and UI tests. Let’s take a closer look at each.

What’s iOS unit testing?

One of the most convenient ways to test source code is to check the correct operation of each module discretely. In this case, you need to break down your app’s code into separate parts in accordance with the basic rules of refactoring. We call this testing approach unit testing or module testing.

Unit testing makes development agile, improves the quality of code, and helps you detect software bugs in iOS apps at an early stage.

Obviously, mere source code testing isn’t enough for a comprehensive analysis of your app, however. This is why you need to examine the graphical user interface (GUI) as well.

What does UI testing mean?

Introduced in Xcode 7, UI testing enables you to examine a user’s interactions with separate elements of the graphical user interface and validate data that these elements may contain. UI testing helps you ensure that the UI functions correctly and meets specifications.

UI tests speed up the estimation process for QA teams and, as a consequence, improve your team’s efficiency.

I bet you’d like to know how to create UI and unit tests and what framework to use.

What iOS testing framework should I use?

You can write both unit and UI tests for iOS apps using the basic XCTest framework. XCTest provides a core set of features to check that an app is working efficiently. But if you want extended functionality, try one of the following frameworks:

  • Quick and Nimble – This easy-to-use combination helps you create unit tests to check source code. Quick is a testing framework and Nimble is a matching framework.
  • OHHTTPStubs – This framework lets you test HTTP requests by adding specially prepared response data. Additionally, OHHTTPStubs lets you change response time, code, and headers.
  • KIF – Short for Keep IT Functional, KIF is one of the tools for UI testing of iOS apps that lets you test functional UI features.

These frameworks run on Objective-C as well as Swift and help you cover the whole project with tests and add extra functionality as necessary. In fact, you can easily apply these frameworks to a Model–View–Presenter (MVP) or Model–View–View-Model (MVVM) architecture.

Before using any of these automation frameworks, however, you’ll need to set up your iOS project.

How to set up an iOS project for testing

Let’s create an empty iOS project with one screen. Don’t forget to check the include unit tests checkbox. Then set up a framework. We recommend using Cocoapods. The podfile structure is quite simple:

Pay special attention to the distribution of targets, as they help keep projects in a state that’s convenient for testing. Keep in mind that the arrangement of targets depends on the type of project.

Finally, run the pod install command and wait for the framework to finish setting up. Congratulations! You’ve created a minimal project to demonstrate the feasibility of testing. Now it’s time to see some testing frameworks in action.

How does Quick/Nimble work?

Create a simple class called ContactRecord with two fields – name and phone number – in the main target. Specify the underlying type for these fields.

Now go to the testing_demoTests.swift file in the testing target. Note that Xcode has already generated several standard methods. These methods allow you to execute the necessary test configuration at any time within the implementation and to measure the app’s performance.

Next, replace the code in the testing_demoTests.swift file with the following. Of course, you may use the standard functionality of the XCTest framework. But we recommend writing this code using Quick:

By doing this, you’ve added imports of two frameworks: Quick and Nimble. Keep in mind that Xcode may show an error, saying that framework data is absent. This happens because the testing target should be compiled. To do this, press CMD+U.

You’ve also added the import of the ios_demo target. This is necessary to make Xcode see classes in the main target.

Let’s turn now to the FirstTestSpec demo test. The FirstTestSpec and QuickSpec classes inherit from XCTestCase. This lets you use the new functionality along with standard methods, such as setUp().

Generally, we recommend breaking your tests into groups. To do so, use the describe function with a description of the test group and the closure/block where tests will be run. The it() function describes a specific test case. This function also contains a description and a block.

At this point, you’ve created an object of the ContactRecord class for simple testing. Now call for matchers, the value correspondence checking functions. These functions are part of the Quick and Nimble frameworks. Use them to check the type of fields and the default values of these fields:

Now press CMD+U and wait for the test to execute. If it executes successfully, Xcode will put a green checkmark next to the FirstTestSpec class. If it fails, a red X will appear.

a green checkmark appears next to the FirstTestSpec class

At first, you’ll need Quick/Nimble’s two primary functions:

  • expect - to
  • expect - notTo

and subsequent checks:

  • equal
  • beAnInstanceOf (for objects)
  • beAKindOf (for classes)
  • beLessThan (and corresponding modifications)
  • beTrue or beFalse
  • beNil (for objects)

Additionally, Quick/Nimble gives you the opportunity to work with asynchronous expectations, which looks like this:

But what if your project deals with diverse exceptions? Don’t worry, you can also test it. Just check out this example:

This is how you can write automated tests with Quick/Nimble. But what about using OHHTTPStubs?

How does OHHTTPStubs work?

If an API doesn’t function properly, no one will adopt it no matter if it’s free, open source, or for cost. Without API testing, you can hardly examine all the possible ways that a user might interact with your app and its related sub-apps. What’s more, API bugs may not only crash a single app but may ruin a chain of business processes relying on it.

Testing API requests helps to debug tasks connected to the return of data from remote and local stores. Indeed, fairly often a response structure may contain invalid data. This may lead to unexpected and probably unpleasant outcomes. To avoid such problems, you need to test the network stack as well.

We advise checking the network stack with the OHHTTPStubs framework. Using OHHTTPStubs, developers can deal with NSUrlConnection and NSUrlSession (i.e. OHHTTPStubs main functionality).

Let’s use the Recipe Puppy API to explore how OHHTTPStubs works. First, create an ApiClient class that will send one simple request to the Recipe Puppy API and receive a list of recipes in return:

Once the request has been executed, you can check the result (e.g. the number of elements in the block or any other characteristics).

Let’s try to prepare a test response for the request. Here we need to create a stub, or a file with prepared data for testing. It’s good practice to write response templates and test with their help.

Once you’ve created the stub, you’ll get json from the puppy_response.json file instead of a response from the remote server. Therefore, you can add your own data to the test target in the project and examine how the app responds to this data.

Once you’ve executed the test, it’s recommended to delete the stubs from the app’s memory. You can do this inside the afterEach closure.

Note that you can also use beforeEach to configure a test before execution. These two functions allow you to control each test state before and after execution:

>

Now you already know some common iOS unit testing frameworks. Let’s now consider a UI testing framework.

How does KIF work?

Creating UI tests is almost the same as creating unit tests. But still, you need to be aware of several differences.

To write a UI test, you can use the standard system framework. However, there are some restrictions. For instance, the target of UI tests is isolated from the app target, so you won’t get full access to the main app target. Such isolation may pose problems with import of classes, which is especially critical for Swift.

To overcome this problem, you can use the KIF system framework. While testing controls, KIF offers a higher animation speed than XCUITest (the basic framework for UI tests) does. Moreover, KIF enables you to interact with objects from the main target.

All tests related to the graphical user interface are executed on the main thread. Start with adding a special extension to support Swift:

>

If you want to access directly an element (e.g. the red button), use the waitForView method:

>

In order to check the properties of any UI component, you can connect Nimble along with the expect function.

Then, create a simple test switching the colors of views and validate these colors. To do this, we need three UIButtons. Set an accessibility label in the interface builder for each of the buttons. After that, create a UITestSpec class and test the buttons. Using the accessibility label, you can perform the tap action on each button and compare each color’s component with the expect function.

>

We’ve decided to make it visual for you and record the color validation. See the video below.

You can also check out the full version of the demo app that we’ve developed to show the capabilities of mobile testing.

Wrapping up

Although mobile app testing may slow down development, it’s an effective tool in the struggle for app quality. Mobile tests help you detect mistakes at an early stage, check the efficiency of your app, and enhance its functionality.

Moreover, mobile app testing is part of continuous integration, and you can always find open source automation frameworks to write your own automated tests.

Follow our Twitter account to keep up with the latest tutorials and articles on iOS development!

CONTENTS

Authors:

Sergey A.

Sergey A.

IOS Developer

Daryna P.

Daryna P.

Copywriter

Rate this article!

Nay
So-so
Not bad
Good
Wow
1 rating, average 5 out of 5

Share article with

Comments (0)

There are no comments yet

Leave a comment

Subscribe via email and know it all first!