Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/ashfurrow/second_curtain

Upload failing iOS snapshot tests cases to S3
https://github.com/ashfurrow/second_curtain

Last synced: about 1 month ago
JSON representation

Upload failing iOS snapshot tests cases to S3

Awesome Lists containing this project

README

        

Second Curtain
=============================

[![Build Status](https://travis-ci.org/ashfurrow/second_curtain.svg?branch=master)](https://travis-ci.org/ashfurrow/second_curtain)

If you're using the cool [FBSnapshotTestCase](https://github.com/facebook/ios-snapshot-test-case) to test your iOS view logic, awesome! Even better if you have continuous integration, like on [Travis](https://travis-ci.org), to automate running those tests!

Purpose
----------------

Isn't it frustrating that you can't *see* the results of your tests? At best, you'll get this kind of error output:

``` sh
ASHViewControllerSpec
a_view_controller_with_a_loaded_view_should_have_a_valid_snapshot, expected a matching snapshot in a_view_controller_with_a_loaded_view_should_have_a_valid_snapshot
/Users/travis/build/AshFurrow/upload-ios-snapshot-test-case/Demo/DemoTests/DemoTests.m:31

it(@"should have a valid snapshot", ^{
expect(viewController).to.haveValidSnapshot();
});

Executed 1 test, with 1 failure (1 unexpected) in 0.952 (0.954) seconds
** TEST FAILED **
```

Wouldn't it be awesome if we could upload the failing test snapshots somewhere, so we can see exactly what's wrong? That's what we aim to do here.

Usage
----------------

Usage is pretty simple. Have an S3 bucket that is world-readable (that is, include the following bucket policy).

``` json
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::bucket-name/*"
}
]
}
```

(Replace "bucket-name" with your bucket name.)

It's also a good idea not to use a general-purpose S3 user for your CI, so create a new one with the following policy that will let them list buckets, but only read from or write to the bucket you're using.

``` json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListAllMyBuckets"],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::bucket-name"
},
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": "arn:aws:s3:::bucket-name/*"
}
]
}
```

OK, so the hard part is mostly done. Now that we have a place to upload our images, let's configure our build.

I use a Makefile to build and run tests on my iOS project, so my `.travis.yml` file looks something like this:

``` ruby
language: objective-c
cache: bundler

env:
- UPLOAD_IOS_SNAPSHOT_BUCKET_NAME=bucket-name
- UPLOAD_IOS_SNAPSHOT_BUCKET_PREFIX=an/optional/prefix
- AWS_ACCESS_KEY_ID=ACCESS_KEY
- AWS_SECRET_ACCESS_KEY=SECRET_KEY
- AWS_REGION=OPTIONAL_REGION_DEFINITION

before_install:
- bundle install

before_script:
- export LANG=en_US.UTF-8
- make ci

script:
- make test
```

(You can take a look at how to [encrypt information in your config file](http://docs.travis-ci.com/user/encryption-keys/), but this has limitations due to how ecrypted variables are accessed via PRs on forks.)

My Makefile looks like this:

``` sh
WORKSPACE = Demo/Demo.xcworkspace
SCHEME = Demo

all: ci

build:
set -o pipefail && xcodebuild -workspace $(WORKSPACE) -scheme $(SCHEME) -sdk iphonesimulator build | xcpretty -c

clean:
xcodebuild -workspace $(WORKSPACE) -scheme $(SCHEME) clean

test:
set -o pipefail && xcodebuild -workspace $(WORKSPACE) -scheme $(SCHEME) -configuration Debug test -sdk iphonesimulator | second_curtain | xcpretty -c --test

ci: build
```

Notice that we're piping the output from `xcodebuild` into `second_curtain`.

Note also that we're using [`xcpretty`](http://github.com/supermarin/xcpretty), as you should, too. The `xcpretty` invocation must come *after* the `second_curtain` invocation, since Second Curtain relies on parsing the output from `xcodebuild` directly.

And finally, our Gemfile:

```
source 'https://rubygems.org'

gem 'cocoapods'
gem 'xcpretty'
gem 'second_curtain', '~> 0.2'
```

And when any snapshot tests fail, they'll be uploaded to S3 and an [HTML page](https://eigen-ci.s3.amazonaws.com/snapshots/2014-08-04--15-47/index.html) will be generated with links to the images so you can download them. Huzzah!

![Sample diff](http://static.ashfurrow.com/github/second_curtain.png)

Note that when the S3 directory is created, it needs to be *unique*. You can provide a custom folder name with the `UPLOAD_IOS_SNAPSHOT_FOLDER_NAME` environment variable. If one is not provided, Second Curtain will fall back to `TRAVIS_JOB_ID` or `CIRCLE_BUILD_NUM`, and then onto one generated by the current date and time.