Using Xcode Frameworks with macOS targets for fast test running and CI integration.

Introduction

When building software is a good idea to write tests.

For the sake of simplicity (you’ll see why later), I’m going to put unit, integration and system tests into the same tests folder. We will leave end-to-end tests (e2e tests from now on) in a separate folder.

Warning: This post was intended for Xcode 13.4.1

The idea of this post is to show how to:

  1. Setup an Xcode Framework with macOS target for rapid test execution.
  2. Setup CircleCI to run the tests.

Xcode Framework

Create a Framework project.

Observe that My Mac (Mac Catalyst) is selected. This prevents iOS Simulator from booting every time we need to kick off our test suite. This is very important because it dramatically reduces the execution time.

Create a New Scheme

You can name it whatever you want. I choose CI for this example.

Then, Edit your brand new Scheme and click Add Test Target that you want your CI to run.

You may also enable Test Execution Randomization if you want to prevent order execution coupling.

Let’s take the CI for a spin

At this point, the setup is complete. We just need to test our run command before deploying this to CI.

xcodebuild clean build test -scheme "CI" -sdk macosx12.3 CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO

CircleCI YML Configuration File

Add the below YML configuration file inside .circleci/config.yml in your project’s root directory and push the code to your VCS. Then configure your project in CircleCI and trigger a build.

version: 2.1
jobs:
  build:
    macos:
      xcode: 13.4.1
    steps:
      - checkout
      - run:
          name: "Run CI Scheme"
          command: xcodebuild clean build test -scheme "CI" -sdk macosx12.3 CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO

Hopefully you will end up with a screen like the next one.

Conclusion

It takes a few specific steps to build a starter Framework library that can be used for any iOS, iPad, and/or macOS app and be integrated into CircleCI. This allows you and your team to start coding a project without even having to test on real devices or emulators. The best part is that this solution escalates very quickly.

Bonus Track

By the way, do you remember when I told you at the beginning that I was gonna split unit, integration and system tests into one folder and e2e into another? Watch this …

Add another testing target: MyFrameworkE2ETests. It could be anything you want.

Now edit your CI scheme and add the newly created target.

Final thoughts …

By now you may have realized that the CI Scheme allows you to add multiple Targets. In this case, you could use it to specialize your different types of tests: Unit, Integration (and System) tests on one hand and E2E tests on the other; It all depends on how you want to structure the whole project.

Full Xcode Project

https://github.com/lintuxt/xcode-frameworks-and-circle-ci