Swift Digest
ST-0028 | Swift Evolution

Swift Testing の AttachmentEncodable の連携を見直す

Revise Swift Testing’s Attachment/Encodable interop

Proposal
ST-0028
Authors
Jonathan Grynspan
Review Manager
Paul LeMarquand
Status
Active Review (August 10...24, 2026)

このダイジェストはClaude Opus 4.7 / 4.8によって生成されたものです(License)。原文はこちら

01 何が問題だったのか

Swift Testing では、Swift 6.2 の ST-0009アタッチメント(attachment) が導入されました。その際、すでに EncodableNSSecureCoding に適合している型については、Attachable プロトコルの要件のデフォルト実装が提供されました。これにより、そうした値をテストレポートやディスクに添付できます。

しかし、この当初のインターフェースにはいくつかの不便な点がありました。

  • 無意味なボイラープレートが必要: すでに EncodableNSSecureCoding に適合している型でも、テストの作者がわざわざ Attachable への適合を明示的に書き足す必要がありました。これは型システムを満足させるだけで、実質的な意味を持たない記述です。
  • エンコード形式の選び方が限られる: property list と JSON のどちらでエンコードするかを選ぶ手段が、アタッチメントの preferred name(推奨される名前)に付ける拡張子しかありませんでした。
  • エンコーダの設定を変えられない: たとえば JSONEncoder.outputFormatting を指定して整形済みの JSON を出力する、といったカスタマイズができませんでした。
  • 両方に適合する型が曖昧: EncodableNSSecureCoding両方 に適合する型のエンコード方法が曖昧でした。デフォルトでは Encodable を使うと文書化されていましたが、この挙動を変える手段はありませんでした。

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

Attachment に新しいイニシャライザを追加します。これは ST-0009 でファイル URL 向けに、ST-0023Transferable 適合型向けに導入されたイニシャライザと同じ流儀のものです。これらは TestingFoundation の両方を import したファイルで利用できます。

これにより、EncodableNSSecureCoding に適合する値を、Attachable への形式的な適合を書かずにそのまま添付できるようになります。

Encodable な値の添付

エンコード形式を AttachableEncodingFormat で指定します。

let menu = FoodTruck.currentMenu
let attachment = try Attachment(encoding: menu, as: .json)
Attachment.record(attachment)

AttachableEncodingFormat には、JSON を表す .json と、property list 形式を表す .propertyListFormat(_:) があります。

let attachment = try Attachment(encoding: recipe, as: .propertyListFormat(.binary))
Attachment.record(attachment)

エンコーダの設定を細かく調整したい場合は、エンコーダそのものを渡すイニシャライザを使います。これにより、JSONEncoder.outputFormatting のようなカスタマイズができます。

let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted]
let attachment = try Attachment(encoding: recipe, using: encoder)
Attachment.record(attachment)

エンコーダを渡すイニシャライザは、Apple プラットフォームでは Combine の TopLevelEncoder に適合するエンコーダを受け取ります。TopLevelEncoder は Combine の一部で非 Apple プラットフォームでは使えないため、非 Apple プラットフォームでは代わりに JSONEncoder / PropertyListEncoder を受け取る具体的なオーバーロードが用意されます。

NSSecureCoding な値の添付

NSSecureCoding に適合する値も、property list 形式を指定して添付できます。

let attachment = try Attachment(encoding: menu, as: .xml)
Attachment.record(attachment)

形式を省略したときの既定

エンコード形式やエンコーダを指定しなかった場合、Swift Testing はアタッチメントの preferred name(拡張子)から形式を推測します(既存のインターフェースと同じ挙動です)。preferred name も指定しなかった場合は、Encodable な型なら JSON、NSSecureCoding な型ならバイナリ property list を既定とします。

なお Encodable 向けのイニシャライザで拡張子から形式を導くときは、".xml" は XML property list、".plist" はバイナリ property list、拡張子なしや ".json" は JSON として扱われます(OpenStep 形式の property list はサポートされません)。

既存インターフェースの非推奨化

Encodable / NSSecureCoding 向けに提供されていた Attachable のデフォルト実装は、将来的な非推奨(to-be-deprecated)としてマークされます。ドキュメントには移行方法が自動的に含まれるようになりますが、ビルド時の新しい診断(deprecation warning)は将来の Swift リリースまで発行されません。

03 今後の見通し

元のProposalでは、次のような発展の方向性が挙げられています。いずれも将来の構想であり、この提案自体で実現されるものではありません。

  • TopLevelEncoder を標準ライブラリへ降ろす: 現在 TopLevelEncoder は Combine で宣言されており、非 Apple プラットフォームでは使えません。これを標準ライブラリへ移せば、すべてのプラットフォームで同じプロトコルが使えるようになり、非 Apple プラットフォーム向けのハードコードされた回避策も取り除けます。著者はこの変更を別途提案する意向を示していますが、この提案の範囲外とされています。
  • 既存インターフェースの正式な非推奨化: 前述のとおり、Encodable / NSSecureCodingAttachable の両方に適合し、デフォルト実装に依存している型に対して、将来の Swift ツールチェインではビルド時に deprecation warning を発行する予定です。