Swift Digest
SE-0129 | Swift Evolution

Package Manager Test Naming Conventions

Proposal
SE-0129
Authors
Anders Bertelrud
Review Manager
Daniel Dunbar
Status
Implemented (Swift 3.0)

01 何が問題だったのか

Swift Package Manager(SwiftPM)では、ソースコードと同様にテストターゲットについても、宣言的ではなく規約(convention)に基づいて構成が決まります。しかし、テストに関する当時の規約にはいくつかの問題がありました。

テストターゲット名が予測しにくい

当時のSwiftPMは、パッケージ最上位の Tests ディレクトリ以下に置かれたディレクトリ名の末尾に、自動的に TestSuite というサフィックスを付けたものをテストモジュール名としていました。

たとえば Tests/Foo/ 以下に置かれたテストのモジュール名は FooTests ではなく FooTestSuite になります。そのため、swift package test で特定のテストだけを実行したいときに、どの名前を渡せばよいのかがディレクトリ構造から一目ではわかりませんでした。これは、モジュール名を使う他のあらゆる場面でも同じ問題を引き起こします。

テストの依存関係を宣言しづらい

テストモジュール名が暗黙に加工されてしまうため、ターゲット依存関係の宣言でテストの名前を指定するのも困難でした。その結果、テストから共通のヘルパーライブラリなどに依存したいという自然なニーズを素直に書けません。

さらに、Tests ディレクトリ配下のモジュールには一律で TestSuite サフィックスが付く仕様だったため、「テストからだけ使うヘルパーライブラリ」を Tests 以下に置くこと自体ができませんでした。

エラーメッセージが分かりにくい

規約が複雑だと、ユーザーが目にする名前とSwiftPM内部の名前がずれ、エラーメッセージも読みにくくなります。ユーザーの意図を規約側から安定して判定できなければ、的確なエラーを出すことも難しくなります。

以上のように、テストの命名規約が「直感的でない」「柔軟性に乏しい」「エラー報告に向かない」という三つの課題を抱えていました。

02 どのように解決されるのか

テストの命名規約をシンプルにし、Sources ディレクトリとの差異をできるだけ減らす方向で整理されました。パッケージ作者が名前をコントロールしやすくなり、予測可能性と柔軟性の両方が向上します。

新しいテストの判定ルール

あるモジュールがテストとみなされるのは、次の両方を満たすときです。

  1. 最上位の Tests ディレクトリ以下に置かれている
  2. モジュール名が Tests で終わる

TestSuite サフィックスを自動で付ける挙動は廃止され、ディレクトリ名がそのままモジュール名になります。つまり、Tests/FooTests/ に置かれたテストのモジュール名は FooTests です。swift package test FooTests のように、ディレクトリ構造から素直に名前を推測できます。

ディレクトリ構成の例

新しい規約のもとでは、次のようなレイアウトが典型的になります。

MyPackage/
├── Package.swift
├── Sources/
│   └── Foo/
│       └── Foo.swift
└── Tests/
    └── FooTests/
        └── FooTests.swift

ここで Tests/FooTests のモジュール名は FooTests であり、Sources/Foo のモジュール名が Foo であるのと対称的な形になります。

テストから他ターゲットへの依存

テストターゲットも通常のターゲットと同じように、依存関係の宣言で名前を指定できるようになりました。たとえばテスト用のヘルパーライブラリに依存させたい場合は、Package.swift で次のように書けます。

.testTarget(
    name: "FooTests",
    dependencies: ["Foo", "TestSupport"]
)

また、Foo というソースターゲットと FooTests というテストターゲットが両方存在する場合、FooTests から Foo への依存は暗黙に設定されます。したがって、被テスト対象に対する依存は多くの場合明示的に書かずに済みます。

一方で、対応するソースターゲット Foo が存在しない FooTests も許容されます。統合テストやフィクスチャなど、特定のソースモジュールと一対一対応しないテストのためのものです。

ディレクトリ配置の制約

この提案の時点では、次の制約が残ります。

  • Tests ディレクトリ以下に実行可能ファイル(executable)や通常のライブラリを置くことはエラー(Linux 向けに必要な LinuxMain.swift のみ例外として許可)
  • Sources ディレクトリ以下にテスト(末尾が Tests のモジュール)を置くことはエラー

これらは将来的な拡張余地を残すための一時的な制約と位置付けられています。テスト専用のヘルパーライブラリやテスト用実行ファイルを Tests 以下に置けるようにする、あるいは Sources 以下にテストを置けるようにする、といった緩和は将来の提案で検討される可能性があります(speculative な方向性であり、実現を約束するものではありません)。

既存コードへの影響

すでに Tests 配下に TestSuite サフィックス前提でモジュールを置いている場合、モジュール名は自動的に加工されなくなるため、Package.swift 中で FooTestSuite のように書いていた参照は FooTests(ディレクトリ名と同じ)に書き換える必要があります。また、Sources 以下に末尾が Tests のモジュールがある場合はリネームが必要です。