Testing your Kitura apps

This guide will walk you through setting up tests in accordance of the XCTest framework, which is bundled with the Swift binary.

Setting up the Tests directory

In the root level of your project, create a directory called Tests.

Inside Tests create a directory for holding your test suite module. It is recommended that it is the same name as the module you wish to test, suffixed with Tests (for example: if you have a module Foo that you would like to test, create a directory FooTests).


Creating Test Cases

Create a new Swift file in the test suite directory (for example: if you would like to test the Frob feature of your Foo module you might call it FooTests/FrobTests.swift)

Add import XCTest at the top

Add a line @testable import <module-name> for each of the modules you want to access in this set of tests. (Note the @testable keyword allows you to call internal methods in your tests)

Create your testing class as a subclass of XCTestCase (for example: class FrobTests: XCTestCase { ... })

Create each test case as a different function within the testing class (for example: func testFrobbingTheFoo() { ... }). Note that each function must begin with the string “test”. You can use Apple’s guide for tips on how to make good test cases.

For Linux compatibility, you will need to add an additional class variable to your test class named allTests which has a signature like this: (substituting the name of the class in place of FrobTests)

static var allTests : [(String, (FrobTests) -> () throws -> Void)]

This should hold an array of tuples matching a string name to the function name for each test case. For example:

static var allTests : [(String, (FrobTests) -> () throws -> Void)] {
  return [
    ("testFrobbingTheFoo", testFrobbingTheFoo)
  ]
}

Creating Test Main (Linux only)

Inside your Tests directory, create a new file called LinuxMain.swift

In this file import all your test modules. The names of the test modules are the names of your test suite directories (eg: FooTests, which will import any classes defined in Swift files inside the FooTests module).

Import XCTest as well

Invoke XCTMain with an array as follows:

XCTMain([
           testCase(FrobTests.allTests)
        ])

Run Tests

In your projects root directory, run the command swift test after having built them using swift build.


Example files:

Tests/FooTests/FrobTests.swift:

import XCTest
@testable import Foo

class FrobTests: XCTestCase {
  static var allTests: [(String, (FrobTests) -> () throws -> Void)] {
    return [
      ("testFrobbingTheFoo", testFrobbingTheFoo)
    ]
  }

  func testFrobbingTheFoo() {
    let foo = Foo()
    foo.frob()
    foo.frob()
    XCTAssertEqual(2, foo.frobCount, "incorrect number of frobs recorded")
  }
}

Tests/LinuxMain.swift:

import XCTest
@testable import FooTests

XCTMain([
  testCase(FrobTests.allTests)
])

Sources/Foo/Foo.swift:

public class Foo: CustomStringConvertible {
  internal var frobCount = 0

  public func frob() {
    frobCount = frobCount + 1
  }

  public var description: String {
    return (frobCount == 0 ? "unfrobbed" : "frobbed")
  }

  public init() {}
}