Skip to content

Instantly share code, notes, and snippets.

@ianpartridge
Created August 9, 2017 13:00
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ianpartridge/aa572ae4dba15155787fafca956413c1 to your computer and use it in GitHub Desktop.
Save ianpartridge/aa572ae4dba15155787fafca956413c1 to your computer and use it in GitHub Desktop.
Swift Packages: Linux Compatibility Testing

Swift Packages: Linux Compatibility Testing

As the Swift on Linux and Swift Package Manager ecosystems mature, many authors of Swift packages want to enable their packages on Linux as well as Apple platforms. The growth of Server-Side Swift makes Linux an important target for many packages.

The first step is to run a package's unit tests on Linux, to verify it behaves as expected.

Enabling unit tests on Linux

Because Swift on Linux does not use the Objective-C runtime, the dynamic features that the XCTest unit testing framework uses to automatically discover testcases are not available.

However, you can easily enable your XCTest unit tests for Linux by following these steps:

  1. In the Tests directory of your Swift package, create a new file. By convention this is named LinuxMain.swift.

  2. In it, call XCTMain(), passing in an array of all your testcase classes:

    XCTMain([
      testCase(TestOne.allTests),
      testCase(TestTwo.allTests),
    ])
  3. Add an additional property in each of your testcase classes, named allTests by convention. This array should contain all your unit tests.

    class TestOne : XCTestCase {
      static var allTests = {
        return [
          ("test_a", test_a),
          ("test_b", test_b),
          // etc
        ]
      }()
      
      func test_a() {
        XCTAssertEqual(2+2, 4)
      }
      
      func test_b() {
        XCTAssertEqual(2*2, 4)
      }
    }

To run your tests, type swift test as normal.

Testing Swift packages on Linux

Even if you don't have access to a Linux machine, it's still easy to run a Swift package's unit tests on Linux by using Docker.

After installing Docker for Mac on your desktop machine you can run the following commands to easily execute unit tests on Linux:

$ cd MyPackage
$ docker run --rm -v "$(pwd):/pkg" -w "/pkg" swift:latest /bin/bash -c "swift test --build-path ./.build/linux"

The docker run arguments mean as follows:

  • --rm: automatically remove the Docker container from disk when it exits.
  • -v "$(pwd):/pkg": bind mount the current working directory to /pkg in the Docker container, so that your package files are visible inside the container.
  • -w "/pkg": when the container starts, change to the /pkg working directory.
  • swift:latest: use the latest version of the Swift image from Docker Hub. This image packages the latest version of Swift and is based on Ubuntu 16.04 LTS.
  • /bin/bash -c "swift test --build-path ./.build/linux": execute the swift test command in the container, using a custom build path. This ensures that the Linux build artifacts are kept separate from any macOS binaries you may have already created.

Assuming the tests all pass, you should see:

Total executed 1 test, with 0 failures (0 unexpected) in 0.0 (0.005) seconds

Next Steps

Once a Swift package runs on Linux, it's best practice to advertise this in the project's README.md file. You might also consider adding a badge from shields.io.

If your project uses a Continuous Integration service like Travis CI you should add automated Linux testing, to avoid regressions.

You can also submit your package to the IBM Swift Package Catalog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment