SwiftParamTest

Test CocoaPods Carthage Compatible SPM Compatible License Twitter

Logo

Swift 的参数化测试。(使用 XCTest)

Screenshot

代码风格

SwiftParamTest 支持两种依赖于 Swift 版本的代码风格。

Result builders API (推荐)

当您使用 Swift 5.1 或更高版本时,我推荐使用此 API。

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)
}

旧版 API

当您使用低于 Swift 5.1 的版本时,您可以使用基于数组字面量的 API,如下所示。

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),
])

基于运算符的 API

您可以使用运算符 ==> 来指定行,如下所示

// 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),
])

保存或输出 Markdown 表格

当启用选项时,保存或输出 markdown 表格(默认情况下全部禁用)。

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 |
}

您也可以指定列标题名称。

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

您也可以从结果中检索 markdown 表格。

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 |

这对于将测试规范表复制并粘贴到 PR 或其他地方很有用。

markdown table in PR

Xcode 代码片段

Xcode Code Snippets

.xcode 目录复制 .codesnippet 文件到以下目录

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

然后重启 Xcode。

或者从存储库的根目录运行以下命令

$ make snippets

示例

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)
        }
    }
}

自定义断言

默认情况下,SwiftParamTest 使用 XCTAssertEqual() 并拥有错误消息。

但您可以使用如下所示的自定义断言。

// 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
    // ----
    //
}

限制

FAQ

无法编译或编译器冲突

此库使用了许多类型推断,因此类型推断有时会失败。这可以通过显式指定类型信息来解决。

例如

// 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)
}

安装

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

Cartfile.private 中写入以下内容。

github "YusukeHosonuma/SwiftParamTest"

作者

Yusuke Hosonuma / tobi462@gmail.com

许可证

SwiftParamTest 使用 MIT 许可证。 有关更多信息,请参见 LICENSE 文件。