Skip to content

oscarcv/swift-snapshot-testing-attach

Repository files navigation

📎 swift-snapshot-testing-attach

Swift 6.0+ License: MIT

Swift Testing Attachment support for swift-snapshot-testing.

When snapshot tests fail, automatically attach reference snapshots and diff artifacts to Xcode's test report — visible right in the Test Navigator. Works as a standalone extension, no modifications to the original library.

Requires: Swift 6.2+ / Xcode 26+ for Attachment.record().
On older toolchains everything compiles but attachments are a no-op.


Installation

Add to your Package.swift:

dependencies: [
  .package(
    url: "https://github.com/oscarcv/swift-snapshot-testing-attach",
    from: "1.0.0"
  ),
]

Then add to your test target:

.testTarget(
  name: "MyAppTests",
  dependencies: [
    .product(name: "SnapshotTestingAttachments", package: "swift-snapshot-testing-attach"),
  ]
)

swift-snapshot-testing is pulled in automatically — no need to add it separately.


Usage

Drop-In Replacement

Replace assertSnapshot with assertSnapshotWithAttachments:

import Testing
import SnapshotTesting
import SnapshotTestingAttachments

@Suite struct MyViewTests {
  @Test func myView() {
    let view = MyView()
    assertSnapshotWithAttachments(of: view, as: .image)
    // On failure → reference + diff appear as attachments in Xcode
  }
}

Global Configuration

Set attachment behavior once for an entire suite:

// Using the trait (recommended for Swift Testing):
@Suite(.snapshotAttachments(.always))
struct MySnapshotTests {
  @Test func homepage() {
    assertSnapshotWithAttachments(of: homepageView, as: .image)
  }
  @Test func settings() {
    assertSnapshotWithAttachments(of: settingsView, as: .image)
  }
}
// Using withSnapshotAttachments (works with XCTest too):
class FeatureTests: XCTestCase {
  override func invokeTest() {
    withSnapshotAttachments(options: .always) {
      super.invokeTest()
    }
  }
}

Per-Call Override

Override global settings for individual assertions:

// Global is .onFailure, but this one also attaches on record:
assertSnapshotWithAttachments(of: view, as: .image, attachments: .always)

Lower-Level API

Handle attachment data manually:

let result = verifySnapshotWithAttachments(of: myView, as: .image)

if let failure = result.failure {
  for attachment in result.attachmentData {
    print("\(attachment.name): \(attachment.data.count) bytes")
  }
}

Attachment Options

Option Description
.onFailure Attach reference + diff when comparison fails (default)
.onRecord Attach snapshot data when recording new references
.always Both .onFailure and .onRecord

Configuration Resolution Order

When assertSnapshotWithAttachments determines which options to use:

  1. Per-call attachments: parameter (highest priority)
  2. withSnapshotAttachments(options:) scoped configuration
  3. @Suite(.snapshotAttachments(…)) trait configuration
  4. .defaults (.onFailure)

Architecture

This is a standalone extension package — it does not modify swift-snapshot-testing:

swift-snapshot-testing-attach
├── assertSnapshotWithAttachments()   ← wraps verifySnapshot()
├── SnapshotFileLocator               ← computes snapshot file paths
├── SnapshotAttachmentsConfiguration  ← @TaskLocal global config
├── SnapshotAttachmentsTrait          ← TestScoping trait
└── Testing.Attachment.record()       ← Swift 6.2+ only
         │
         ▼ depends on (unmodified)
    swift-snapshot-testing

License

MIT — same as swift-snapshot-testing.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages