Setting up travis-ci for automated unit testing of iOS projects on GitHub

This guide is how I set up new projects to run unit tests automatically when I push a commit or merge a branch on GitHub for iOS projects.

The first step is to create a new project in Xcode. I am going to select a single view application and enable storyboards, Automatic Reference Counting and Unit Tests.

Screen Shot 2013-05-06 at 11.42.27 PM

All I’m going to change is the testExample method in the unit testing bundle to something that will pass. For now I have just gone with this:

- (void)testExample
{
    STAssertNil(nil, @"This object should be nil");
}

Check that the tests pass by hitting cmd+u. Now that I have my unit tests passing, I’m going to add this project to GitHub. I’ll leave the details out here, as this isn’t the focus of this tutorial but you can find my example project here: https://github.com/daniel-beard/SettingUpTravisCIForiOS.

Now we can setup the TravisCI build. I use the xctool to build my projects as it has a nicer output and is easier to use than the built in xcodebuild tool. Add xctool as a submodule to the git repository using the following commands:

git submodule add https://github.com/facebook/xctool.git ./xctool
git submodule update --init
git commit ./xctool -m "Added xctool as a submodule"

Then we need to add a config file so that travis-ci knows how to build our project. This file is named .travis.yml and lives in the root of the git repository. Here is the contents of mine:

language: objective-c
before_install: "git submodule init && git submodule update && sudo gem update --system && sudo gem install bundler && bundle install"
script: "bundle exec rake test --trace"

Then we have to add a Rakefile that tells the xctool which project and target to build:

desc 'Run the tests'
task :test do
   exec('xctool/xctool.sh -project SettingUpTravisCIForiOS.xcodeproj -scheme SettingUpTravisCIForiOS test')
end

task :default => :test

And finally the Gemfile

source 'https://rubygems.org'

gem 'rake'

You can then test locally that your project builds using the command rake in your root git repository.
I get build messages, then ** TEST SUCCEEDED: 1 of 1 tests passed ** (25285 ms). Now that we have the unit tests running locally, all that is left is to set up the travis-ci build. Login to https://travis-ci.org/ with your GitHub account and under account settings select the repository that should be unit tested automatically. This automatically sets up a service hook in GitHub so that every time you push to your repository, it will get unit tested.

You can also use the status images from travis-ci to show the test status directly in your README file on GitHub. Check out my example project here: SettingUpTravisCIForiOS

Git notes

This is a list of git notes that I use everyday. Hopefully someone else finds it useful. I will update this list over time.

  • The master branch reflects production ready code only. This branch should be deployable at any time and merges to this branch should not break the build process.
  • Feature branches should be merged into the master when they are complete.
  • Feature branches consist of a single feature or discrete unit of work
  • Commit early and commit often!

Generating SSH-Public Key

  1. Switch to your .ssh directory and check if the id_rsa.pub file exists, this is your public key
  2. If it doesn’t exist, generate one with the following commandssh-keygen -t rsa -C "youremail@email.com"Output is something like the following:
    Generating public/private rsa key pair.
    Enter file in which to save the key (/Users/danielbeard/.ssh/id_rsa): 
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in /Users/danielbeard/.ssh/id_rsa.
    Your public key has been saved in /Users/danielbeard/.ssh/id_rsa.pub.
    The key fingerprint is:
    43:c5:5b:5h:b1:f1:51:43:ad:20:a6:92:6a:1f:8a:3a danielbeard@iosdev.local
    

Copy the contents of the public key file to your clipboard:
pbcopy < ~/.ssh/id_rsa.pub

Normal Workflow

  • Checkout the remote repository with: git clone git@github.com:AustralianFinanceGroup/SalesTools.git
  • Updating the repository (won’t need to be done the first time): git pull
  • Create a new branch from the master or current development branch git checkout -b featurebranchname master
  • Make changes to local files
  • Check local modifications with git status
  • Stage certain files with git add <file1> <file2> etc or add all changes git add .
  • Commit to you local repository git commit -m 'commit message'
  • Push the local commit to the remote repository and set up for tracking git push -u origin featurebranchname
  • Repeat until feature branch is complete.
  • Merge master or development branch into the working branch
    • git checkout master
    • git pull
    • git checkout featurebranchname
    • git merge master
  • Push to remote repository git push -u origin featurebranchname
  • Submit pull request and wait for code review

Repository Changes

  • Checking which files are in what state: git status
  • Tracking new files: git add README
  • Committing your changes: git commit -m 'Commit message goes here'
  • Push your current master to the remote origin: git push -u origin master
  • Unstaging a staged file: git reset HEAD <file>
  • Stage all untracked files – git add -u
  • Unmodifying a modified file: git checkout -- benchmarks.rb

Notes:

  • The git add command stages a file for a commit. Calling git status shows which files are staged/unstaged or if they are untracked.
  • If you modify a file after calling git add, the git status command will show the file as being both staged and unstaged.
  • If you modify a file after calling git add, you have to run git add again to stage the latest version of the file
    Providing the -a option to git commit makes git automatically stage every file before doing the commit. (Letting you skip the git add part)

Basic repository changes: http://git-scm.com/book/en/Git-Basics-Recording-Changes-to-the-Repository

Branching

  • Creating a new branch: git checkout -b branchname
  • Branching from a current branch: git checkout -b feature devbranch
  • Pushing branch to remote with tracking: git push -u origin branchname
  • Rename branch git branch -m <oldname> <newname>
  • Delete the local branch: git branch -d branchname
  • Delete the remote branch: git push origin :branchname
  • Listing all branches: git branch -a
  • Just list remote branches: git branch -r
  • Checking out a tracked remote branch: git checkout --track origin/branch_name
  • Merging a branch
    • Must have committed all changes (at least locally) like so: git commit -a -m "Made a change in this branch"
    • Switch to whichever branch you are merging back into, e.g. master git checkout master
    • Merge the branch (ALWAYS USE NO-FF): git merge --no-ff branchname

Notes:

Tracked branches are local branches that have a direct relationship to a remote branch.
If you’re on a tracking branch and type git push or git pull, git automatically knows which branch and server to push/pull from.

Git remote branches :http://git-scm.com/book/en/Git-Branching-Remote-Branches#Tracking-Branches
Git local branches: http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging

Tagging

  • Only used for tagging master branch merges or “releases”
  • You can tag at any point, it doesn’t have to be immediately.
  • Show the commit history like this: git log --pretty=oneline
15027957951b64cf874c3557a0f3547bd83b3ff6 Merge branch 'experiment'
a6b4c97498bd301d84096da251c98a07c7723e65 beginning write support
0d52aaab4479697da7686c15f77a3d64d9165190 one more thing
6d52a271eda8725415634dd79daabbc4d9b6008e Merge branch 'experiment'
0b7434d86859cc7b8c3d5e1dddfed66ff742fcbc added a commit function
4682c3261057305bdd616e23b64b0857d832627b added a todo file
166ae0c4d3f420721acbb115cc33848dfcc2121a started write support
9fceb02d0ae598e95dc970b74767f19372d61af8 updated rakefile
964f16d36dfccde844893cac5b347e7b3d44abbc commit the todo
8a5cbc430f1a9c3d00faaeffd07798508422908a updated readme
  • To tag a certain commit, specify the commit checksum (or part of it) at the end of the command git tag -a v1.2.1 9fceb02
  • Then to transfer all your tags to the remote repository git push origin --tags

Git tags: http://git-scm.com/book/en/Git-Basics-Tagging

Tracking changes between branches

  • Show the modified files between two branches: git diff --name-status master..branch
  • Show side by side comparison : git difftool -t vimdiff master..branch

Other notes and links

Git aliases: http://git-scm.com/book/en/Git-Basics-Tips-and-Tricks#Git-Aliases
Branching model: http://nvie.com/posts/a-successful-git-branching-model/
GitHub flow: http://scottchacon.com/2011/08/31/github-flow.html