1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Swift のテストといえば XCTest が定番でしたが、最近は Swift Testing という新しい選択肢が用意されています。Swift Testing はマクロを使った 簡潔で読みやすい API を特徴としていて、#expect では式の評価値も含めて失敗理由を追いやすい設計になっています。

また、Swift Concurrency と統合され、テストはデフォルトで並列実行される点も、今っぽいです。

前提(環境)

Swift TestingはSwift公式ツールチェーンに含まれていてimport Testingするだけで使い始められます。
そしてXcode 16とSwift 6ツールチェーンに同梱されているため、基本的に「パッケージ依存を追加しなくても使える」立ち上がりの軽さがあります。

クロスプラットフォームも意識されていて、Apple platforms / Linux / Windowsが “Supported” とされています。

まずは最小のテストを書く

Swift Testingの基本形はとても素直です。

import Testing

@Test
func helloWorld() {
    let greeting = "Hello, world!"
    #expect(greeting == "Hello")
}

@Test を付けた関数がテストになり、検証は #expect(...) で書きます。
この #expect は「失敗したときに、式の中で評価された値を拾って分かりやすくする」思想が最初から入っています。

テストをまとめる

テスト関数を型(struct など)に入れて整理するのも王道です。

import Testing

struct VideoTests {
    @Test("Check video metadata")
    func videoMetadata() {
        // ...
        #expect(true)
    }

    @Test
    func rating() async throws {
        // async/throws も自然に書けます
        #expect(true)
    }
}

表示名を付けたいときは @Test("...") のように文字列を渡せます。
また、async throws をそのまま書ける例も公式で出ています。

タグで横断管理する(.tags / @Suite

「このカテゴリのテストだけ回したい」みたいな場面ではタグが便利です。

import Testing

@Test(.tags(.formatting))
func formattedDuration() async throws {
    #expect(true)
}

さらに、スイート側にタグを付けて 配下のテストに継承させる例もあります。

import Testing

@Suite(.tags(.formatting))
struct MetadataPresentation {
    @Test
    func rating() async throws {
        #expect(true)
    }
}

タグやスイートでの整理は、公式でも「柔軟に管理できる」ことが強調されています。

同じテストを量産しない

地味に嬉しいのが パラメタライズドテストです。
同じテストを値だけ変えて回す、を公式の書き方でまとめられます。

import Testing

@Test("Continents mentioned in videos", arguments: [
    "A Beach",
    "By the Lake",
    "Camping in the Woods",
])
func mentionedContinents(videoName: String) async throws {
    // videoName が順に渡ってきます
    #expect(videoName.isEmpty == false)
}

「繰り返しを減らして短く書ける」「Swift Concurrency と統合」「並列実行がデフォルト」という流れと相性が良いです。

テストの挙動をカスタムする

Swift Testingはtraitsで、テストの実行条件などを表現できます。
例えば「条件が満たされるときだけ有効化」や「理由付きで無効化」などです。

import Testing

@Test(.enabled(if: AppFeatures.isCommentingEnabled))
func videoCommenting() {
    #expect(true)
}

@Test(.disabled("Due to a known crash"))
func example() {
    #expect(true)
}

さらに、既知バグとして URL と説明を持たせる例も紹介されています。

XCTest と共存できる

既にXCTestの資産がある場合でも、Swift Testing は XCTest と並行運用でき、段階的に移行しやすい方針になっています。

おわりに

Swift Testing は、公式が言っている通り「マクロで表現力を上げつつ、ボイラープレートを減らす」方向に強く振られています。
個人的には、@Test + #expect の時点で「テスト書くの、ちょっと楽かも」と思えるのが大きいです。

参考

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?