Skip to content

YusukeHosonuma/SwiftParamTest

Repository files navigation

SwiftParamTest

Test CocoaPods Carthage Compatible SPM Compatible License Twitter

Logo

Parameterized-test for Swift. (with XCTest)

Screenshot

Code Style

SwiftParamTest supports two way of code-style dependent on Swift version.

Result builders API (recommended)

I recommend this API when you use Swift 5.1 or later.

assert(to: max) {
    args(1, 2, expect: 2)
    args(2, 1, expect: 2)
    args(4, 4, expect: 4)
}

// You can also use tuple (with label).

assert(to: max) {
    args((x: 1, y: 2), expect: 2)
    args((x: 2, y: 1), expect: 2)
    args((x: 4, y: 4), expect: 4)
}

Legacy API

You can use array literal based API that like follwing when you use under Swift 5.1.

assert(to: max, expect: [
    args(1, 2, expect: 2),
    args(2, 1, expect: 2),
    args(4, 4, expect: 4),
])

// You can also use tuple (with label).

assert(to: max, expect: [
    args((x: 1, y: 2), expect: 2),
    args((x: 2, y: 1), expect: 2),
    args((x: 4, y: 4), expect: 4),
])

Operator based API

You can specify row by use the operator ==> that like following:

// Function Builder API
assert(to: max) {
    expect((1, 2) ==> 2)
    expect((2, 1) ==> 2)
    expect((4, 4) ==> 4)
}

// Legacy API
assert(to: max, expect: [
    expect((1, 2) ==> 2),
    expect((2, 1) ==> 2),
    expect((4, 4) ==> 4),
])

Save or Output Markdown Table

Save or output markdown table when enabled by option (default is all disable).

override func setUp() {
    ParameterizedTest.option = ParameterizedTest.Option(
        traceTable: .markdown,            // output console is enabled
        saveTableToAttachement: .markdown // save to attachement is enabled
    )
}

override func tearDown() {
    ParameterizedTest.option = ParameterizedTest.defaultOption // restore to default
}

func testExample() {
    assert(to: max) {
        args(1, 2, expect: 2)
        args(2, 1, expect: 2)
        args(4, 4, expect: 4)
    }
    // =>
    // | Args 0 | Args 1 | Expected |
    // |--------|--------|----------|
    // |      1 |      2 |        2 |
    // |      2 |      1 |        2 |
    // |      4 |      4 |        4 |
}

You can also specify column header name too.

func testMarkdownTable() {
    assert(to: max, header: ["x", "y"]) { // specify `header`
        args(1, 2, expect: 2)
        args(2, 1, expect: 2)
        args(4, 4, expect: 4)
    }
    // =>
    // | x | y | Expected |
    // |---|---|----------|
    // | 1 | 2 |        2 |
    // | 2 | 1 |        2 |
    // | 4 | 4 |        4 |
}

markdown table

You can also retrive markdown table from result too.

let tableString = assert(to: max, header: ["x", "y"]) {
                      args(1, 2, expect: 2)
                      args(2, 1, expect: 2)
                      args(4, 4, expect: 4)
                  }.table

print(tableString)
// =>
// | x | y | Expected |
// |---|---|----------|
// | 1 | 2 |        2 |
// | 2 | 1 |        2 |
// | 4 | 4 |        4 |

This is useful for copy and paste the test specification table to PR or others.

markdown table in PR

Xcode Code Snippets

Xcode Code Snippets

Copy .codesnippet files to the following directory from .xcode directory:

~/Library/Developer/Xcode/UserData/CodeSnippets/

and restart Xcode.

Or run the following command from the root of the repository:

$ make snippets

Example

import SwiftParamTest
import XCTest

class ExampleTests: XCTestCase {
    override func setUp() {
        ParameterizedTest.option = ParameterizedTest.Option(traceTable: .markdown,
                                                            saveTableToAttachement: .markdown)
    }

    override func tearDown() {
        ParameterizedTest.option = ParameterizedTest.defaultOption
    }

    func testExample() {
        // for `function`
        assert(to: abs) {
            args( 0, expect: 0)
            args( 2, expect: 2)
            args(-2, expect: 2)
        }

        // for `operator`
        assert(to: +) {
            args(1, 1, expect: 2)
            args(1, 2, expect: 3)
            args(2, 2, expect: 4)
        }

        // for `instance method` (when receiver is not fixed)
        assert(to: String.hasPrefix) {
            args("hello", "he", expect: true)
            args("hello", "HE", expect: false)
        }

        // for `instance method` (when receiver is fixed)
        assert(to: "hello".hasPrefix) {
            args("he", expect: true)
            args("HE", expect: false)
        }
    }
}

Custom Assertion

SwiftParamTest uses XCTAssertEqual() and owns error messages by default.

But you can use custom assertion like follows.

// custom assertion
func customAssert<T: Equatable>(_ actual: T, _ expected: T, file: StaticString, line: UInt) {
    let message = """

    ----
    Expected: \(expected)
    Actual: \(actual)
    ----
    """
    XCTAssert(expected == actual, message, file: file, line: line)
}

// passed by `with` arguments
assert(to: fizzBuzz, with: customAssertion) {
    args(1, expect: "Fizz")
    // =>
    //
    // XCTAssertTrue failed -
    // ----
    // Expected: 1
    // Actual: Fizz
    // ----
    //
}

Limitation

  • Only up to four arguments are supported.

FAQ

Can't compile or compiler is clashed

This library use many type inference, therefore type inference are failed in sometime. This may be resolved by explicitly specifying the type information.

for example:

// Legacy API
assert(to: max, expect: [
    args(1, 2, expect: 2),
    args(2, 1, expect: 2),
    args(4, 4, expect: 4),
] as [Row2<Int, Int, Int>]) // `N` in `RowN` is arguments count

// Function Builder API
typealias T = Int
assert(to: max) {
    args(1 as T, 2 as T, expect: 2)
    args(2 as T, 1 as T, expect: 2)
    args(4 as T, 4 as T, expect: 4)
}

Installation

CocoaPods

pod 'SwiftParamTest'

Swift Package Manager

dependencies: [
    .package(url: "https://github.com/YusukeHosonuma/SwiftParamTest.git", .upToNextMajor(from: "2.2.0")),
],
targets: [
    .testTarget(
        name: "YOUR_TEST_MODULE",
        dependencies: [
            "SwiftParamTest",
        ]),
],

Carthage

Write following to Cartfile.private.

github "YusukeHosonuma/SwiftParamTest"

Author

Yusuke Hosonuma / [email protected]

License

SwiftParamTest is available under the MIT license. See the LICENSE file for more info.