Reorganizing CocoaPod Folder Structure for Unit and Integration Testing

Back | cocoapods, ios, open source | 3/26/2014 |

My first CocoaPod described in this post sparked a discussion with the CocoaPods team. There’re a few things I didn’t like about the project organization.

  1. The name of the workspace was “Demo”. I would expect the project to have the same name as the pod being written.
  2. The demo project contained the Podfile, requiring developers to cd into Demo, then run pod install. I would expect the Podfile to live in the root of the project.
  3. The demo project contained tests for the pod. I would expect the demo to be a demo and to have a test project that unit tests the pod being written.

All these issues can be addressed. I’ve reorganized two of my pods, ARASCIIImageSwizzle and ARTiledImageView and fixed all the issues above.

Folder Structure

Fixing the folder structure and naming is fairly straightforward. You can move the contents of the Demo folder one level up. This brings the Podfile to the root. The Podfile can also explicitly name the workspace.

  1. workspace 'ARASCIISwizzle'
  3. pod 'ARASCIISwizzle', :path => 'ARASCIISwizzle.podspec'
  5. xcodeproj 'Demo.xcodeproj'

You’ll have to update .travis.yml to build a different workspace and to reference the development pod in the same folder.

  1. language: objective-c
  2. before_install:
  3.   - brew update
  4.   - brew uninstall xctool
  5.   - brew install xctool
  6.   - export LANG=en_US.UTF-8
  7.   - gem i cocoapods --no-ri --no-rdoc
  8.   - pod install
  9. xcode_workspace: ARASCIISwizzle.xcworkspace
  10. xcode_scheme: Demo
  11. xcode_sdk: iphonesimulator

You can see this commit in ARTiledImageView that accomplishes the same.

Integration Tests

The tests that are part of the Demo project are really integration tests. I’ve renamed those consequently with a bulk replace of file names and within the source code. You can see it in this commit in ARTiledImageView.

Unit Tests

Lets build a clean unit test project for the pod, independent of the Demo project.

Create a new empty project in XCode called “Tests” or, if you prefer, “UnitTests”.

Add a target.

Screen Shot 2014-03-25 at 2.15.29 PM


Choose Cocoa Touch Unit Testing bundle.

Screen Shot 2014-03-25 at 2.15.48 PM

Open Manage Schemes and make sure the scheme is Shared. Then edit the Test project’s scheme and check the Run box under the Build action.

Screen Shot 2014-03-26 at 9.58.04 AM

The Podfile must now reference “Demo”, “Tests” and the “IntegrationTests” project. The syntax for that is a bit backwards, discussed in

  1. workspace 'ARASCIISwizzle'
  3. pod 'ARASCIISwizzle', :path => 'ARASCIISwizzle.podspec'
  5. xcodeproj 'Demo.xcodeproj'
  7. target 'Demo' do
  8.   pod 'FLKAutoLayout', '~> 0.1.1'
  9.   xcodeproj 'Demo.xcodeproj'
  10. end
  12. target 'IntegrationTests' do
  13.   pod 'Specta', '~> 0.2.1'
  14.   pod 'Expecta', '~> 0.2.3'
  15.   pod 'FBSnapshotTestCase', :head
  16.   pod 'EXPMatchers+FBSnapshotTest', :head
  17.   xcodeproj 'Demo.xcodeproj'
  18. end
  20. target 'Tests' do
  21.   pod 'Specta', '~> 0.2.1'
  22.   pod 'Expecta', '~> 0.2.3'
  23.   pod 'FBSnapshotTestCase', :head
  24.   pod 'EXPMatchers+FBSnapshotTest', :head
  25.   pod 'OCMock', '~> 2.2.3'
  26.   xcodeproj 'Tests.xcodeproj'
  27. end

Travis will build “Tests” and “IntegrationTests” in a matrix.

  1. xcode_scheme:
  2.   - Demo
  3.   - Tests

You can see the results of the above in this commit in ARASCIISwizzle.


This is a lot closer to the Rubygems-style organization where everything is accessible from the top and tests live at the same level as pod classes.