Swift5でswift-testingを使用する方法

2024/08/20に公開

概要

Swift5.9からmacroが搭載され、2024年のWWDCではAppleがmacroを活かしたテストライブラリ、「swift-testing」を紹介しました。

swift-testingライブラリ自体は2023年から存在しており、Swift6が出る前から使用自体は可能だったのですが、残念ながら最新のswift-testingではSwift5のサポートが打ち切られており、Swift6しかサポートされていません。

Xcode16の安定版がリリースされていないため、Xcode15では最新のswift-testingを実行する手段がなく、Swift5.9がサポートされていた際にはドキュメントに記述されていた実行方法も削除されてしまっています。

そのため、この記事ではSwift5のままswift-testingライブラリを実行する方法を紹介します。

環境

Apple Swift version 5.10
Xcode Version 15.4

セットアップ

Swift Packageプロジェクトの作成

mkdir swift-testing-example
cd swift-testing-example
swift package init --name swift-testing-example --type library
open Package.swift

Swift Testingライブラリへの依存を追加

Package.swift
// swift-tools-version: 5.10
// The swift-tools-version declares the minimum version of Swift required to build this package.

import PackageDescription

let package = Package(
    name: "swift-testing-example",
    products: [
        // Products define the executables and libraries a package produces, making them visible to other packages.
        .library(
            name: "swift-testing-example",
            targets: ["swift-testing-example"]),
    ],
+   dependencies: [
+       .package(url: "https://github.com/apple/swift-testing.git", from: "0.10.0"),
+   ],
    targets: [
        // Targets are the basic building blocks of a package, defining a module or a test suite.
        // Targets can depend on other targets in this package and products from dependencies.
        .target(
            name: "swift-testing-example"),
        .testTarget(
            name: "swift-testing-exampleTests",
            dependencies: [
                "swift-testing-example",
+               .product(name: "Testing", package: "swift-testing"),
            ]),
    ]
)

AllTestsを作成する

Swift Testingで作成したテストはSwift5ではテストと認識されないため、XCTestとして実行する必要があります。そのため、Swift Testingで作成したテストを実行するテストを記述します。

Tests/swift-testing-exampleTests/AllTests.swift
import Testing
import XCTest

final class AllTests: XCTestCase {
    func testAll() async {
        await XCTestScaffold.runAllTests(hostedBy: self)
    }
}

Swift Testingでテストを記述する

Tests/swift-testing-exampleTests/AddTests.swift
import Testing

func add(a: Int, b: Int) -> Int {
    a + b
}

@Suite("addのテスト")
struct AddTests {
    
    @Test("加算のテスト", arguments: [
        (a: 1, b: 2, expected: 3),
        (a: 2, b: 3, expected: 5),
        (a: 3, b: 4, expected: 7),
    ])
    func test(a: Int, b: Int, expected: Int) {
        #expect(add(a: a, b: b) == expected)
    }
}

AllTestsを実行する

Xcode上からはAllTestsを実行します。ターミナルからswift testを実行しても大丈夫です。

実行して、失敗するとこのように表示されます。

あとがき

Swift Testingのマクロでは、例のように値だけ変えたケースのテストや、並行実行と直列実行の使い分け、失敗時の詳細な比較などがとても便利です。iOS畑の人が最新のSwiftバージョンをなかなか使えないのはもちろん、Server-SideであってもVapor5がリリースされるまではなかなかSwift6に移行できないであろうことが予想されるため、この記事を書きました。

nextbeat Tech Blog

Discussion