Developing complex mobile applications requires the same level of engineering as developing any other web or desktop application. Oddly, it seems to be less common to embrace practices like continuous delivery or even automated testing. That was at least the case in 2013, as stated by Reto Zenger: Continuous Delivery für iOS Apps. If you have already tried to run your iOS tests with the command xcodebuild and then read the log generated, you might have an idea why mobile developers are sometimes unadventurous.
Fortunately, the tooling has evolved a lot in the last few months. The newcomer Fastlane, by Felix Krause, will change a lot of things. I believe that, today, there is absolutely no reason not to have at least a continuous integration server for every mobile Project.
Fastlane is available for both Android and iOS. This article will take iOS as base for the examples. On my Github account, you will find an iOS demo project. It contains a step by step tutorial, guiding you through all the stages required to start performing Continuous Integration on a Jenkins Server.
Why Fastlane? Why Jenkins?
If you want to get rid of the expensive build master, the first step is to find a way to build your app and run the tests on the command line. For iOS, I love to do it with the awesome Fastlane. But alternatives like Apple’s Xcode bots or Facebook’s xctool could also be used.
Fastlane provides a bunch of commands which help automate the deployment of apps. Deployment lanes are defined in a configuration file within your Xcode project. Besides running the tests, several useful workflows can be imagined thanks to various available actions. For example: Snapshot allows you to automatically take the screenshots of your app in several languages, Deliver Uploads your screenshots, metadata and the build to the App Store, Cert helps to manage the iOS code signing certificates… And that’s just the tip of the iceberg.
Fastlane and Jenkins work well together, especially because the output produced by the executed lane is much more human readable than what xcodebuild produces. Besides, the commands are really simple to remember, with lots of sensible defaults and a clean syntax. Jenkins is known to be very flexible, thanks to the enormous amount of maintained plugins available. Combining the flexibility of Jenkins and the power of Fastlane should allow you to cover almost any scenario of delivery for your app.
Both Fastlane and Jenkins are free and open source. Fastlane is developed by Felix Krause. As we can see on his repository, most of the commits are from him. He is however merging lots of pull requests from the community. The amount of work Felix has achieved is impressive. His work was so incredible that Apple approached him to start an internship in the Silicon Valley. Moreover, in October 2015, Fabric, a widely used mobile development suite belonging to Twitter, announced that Fastlane will be integrated in their tool and supported by their team. Felix can now work 100% on Fastlane, which is a very good news if one want to make sure that it remains functional for every new iOS version.
Last but not least, the Android developers now also benefit from Fastlane. This helps of course standardize the deployment process of your apps: one tool to rule them all.
Still not convinced about those tools? Keep reading and look at the screenshots…
Look at the next examples from my demo project, doesn’t it look easy to do CI for iOS?
A simple testing lane could look like this (abstract):
platform :ios do before_all do cocoapods increment_build_number gym(scheme: "IosContinuousIntegration", workspace: "IosContinuousIntegration.xcworkspace", use_legacy_build_api: true) end desc "Runs all the tests" lane :test do scan(device: "iPhone 6s") end end
Then, building the app and running the tests is done with the command:
fastlane ios test
gym, an archive will be added in the Xcode organizer for each build. Therefore, every successful build is ready to be uploaded to the App Store. The scan command will execute the Unit and UI tests in the local simulator.
The integration with Jenkins is straightforward, just execute the same command for every new commit pushed to the repository. No plugin is necessary to run the tests.
Jenkins and Fastlane provide easy integration with Slack, to inform the development team about build failures.
Setting up a CI Server for a project is a very important step. But in order to benefit from it and make it last the distance, the tests have to remain stable and maintainable. You want to make sure that every broken build means: “the last commit broke something“, and not: “the tests failed but I think everything works nevertheless because the tests are flaky“.
This is why using the Xcode UI Tests Recorder to write your UI tests is not enough. Indeed, the code generated is very sensitive to the changes made in the user interface. A common practice in testing that helps avoid it is the Page Object pattern. The idea is to create an object which knows how to interact with the UI. The object is used by every test accessing the corresponding view. The advantage is obvious: if a view changes, only the corresponding object needs to be updated. All the tests using it will automatically benefit from the change. The Xcode Recorder can still be used to figure out how to interact with the UI, but the code needs to be refactored and moved in the corresponding Page Object.
With a CI server for your project, you can now keep improving it incrementally… Sending emails in case of a broken build, configuring authorization to access Jenkins and perform analysis of the code base health are widely used features on CI servers.
You can start thinking about how to automate the user acceptance tests and release parts of your deployment pipeline. Continuous delivery is near… As we have seen, Fastlane can help you there as well. For example, Pilot can be used to upload new builds to TestFlight and distribute them to the testers.
Happy delivery, and keep automating!
- Continous Delivery Book, by Jez Humble and David Farley: http://martinfowler.com/books/continuousDelivery.html
- Integrate Jenkins and Fastlane, by Felix Krause https://github.com/KrauseFx/fastlane/blob/master/docs/Jenkins.md
- Setting up Jenkins on a Mac, by Eric Cerney http://www.cimgf.com/2015/05/26/setting-up-jenkins-ci-on-a-mac-2/
- Automated UI testing in Xcode 7, by Richard North https://rnorth.org/11/automated-ui-testing-in-xcode-7
- Fastlane is now part of Fabric, by Felix Krause https://krausefx.com/blog/fastlane-is-now-part-of-fabric
- Apple headhunts UCLAN student http://www.uclan.ac.uk/news/apple_headhunts_uclan_student.php
- Continuous Delivery with Fastlane (in French), by Patrick Jayet: http://fr.slideshare.net/xrb/fastlane-et-livraison-continue-sous-ios-54270460