Preview into Unit testing via Swift Package Manager

3 minute read

Swift Package Manager just went through a massive refactoring and adds support for testing using XCTest on OSX and Linux. It is not yet available on the latest snapshot but we can always try it out by building swiftpm.

Get the latest swift pm

Install the latest snapshot and run the commands below to build swiftpm, should take about a minute.

$ git clone https://github.com/apple/swift-package-manager $ cd swift-package-manager $ Utilities/bootstrap $ alias sb = $PWD /.build/debug/swift-build $ alias st = $PWD /.build/debug/swift-test

The last two steps will create aliases to swift-build and swift-test (Yes, swiftpm outputs two exectuables now). This is not required but is convienent than using the entire path.

Set up tests structure

I’ll be using the package I created earlier which is a simple GET client.

Create a folder Tests in root of your swift package

in root of your swift package Inside Tests create another folder which will be a test-module, you can create as many test-module (ie folders) you need in case your package contains more than one target

create another folder which will be a test-module, you can create as many test-module (ie folders) you need in case your package contains more than one target According to the proposal it would be possible to directly write test if you have only one target

Create a .swift file to write your tests inside that test-module dir

$ git clone https://github.com/aciidb0mb3r/SimpleGetClient $ cd SimpleGetClient $ mkdir Tests && cd Tests $ mkdir SimpleGetClient & SimpleGetClient $ touch SimpleGetTests.swift

Write Test Cases

Import the package you want to test and XCTest

Subclass XCTestCase

The method name should begin with “test”

Here is an example :

@testable import SimpleGetClient import XCTest class SimpleGetTests : XCTestCase { let client = GetClient () func testGetRequestStatusCode () { let result = client . fetch ( "http://httpbin.org/status/419" ) XCTAssertEqual ( result . responseCode , "419" , "Incorrect value received from server" ) } }

Now run swift build and swift test to build the package and run the tests. Use the aliases created above to use the swift-build and swift-test we built above.

$ sb --clean && sb && st Compiling Swift Module 'SimpleGetClient' ( 1 sources ) Compiling Swift Module 'SimpleGetClienttest' ( 1 sources ) Linking Package.xctest Test Suite 'All tests' started at 2016-02-17 20:37:56.947 Test Suite 'Package.xctest' started at 2016-02-17 20:37:56.948 Test Suite 'SimpleGetTests' started at 2016-02-17 20:37:56.948 Test Case '-[SimpleGetClienttest.SimpleGetTests testGetRequestStatusCode]' started. Test Case '-[SimpleGetClienttest.SimpleGetTests testGetRequestStatusCode]' passed ( 1.836 seconds ) . Test Suite 'SimpleGetTests' passed at 2016-02-17 20:37:58.784. Executed 1 test , with 0 failures ( 0 unexpected ) in 1.836 ( 1.836 ) seconds Test Suite 'Package.xctest' passed at 2016-02-17 20:37:58.784. Executed 1 test , with 0 failures ( 0 unexpected ) in 1.836 ( 1.836 ) seconds Test Suite 'All tests' passed at 2016-02-17 20:37:58.784. Executed 1 test , with 0 failures ( 0 unexpected ) in 1.836 ( 1.837 ) seconds

Tests on Linux

For Linux users, theres a little more wiring up to do. First create an extension to your test case conforming to XCTestCaseProvider and return all the test methods.

#if os(Linux) extension SimpleGetTests : XCTestCaseProvider { var allTests : [( String , () throws -> Void )] { return [ ( "testGetRequestWithOneArg" , testGetRequestWithOneArg ), ( "testGetRequestStatusCode" , testGetRequestStatusCode ), ] } } #endif

Now go to the Tests directory and create a file named LinuxMain.swift and write the following :

import XCTest @testable import SimpleGetClienttest XCTMain ([ SimpleGetTests (), ])

ie import all test-modules by writing <test-module-dirname>test and call the constructor to all your XCTestCase subclasses inside XCTMain method. Now swift-test should work for linux too.

Travis!

I was able to run the test cases on Travis-CI’s Ubuntu distro using this .travis.yml :

sudo : required dist : trusty before_install : - wget -q -O - https://swift.org/keys/all-keys.asc | gpg --import - - wget https://swift.org/builds/development/ubuntu1404/swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a/swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a-ubuntu14.04.tar.gz - tar xzf swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a-ubuntu14.04.tar.gz - export PATH=${PWD}/swift-DEVELOPMENT-SNAPSHOT-2016-02-08-a-ubuntu14.04/usr/bin:"${PATH}" script : - git clone https://github.com/apple/swift-package-manager - cd swift-package-manager && git checkout 151a973 && cd ../ - swift-package-manager/Utilities/bootstrap - ${PWD}/swift-package-manager/.build/debug/swift-build - ${PWD}/swift-package-manager/.build/debug/swift-test

Since swift-test is not currently available in the toolchain, I built swiftpm on travis itself. (Hacks :>)

The package I used is available here : https://github.com/aciidb0mb3r/SimpleGetClient

PS : It was probably a little too early to write this post 😂 but things shouldn’t change a lot.