Archives for ottobre 2015

ottobre 27, 2015 - No Comments!

Continuous Delivery for iOS

Introduction

The aim of this post is to demonstrate how it is possible to do continuous delivery for iOS. This post contains an example application written in Swift and uses automated tests to drive the development.

We will start from the very beginning, how to bootstrap a new swift project in Xcode and setup a dependency manager.

Then it will be shown how to write unit test and UI tests for an iOS application.

We will finish by showing how it is possible to setup a continuous integration system using an external service, and how to use this service to deploy our application directly to our users.

The project example is at https://github.com/tiagomartinho/StringCalculatorSwift

Project Bootstrap

NOTE: This post was done using Xcode 7.0.1 and Swift 2.0.

Create a New Project

Creating a new iOS project is as simple as opening Xcode and, using the new project assistant, select the single view application template.

Screen Shot 2015-09-03 at 14.48.06Then select the language as Swift and the option to include the unit tests and UI tests, since they will be useful later on.

Screen Shot 2015-10-16 at 13.41.26This creates our project and three targets, one for the application, one for the unit tests, and one  for the functional tests.

Screen Shot 2015-10-02 at 14.19.10If you didn’t select the option to include the tests target in the creation of the project (or you already have a existing project) you could add the tests by adding a new target to the project and select the following templates.

Screen Shot 2015-09-29 at 14.32.41

Setup the Dependency Manager

The dependency manager used in this example is Cocoapods, as from https://cocoapods.org:

“CocoaPods is the dependency manager for Swift and Objective-C Cocoa projects. It has over ten thousand libraries and can help you scale your projects elegantly.”

Setting right away cocoapods gives us the flexibility for later adding external dependencies easily.

To setup cocoapods first is needed to install it (if you don't have it already) by running the command:

> sudo gem install cocoapods

Then it is needed to define a pod file (a simple text file containing all the dependencies of the project)

Here is an example Podfile:

platform :ios, '8.0'
use_frameworks!
target 'MyApp' do
pod 'AFNetworking', '~> 2.5'
pod 'ORStackView', '~> 2.0'
pod 'SwiftyJSON', '~> 2.1'
end

You'll need to run the following command to install the dependencies:

> pod install

From now on we have to work with the workspace instead of the project as before.

All dependencies can be easily used using import statements in our swift files.

import AFNetworking

Writing Our Application

To write our application we will use TDD and to do so we need a way to write and run unit tests efficiently.

Our example application will be an iOS application of the string calculator kata. As seen in https://osherove.com/tdd-kata-1/

Unit Tests

To unit test our application we will use XCTest the Xcode Testing Framework.

To define a new unit test class we use the new file template of Xcode and select Unit Test Case Class.

Screen Shot 2015-10-16 at 13.55.03

One important thing is to add all the classes under test not only to the application target but also to our test target, otherwise the tests cannot see the classes under test.

Screen Shot 2015-09-04 at 14.40.13

Another way is to use the new @testable annotation like that:

@testable import targetOfTheApplication

As seen in https://natashatherobot.com/swift-2-xcode-7-unit-testing-access/

Now we can write our first test:

Screen Shot 2015-10-07 at 14.08.42To run all the tests of the application press: CMD + U

To run all test of the selected test class press: CTRL + OPTION + CMD + U

To run the previous tests press: CTRL + OPTION + CMD + G

From here we can write our String Calculator class using TDD. If you want to follow all the history of the development take a look at the git log https://github.com/tiagomartinho/StringCalculatorSwift/commits/master

UI Tests

To test that our application features work as expected we will use the same Xcode Testing Framework, XCTest.

To define a new UI test class we use the new file template of Xcode and select UI Test Case Class.

Screen Shot 2015-10-16 at 13.59.45

And add it to our UI test target.

Screen Shot 2015-10-07 at 14.13.16

I like to modify the template of Xcode by extracting the application variable and removing the unused  methods and comments:

Screen Shot 2015-10-07 at 14.15.50

To write our first UI test first we have to define the accessibility identifier of our UI in order for them to be accessible by the framework.

This can be done programmatically by code or by setting the property on the storyboard.

Screen Shot 2015-10-07 at 14.20.56

If the UI element does not have the property accessible from the storyboard it is possible to defined it as a user defined runtime attribute.

Screen Shot 2015-10-07 at 14.24.49

After setting the accessibility identifier for the elements of our UI, we are now able to write our UI tests.

To get a reference to the UI element we define a variable as an XCUIElement and based on the type we reference it by doing:

Screen Shot 2015-10-07 at 14.26.45The first test is to assert that all elements of the UI exist and have the correct initial state:

Screen Shot 2015-10-07 at 14.30.24

In the second test we insert text into a text field object and press the calculate button. We then assert that all labels contain the correct text.

Screen Shot 2015-10-12 at 14.12.54

The purpose of this UI tests are not to assert the logic of our app, since we already tested it in the unit test, but to test if the UI behave according to our expectations and if all elements are accessible.

Continuous Integration and Continuous Delivery for iOS

To implement the continuous integration of our app we will use an external service called Greenhouse CI.

The first step is to set the repository where the project is hosted:

Screen Shot 2015-10-12 at 14.27.17

Then all the project information to build the project:

Screen Shot 2015-10-16 at 14.12.33

Greenhouse has a great troubleshoot guide in case you are not able to import correctly the provisioning profiles and certificates.

You can also set the environment using variables or specific files for your scripts, and choose the version of Xcode to use.

Screen Shot 2015-10-19 at 14.13.54

To deploy your application to your users you can configure the tab Publish. In this example we use Beta by Crashlytics (Fabric). You get the API key and Build secret from https://www.crashlytics.com/login?redirect_url=%2Fsettings%2Forganizations if you already have an account from Crashlytics.

Screen Shot 2015-10-14 at 14.18.58

From here you can save the configuration and hit Build.

Screen Shot 2015-10-19 at 14.18.49

After the build finishes you will see in the Fabric website the build available.

Screen Shot 2015-10-19 at 14.21.05

And your testers you receive the following email to test the application.

Screen Shot 2015-10-19 at 14.22.11

Conclusion

In this post we saw how it is possible to do continuous delivery of an iOS application. Starting from the creation of the project to writing our first unit and UI test, till the automatic deploy to our testers.

The sample project is available at https://github.com/tiagomartinho/StringCalculatorSwift