タグ・バグ・時間制限の trait のメタデータを event stream に含める
Include metadata for tags, bugs, and time limit traits in event stream
このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら↗。
01 何が問題だったのか
Swift Testing は、テスト実行中のイベントを JSON Lines 形式で書き出す JSON event stream を備えており、IDE や CI/CD などの外部ツールはこれを購読してテスト結果を解析・可視化します。ところが現状の JSON スキーマには、テストに付与されたメタデータの一部しか含まれておらず、外部ツールから利用できないものがありました。
具体的には、以下のメタデータが JSON 出力に含まれていませんでした。
- タグ(
.tags(...))。テストをカテゴリ分けするために使われます - バグの関連付け(
.bug(...))。テストに関連するバグや課題を表します - 時間制限(
.timeLimit(...))。テストの実行時間に上限を与えます
これらが取得できないことで、外部ツールでは次のような体験を提供しづらい状況がありました。
- IDE 拡張からタグでテストを絞り込む
- CI/CD でテストカテゴリ別にレポートを生成する
- パフォーマンス監視ツールで時間制限つきテストを追跡する
- バグトラッカと連携して、失敗したテストに関連するバグを表示する
これらのメタデータは Swift Testing 内部では既に保持されているにもかかわらず、JSON event stream のスキーマには露出していなかった、というのが本 Proposal の出発点です。
02 どのように解決されるのか
JSON event stream のスキーマバージョン "6.4" 以降で、テスト関数およびテストスイートを表す構造に "tags"、"bugs"、"timeLimit" の 3 つのフィールドを追加します。これらはいずれもオプショナルで、対応する trait がテストに付与されていない場合は出力から省略され、JSON が無駄に肥大化したり null で埋め尽くされたりしないようになっています。
追加は純粋に additive で、既存のスキーマバージョン("0" や "6.3" など)を消費しているツールには影響しません。
スキーマの追加内容
<test-suite> および <test-function> 構造に対する BNF 上の差分は次のとおりです。
["displayName": <string>,]
"sourceLocation": <source-location>,
"id": <test-id>,
- "isParameterized": <bool>
+ "isParameterized": <bool>,
+ ["tags": <array:tag>,]
+ ["bugs": <array:bug>,]
+ ["timeLimit": <number>]
}
+<tag> ::= <string>
+
+<bug> ::= {
+ ["url": <string>,]
+ ["id": <string>,]
+ ["title": <string>]
+}
各フィールドの意味は次のとおりです。
tags: テストに付与されたタグの文字列表現の配列bugs: テストに関連付けられたバグの配列。要素はurl/id/titleを持つオブジェクトで、いずれもオプショナルtimeLimit: テストに設定された時間制限を秒数で表す数値
出力例
たとえば次のようなテスト関数を考えます。
extension Tag {
@Tag public static var blue: Self
@Tag public static var red: Self
public enum Foo {
@Tag public static var bar: Self
}
}
@Test(
.tags(.blue),
.tags(Tag.red),
.bug("https://my.defect.com/1234"),
.bug(id: "12345", "other defect"),
.timeLimit(.minutes(testTimeLimit + 1)),
.timeLimit(.minutes(testTimeLimit)),
.timeLimit(.minutes(testTimeLimit + 10)),
arguments: expectedArgs as [String]
)
func example() {}
このテストに対して新スキーマで生成される JSON の payload には、次のような形でメタデータが含まれます。
{
"kind": "test",
"payload": {
"bugs": [
{ "url": "https://my.defect.com/1234" },
{ "id": "12345", "title": "other defect" }
],
"tags": [
"blue",
"red"
],
"timeLimit": 3
}
}
タグの文字列化ルール
tags フィールドの各要素は、@Tag で宣言された Swift のプロパティを文字列化したものになります。Tag 型からの相対パスとして表現され、Tag 自体や Testing モジュール名のような共通の前置きは取り除かれます。
| trait の書き方 | JSON での文字列 |
|---|---|
.tags(.blue) |
"blue" |
.tags(Tag.blue) |
"blue" |
.tags(Testing.Tag.blue) |
"blue" |
.tags(.Foo.bar) |
"Foo.bar" |
.tags(Tag.Foo.bar) |
"Foo.bar" |
.tags(Testing.Tag.Foo.bar) |
"Foo.bar" |
これにより、Swift コード上の表記の揺れにかかわらず、同じタグであれば JSON 上でも同じ文字列で識別できます。
バグと時間制限の取り扱い
bugs の各要素では url / id / title のいずれもオプショナルで、.bug(_:) や .bug(id:_:) などの呼び出しで指定された情報のみが含まれます。指定されていないキーはオブジェクトから省略されます。
timeLimit は秒単位の数値です。同一テストに複数の .timeLimit(...) が付与されている場合は、Swift Testing 内部で最も短い時間制限が選ばれ、その値が秒に変換されて出力されます。上記の例では、testTimeLimit を含む 3 つの指定のうち最も短い .minutes(testTimeLimit)(テスト実行時の値で 3 秒)が採用されています。
ツール側で期待できる体験
これらのフィールドが揃うことで、JSON event stream を消費するツール側で次のような体験を組み立てられるようになります。
- IDE がテストレポートをタグで並べ替え・絞り込みする
- CI 上でタグごとに集計したテストレポートを生成する
- 時間制限つきテストを抽出し、その実行時間を追跡する
- 既知バグに関連付けられたテストの失敗・成功を、バグトラッカ側と紐付けて表示する
03 今後の見通し
本 Proposal の議論の中で、いくつかの発展方向が挙げられています。いずれも将来の構想であり、実現を約束するものではありません。
timeLimitの単位の表現。今回追加されるtimeLimitフィールドは、Swift Testing 既存 API との一貫性を優先して短い名前を採用し、単位(秒)はスキーマ仕様の文書側に書く形になっています。timeLimitInSecondsのように単位をフィールド名に含める方向や、値とともに単位を表現する方向については、別途 Proposal を立てて検討するとされています。- 追加のメタデータの露出。今回扱った tags / bugs / timeLimit 以外にも、Swift Testing が持つ trait をエコシステムの発展に合わせて JSON event stream に出していく余地があるとされています。