This article is the iOS counterpart of Romain’s recent article on tracking code quality with Sonar on Android.
The problematic remains the same: quality is often overlooked for mobile Apps and the cost of setting up a proper quality tracking environment is usually deemed too high. This article will focus on showing that, while the iOS platform is not as tooled as Android, it’s now fast and easy to track code quality on iOS projects.
Even though this has been possible in the past mostly using Java tools (see a preceding post on tracking iOS code quality with Jenkins), it has often been limited to big projects where a quality process has to be enforced (and sometimes some metrics were even part of the contract – even if I am not a big fan of this). The main limitation was in that case the time and expertise to set everything up.
This article follows a presentation we held at soft-shake last October.
For the uninitiated, SonarQube is a continuous quality analysis platform running as a web server that tracks metrics regarding your code and its structure. It can be extended through plugins, and usually embeds useful tools and checks. Historically SonarQube only dealt with Java code but it has been extended since, and it handles most common languages as of today (available features may vary).
Our use case being an iOS application, we are wandering far away from the Java world and there is no official support of this language by SonarSource. Romain Felden and I created a dedicated community plugin – Sonar Objective-C plugin – that enables Objective-C project analysis.
Quite a few tools will have to be installed on your computer, this is clearly the most time-consuming part. Hopefully you will have to do that only once on your CI server (or locally on your workstation):
- SonarQube tooling: you have to install SonarQube, SonarQube Runner and SonarQube Objective-C plugin via the standard plugin install procedure
- Build tooling: xctool, which is replacement for Apple xcodebuild tool with quite a few enhancements. The best way to install it is via HomeBrew. A side note on that point: xctool is only used internally by the plugin to build, test and compute the metrics, it has no impact whatsoever on your project, it will still be built with Xcode/xcodebuild.
- Analysis tooling: you have to install OCLint (violations) and gcovr (code coverage). gcovr is a simple binary to put somewhere in your PATH.
Tip: You may need to go wild and install a development version of OCLint (0.8/0.9) as in my experience, the stable 0.7 version had blockers on my projects
Situation is easier than for Android because there is actually only one build tool: Xcode.
The only things you should do are:
- copy sonar-project.properties in your Xcode project root folder (along your .xcodeproj/.xcworkspace file)
- copy run-sonar.sh in your Xcode project root folder and make it executable (via chmod)
The run-sonar.sh file will stay untouched. You should then describe your project in the sonar-project.properties file, via the following properties:
- sonar.objectivec.appScheme and sonar.objectivec.testScheme/li>
Tip: Comment sonar.objectivec.testScheme if you have no unit/UI tests in your application
After some research, I stumbled upon the iOctoCat open-source application. Despite its name, it has nothing to do with OCTO. It’s an old iOS client for GitHub (by GitHub). This application is interesting because it’s non-trivial, it has some tests (you’re not misreading) and clean dependencies (with CocoaPods).
To push things even further, here is a fork of the repository cleaned up and fixed for the latest version of Xcode.
Stage 1: look ma, no hands
Unfortunately, nothing works out-of-the-box like in Android, where you can get first analysis results with no configuration at all! But there is no free lunch, is there?
Anyway you first need to configure the demo project. This is done with the following command lines:
git clone https://github.com/cyrilpicat/ioctocat
Tip: On a your own project, you don’t have to build the project first, the plugin takes care of that. The bootstrap.sh script is a facility provided by iOctocat developers to download and build all the dependencies of iOctocat
Stage 2: the full monty
You should configure the sonar-project.properties for this project. Here is what mine looks in the end (you can download the file from here):
########################## # Required configuration # ########################## sonar.projectKey=iOctocat sonar.projectName=iOctocat sonar.projectVersion=1.0 sonar.language=objc # Project description sonar.projectDescription=(Old) GitHub client for iOS # Path to source directories (application code, not third-party code) sonar.sources=Classes # Xcode project configuration sonar.objectivec.workspace=iOctocat.xcworkspace sonar.objectivec.projects=iOctocat.xcodeproj sonar.objectivec.appScheme=iOctocat sonar.objectivec.testScheme=iOctocat Unit Tests ########################## # Optional configuration # ########################## # Encoding of the source code sonar.sourceEncoding=UTF-8 # JUnit report generated by run-sonar.sh is stored in sonar-reports/TEST-report.xml # Change it only if you generate the file on your own # The XML files have to be prefixed by TEST- otherwise they are not processed sonar.junit.reportsPath=sonar-reports/ # Paths to exclude from coverage report (tests, 3rd party libraries etc.) # sonar.objectivec.excludedPathsFromCoverage=pattern1,pattern2 sonar.objectivec.excludedPathsFromCoverage=.*Tests.*
Then you run the analysis on your project with the following command line (in your Xcode project root folder):
The dashboard you get is illustrated in the following picture:
If you look at it and compare to its Android counterpart, you will see that quite a few metrics are missing, like:
- Complexity: cyclomatic complexity by method/class/file
- Design: dependencies between classes, files
- Documentation: code documentation (doxygen, appledoc etc.)
- Size: number of statements, number of classes, methods and properties
- Tests: no support for tests other than unit tests (integration, acceptance etc.)
Your next question should be: fine it looks nice and easy but when are we going to have a full support for the Objective-C in SonarQube?
Well that’s not an easy question, as the plugin is done mostly on our free time. But it’s faster with real users: star the GitHub project and I am sure it will go faster!
Aside from this twisted answer, here is the plan as of today:
- have a fix release very soon for the various issues raised since last October (v0.3.2)
- add support for the various test frameworks out-of-there (v0.4)
- add a basic support for the Objective-C language (syntax highlighting, classes, methods etc.) (v0.9)
While I expect to have the first two quite soon, the latter is more my 6-12 months plan. Why so long? Because until now, the plugin was more about getting existing tools work smoothly and with no configuration. Now the hardest work begins: have SonarQube understand the Objective-C language.
Afterwards the plugin should be really useful, but still not as complete and integrated as a supported SonarQube plugin. I must say that on my side I have no plan to get it further the useful stage. But who knows, plans change!
Why did I tell you all this?
Even if the analysis is still limited, it’s nice you can get this analysis with no modification of the project at all. Personally I find it more easy to setup than its Android counterpart.
Either way, now you know how to get relevant metrics out of your neat iOS application in no time using Sonar. No more excuse for not using it on your own project, even if it is a indie iOS App.