From 8105068ea4d120523b066822905cbabc20d7f1b9 Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Thu, 1 Aug 2024 18:13:59 -0400 Subject: [PATCH 01/11] Don't invoke XCTContext when running in the Testing framework. (#884) --- Sources/SnapshotTesting/AssertSnapshot.swift | 5 ++++- .../Internal/RecordIssue.swift | 8 ++++++++ .../AssertSnapshotSwiftTests.swift | 19 +++++++++++++++++++ .../AssertSnapshotSwiftTests/dump.1.txt | 4 ++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift create mode 100644 Tests/SnapshotTestingTests/__Snapshots__/AssertSnapshotSwiftTests/dump.1.txt diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index b2d473d38..7aa1113d9 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -311,7 +311,10 @@ public func verifySnapshot( func recordSnapshot() throws { try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) #if !os(Linux) && !os(Windows) - if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { + if + !isSwiftTesting, + ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") + { XCTContext.runActivity(named: "Attached Recorded Snapshot") { activity in let attachment = XCTAttachment(contentsOfFile: snapshotFileUrl) activity.add(attachment) diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift index 01c700df8..a6953291f 100644 --- a/Sources/SnapshotTesting/Internal/RecordIssue.swift +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -4,6 +4,14 @@ import XCTest import Testing #endif +var isSwiftTesting: Bool { +#if canImport(Testing) + return Test.current != nil + #else + return false + #endif +} + @_spi(Internals) public func recordIssue( _ message: @autoclosure () -> String, diff --git a/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift b/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift new file mode 100644 index 000000000..12528b843 --- /dev/null +++ b/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift @@ -0,0 +1,19 @@ +#if canImport(Testing) + import Testing + import Foundation + import InlineSnapshotTesting + @_spi(Experimental) import SnapshotTesting + + @Suite( + .snapshots( + record: .missing + ) + ) + struct AssertSnapshotTests { + @Test func dump() { + struct User { let id: Int, name: String, bio: String } + let user = User(id: 1, name: "Blobby", bio: "Blobbed around the world.") + assertSnapshot(of: user, as: .dump) + } + } +#endif diff --git a/Tests/SnapshotTestingTests/__Snapshots__/AssertSnapshotSwiftTests/dump.1.txt b/Tests/SnapshotTestingTests/__Snapshots__/AssertSnapshotSwiftTests/dump.1.txt new file mode 100644 index 000000000..0e3f0406c --- /dev/null +++ b/Tests/SnapshotTestingTests/__Snapshots__/AssertSnapshotSwiftTests/dump.1.txt @@ -0,0 +1,4 @@ +▿ User + - bio: "Blobbed around the world." + - id: 1 + - name: "Blobby" From e883fc9ea51e76dc9ed13fd4a92b0ee258a1e8c9 Mon Sep 17 00:00:00 2001 From: stephencelis Date: Thu, 1 Aug 2024 22:14:36 +0000 Subject: [PATCH 02/11] Run swift-format --- Sources/SnapshotTesting/AssertSnapshot.swift | 5 ++--- Sources/SnapshotTesting/Internal/RecordIssue.swift | 6 +++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 7aa1113d9..f7bb12397 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -311,10 +311,9 @@ public func verifySnapshot( func recordSnapshot() throws { try snapshotting.diffing.toData(diffable).write(to: snapshotFileUrl) #if !os(Linux) && !os(Windows) - if - !isSwiftTesting, + if !isSwiftTesting, ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") - { + { XCTContext.runActivity(named: "Attached Recorded Snapshot") { activity in let attachment = XCTAttachment(contentsOfFile: snapshotFileUrl) activity.add(attachment) diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift index a6953291f..214761180 100644 --- a/Sources/SnapshotTesting/Internal/RecordIssue.swift +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -5,10 +5,10 @@ import XCTest #endif var isSwiftTesting: Bool { -#if canImport(Testing) - return Test.current != nil + #if canImport(Testing) + return Test.current != nil #else - return false + return false #endif } From 81bbb328471d97379b1ac99cadf2781da898789b Mon Sep 17 00:00:00 2001 From: Stephen Celis Date: Wed, 7 Aug 2024 12:54:47 -0700 Subject: [PATCH 03/11] Xcode 16 beta 5: Fix snapshots test trait (#885) It is no longer possible to `@_spi(Experimental) import Testing`, so we can no longer ship a custom execution test trait. Instead of using such a trait to override a task local for the duration of a test, we can use a more general trait to store the information, and the assertion helpers can coalesce to the trait, instead. --- Sources/SnapshotTesting/AssertSnapshot.swift | 50 +++++++++++++++++-- .../SnapshotTesting/SnapshotsTestTrait.swift | 28 +++++------ .../SnapshotsTraitTests.swift | 18 +++---- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index f7bb12397..24868e082 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,5 +1,9 @@ import XCTest +#if canImport(Testing) + import Testing +#endif + /// Enhances failure messages with a command line diff tool expression that can be copied and pasted /// into a terminal. @available( @@ -9,12 +13,33 @@ import XCTest "Use 'withSnapshotTesting' to customize the diff tool. See the documentation for more information." ) public var diffTool: SnapshotTestingConfiguration.DiffTool { - get { _diffTool } + get { + _diffTool + } set { _diffTool = newValue } } @_spi(Internals) -public var _diffTool: SnapshotTestingConfiguration.DiffTool = .default +public var _diffTool: SnapshotTestingConfiguration.DiffTool { + get { + #if canImport(Testing) + if let test = Test.current { + for trait in test.traits.reversed() { + if let diffTool = (trait as? _SnapshotsTestTrait)?.configuration.diffTool { + return diffTool + } + } + } + #endif + return __diffTool + } + set { + __diffTool = newValue + } +} + +@_spi(Internals) +public var __diffTool: SnapshotTestingConfiguration.DiffTool = .default /// Whether or not to record all new references. @available( @@ -28,7 +53,26 @@ public var isRecording: Bool { } @_spi(Internals) -public var _record: SnapshotTestingConfiguration.Record = { +public var _record: SnapshotTestingConfiguration.Record { + get { + #if canImport(Testing) + if let test = Test.current { + for trait in test.traits.reversed() { + if let record = (trait as? _SnapshotsTestTrait)?.configuration.record { + return record + } + } + } + #endif + return __record + } + set { + __record = newValue + } +} + +@_spi(Internals) +public var __record: SnapshotTestingConfiguration.Record = { if let value = ProcessInfo.processInfo.environment["SNAPSHOT_TESTING_RECORD"], let record = SnapshotTestingConfiguration.Record(rawValue: value) { diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift index 6b4b82f77..ae9a51ea3 100644 --- a/Sources/SnapshotTesting/SnapshotsTestTrait.swift +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -1,5 +1,5 @@ #if canImport(Testing) - @_spi(Experimental) import Testing + import Testing @_spi(Experimental) extension Trait where Self == _SnapshotsTestTrait { @@ -32,21 +32,21 @@ /// A type representing the configuration of snapshot testing. @_spi(Experimental) - public struct _SnapshotsTestTrait: CustomExecutionTrait, SuiteTrait, TestTrait { + public struct _SnapshotsTestTrait: SuiteTrait, TestTrait { public let isRecursive = true let configuration: SnapshotTestingConfiguration - public func execute( - _ function: @escaping () async throws -> Void, - for test: Test, - testCase: Test.Case? - ) async throws { - try await withSnapshotTesting( - record: configuration.record, - diffTool: configuration.diffTool - ) { - try await function() - } - } + // public func execute( + // _ function: @escaping () async throws -> Void, + // for test: Test, + // testCase: Test.Case? + // ) async throws { + // try await withSnapshotTesting( + // record: configuration.record, + // diffTool: configuration.diffTool + // ) { + // try await function() + // } + // } } #endif diff --git a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift index 0d2a685d2..6d9d0d331 100644 --- a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift @@ -1,13 +1,12 @@ #if compiler(>=6) && canImport(Testing) - @_spi(Experimental) import Testing +import Testing @_spi(Experimental) @_spi(Internals) import SnapshotTesting struct SnapshotsTraitTests { @Test(.snapshots(diffTool: "ksdiff")) func testDiffTool() { #expect( - SnapshotTestingConfiguration.current? - .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + _diffTool(currentFilePath: "old.png", failedFilePath: "new.png") == "ksdiff old.png new.png" ) } @@ -17,8 +16,7 @@ @Test(.snapshots(diffTool: "difftool")) func testDiffToolOverride() { #expect( - SnapshotTestingConfiguration.current? - .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + _diffTool(currentFilePath: "old.png", failedFilePath: "new.png") == "difftool old.png new.png" ) } @@ -28,11 +26,10 @@ @Test func config() { #expect( - SnapshotTestingConfiguration.current? - .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + _diffTool(currentFilePath: "old.png", failedFilePath: "new.png") == "ksdiff old.png new.png" ) - #expect(SnapshotTestingConfiguration.current?.record == .all) + #expect(_record == .all) } @Suite(.snapshots(record: .failed, diffTool: "diff")) @@ -40,11 +37,10 @@ @Test func config() { #expect( - SnapshotTestingConfiguration.current? - .diffTool?(currentFilePath: "old.png", failedFilePath: "new.png") + _diffTool(currentFilePath: "old.png", failedFilePath: "new.png") == "diff old.png new.png" ) - #expect(SnapshotTestingConfiguration.current?.record == .failed) + #expect(_record == .failed) } } } From 6d932a79e7173b275b96c600c86c603cf84f153c Mon Sep 17 00:00:00 2001 From: stephencelis Date: Wed, 7 Aug 2024 19:55:25 +0000 Subject: [PATCH 04/11] Run swift-format --- Tests/SnapshotTestingTests/SnapshotsTraitTests.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift index 6d9d0d331..369e1c70a 100644 --- a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift @@ -1,5 +1,5 @@ #if compiler(>=6) && canImport(Testing) -import Testing + import Testing @_spi(Experimental) @_spi(Internals) import SnapshotTesting struct SnapshotsTraitTests { From 384b1c97cc730523c28bb92f56525f76c87a6815 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Thu, 8 Aug 2024 18:47:23 +0200 Subject: [PATCH 05/11] Feature/fixed decimal separator (#889) * fix formatting of numbers to have stable snapshots as seen in https://github.com/pointfreeco/swift-snapshot-testing/pull/533 * fix to make tests compile https://github.com/pointfreeco/swift-snapshot-testing/pull/887 --------- Co-authored-by: stijn --- Sources/SnapshotTesting/Snapshotting/CGPath.swift | 1 + Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift | 1 + Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/SnapshotTesting/Snapshotting/CGPath.swift b/Sources/SnapshotTesting/Snapshotting/CGPath.swift index cd48ec40e..65470605c 100644 --- a/Sources/SnapshotTesting/Snapshotting/CGPath.swift +++ b/Sources/SnapshotTesting/Snapshotting/CGPath.swift @@ -153,6 +153,7 @@ private let defaultNumberFormatter: NumberFormatter = { let numberFormatter = NumberFormatter() + numberFormatter.decimalSeparator = "." numberFormatter.minimumFractionDigits = 1 numberFormatter.maximumFractionDigits = 3 return numberFormatter diff --git a/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift b/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift index c506bb329..b84a59bf3 100644 --- a/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift +++ b/Sources/SnapshotTesting/Snapshotting/NSBezierPath.swift @@ -105,6 +105,7 @@ private let defaultNumberFormatter: NumberFormatter = { let numberFormatter = NumberFormatter() + numberFormatter.decimalSeparator = "." numberFormatter.minimumFractionDigits = 1 numberFormatter.maximumFractionDigits = 3 return numberFormatter diff --git a/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift b/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift index 12528b843..385b0f2b8 100644 --- a/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift +++ b/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift @@ -1,7 +1,6 @@ #if canImport(Testing) import Testing import Foundation - import InlineSnapshotTesting @_spi(Experimental) import SnapshotTesting @Suite( From c02e52b4d105e9186528b44e44996ac5b80e3537 Mon Sep 17 00:00:00 2001 From: Stijn Willems Date: Thu, 8 Aug 2024 18:54:07 +0200 Subject: [PATCH 06/11] fix missing inline snapshot testing (#887) * fix missing inline snapshot testing * remove the need to import inline in not inline snapshot target --------- Co-authored-by: stijn From 74b3709042a05f888d8a7aab74086e0eb4618828 Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Mon, 9 Sep 2024 16:02:52 -0400 Subject: [PATCH 07/11] Import only the implementation of Testing. (#903) --- Sources/SnapshotTesting/AssertSnapshot.swift | 2 +- Sources/SnapshotTesting/Internal/RecordIssue.swift | 2 +- Sources/SnapshotTesting/SnapshotsTestTrait.swift | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 24868e082..943f2150a 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,7 +1,7 @@ import XCTest #if canImport(Testing) - import Testing +@_implementationOnly import Testing #endif /// Enhances failure messages with a command line diff tool expression that can be copied and pasted diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift index 214761180..58c22184e 100644 --- a/Sources/SnapshotTesting/Internal/RecordIssue.swift +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -1,7 +1,7 @@ import XCTest #if canImport(Testing) - import Testing + @_implementationOnly import Testing #endif var isSwiftTesting: Bool { diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift index ae9a51ea3..d93e12222 100644 --- a/Sources/SnapshotTesting/SnapshotsTestTrait.swift +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -1,5 +1,5 @@ #if canImport(Testing) - import Testing +@_implementationOnly import Testing @_spi(Experimental) extension Trait where Self == _SnapshotsTestTrait { From c1ad88331c179a285ad198ad3b1d194dbfcb454f Mon Sep 17 00:00:00 2001 From: mbrandonw Date: Mon, 9 Sep 2024 20:04:58 +0000 Subject: [PATCH 08/11] Run swift-format --- Sources/SnapshotTesting/AssertSnapshot.swift | 2 +- Sources/SnapshotTesting/SnapshotsTestTrait.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 943f2150a..a521ca966 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,7 +1,7 @@ import XCTest #if canImport(Testing) -@_implementationOnly import Testing + @_implementationOnly import Testing #endif /// Enhances failure messages with a command line diff tool expression that can be copied and pasted diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift index d93e12222..ab8c1801a 100644 --- a/Sources/SnapshotTesting/SnapshotsTestTrait.swift +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -1,5 +1,5 @@ #if canImport(Testing) -@_implementationOnly import Testing + @_implementationOnly import Testing @_spi(Experimental) extension Trait where Self == _SnapshotsTestTrait { From 7b0bbbae90c41f848f90ac7b4df6c4f50068256d Mon Sep 17 00:00:00 2001 From: Brandon Williams Date: Tue, 10 Sep 2024 13:19:51 -0400 Subject: [PATCH 09/11] Add an NB to @_implementationOnly import. --- Sources/SnapshotTesting/AssertSnapshot.swift | 2 ++ Sources/SnapshotTesting/Internal/RecordIssue.swift | 2 ++ Sources/SnapshotTesting/SnapshotsTestTrait.swift | 2 ++ 3 files changed, 6 insertions(+) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index a521ca966..8837fd9db 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,6 +1,8 @@ import XCTest #if canImport(Testing) + // NB: We are importing only the implementation of Testing because that framework is not available + // in Xcode UI test targets. @_implementationOnly import Testing #endif diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift index 58c22184e..a8dad29b5 100644 --- a/Sources/SnapshotTesting/Internal/RecordIssue.swift +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -1,6 +1,8 @@ import XCTest #if canImport(Testing) + // NB: We are importing only the implementation of Testing because that framework is not available + // in Xcode UI test targets. @_implementationOnly import Testing #endif diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift index ab8c1801a..95c4b7915 100644 --- a/Sources/SnapshotTesting/SnapshotsTestTrait.swift +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -1,4 +1,6 @@ #if canImport(Testing) + // NB: We are importing only the implementation of Testing because that framework is not available + // in Xcode UI test targets. @_implementationOnly import Testing @_spi(Experimental) From fb739f2e2c920ccd134b6ff24d2fb782a6b97e6f Mon Sep 17 00:00:00 2001 From: Brandon Williams <135203+mbrandonw@users.noreply.github.com> Date: Tue, 8 Oct 2024 13:05:50 -0400 Subject: [PATCH 10/11] Fix assertSnapshot for Swift Testing tests. (#916) * Fix assertSnapshot for Swift Testing tests. * wip * Update CI --- .github/workflows/ci.yml | 7 +++--- Sources/SnapshotTesting/AssertSnapshot.swift | 9 ++++--- .../Articles/IntegratingWithTestFrameworks.md | 13 +++------- .../MigrationGuides/MigratingTo1.17.md | 17 ++++--------- .../Internal/RecordIssue.swift | 4 +-- .../SnapshotTesting/SnapshotsTestTrait.swift | 6 +---- .../AssertInlineSnapshotSwiftTests.swift | 24 +++++++++++++++++- .../AssertSnapshotSwiftTests.swift | 2 +- .../SnapshotsTraitTests.swift | 2 +- .../SwiftTestingTests.swift | 25 +++++++++++++++++++ .../SwiftTestingTests/testSnapshot.1.txt | 3 +++ .../testSnapshotFailure.1.txt | 3 +++ 12 files changed, 75 insertions(+), 40 deletions(-) create mode 100644 Tests/SnapshotTestingTests/SwiftTestingTests.swift create mode 100644 Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshot.1.txt create mode 100644 Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshotFailure.1.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 719b259d1..27815d448 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -13,10 +13,11 @@ jobs: strategy: matrix: xcode: - - "14.3.1" + - 15.4 + - '16.0' - name: macOS 13 (Xcode ${{ matrix.xcode }}) - runs-on: macos-13 + name: macOS + runs-on: macos-14 steps: - uses: actions/checkout@v3 - name: Select Xcode ${{ matrix.xcode }} diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 8837fd9db..25aed26f3 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -1,9 +1,7 @@ import XCTest #if canImport(Testing) - // NB: We are importing only the implementation of Testing because that framework is not available - // in Xcode UI test targets. - @_implementationOnly import Testing + import Testing #endif /// Enhances failure messages with a command line diff tool expression that can be copied and pasted @@ -421,7 +419,10 @@ public func verifySnapshot( if !attachments.isEmpty { #if !os(Linux) && !os(Windows) - if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS") { + if + ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS"), + !isSwiftTesting + { XCTContext.runActivity(named: "Attached Failure Diff") { activity in attachments.forEach { activity.add($0) diff --git a/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md b/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md index 2f7020772..b11b3437a 100644 --- a/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md +++ b/Sources/SnapshotTesting/Documentation.docc/Articles/IntegratingWithTestFrameworks.md @@ -67,21 +67,14 @@ class FeatureTests: XCTestCase { This will override the `diffTool` and `record` properties for each test function. -Swift's new testing framework does not currently have a public API for this kind of customization. -There is an experimental feature, called `CustomExecutionTrait`, that does gives us this ability, -and the library provides such a trait called ``Testing/Trait/snapshots(diffTool:record:)``. It can -be attached to any `@Test` or `@Suite` to configure snapshot testing: +Swift's new testing framework also allows for this kind of configuration, both for a single test +and an entire test suite. This is done via what are known as "test traits": ```swift -@_spi(Experimental) import SnapshotTesting +import SnapshotTesting @Suite(.snapshots(record: .all, diffTool: .ksdiff)) struct FeatureTests { … } ``` - -> Important: You must import SnapshotTesting with the `@_spi(Experimental)` attribute to get access -to this functionality because Swift Testing's own `CustomExecutionTrait` is hidden behind the same -SPI flag. This means this API is subject to change in the future, but hopefully Apple will -publicize this tool soon. diff --git a/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md b/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md index 489516307..feefdcae3 100644 --- a/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md +++ b/Sources/SnapshotTesting/Documentation.docc/Articles/MigrationGuides/MigratingTo1.17.md @@ -151,16 +151,12 @@ in an XCTest context or a Swift Testing context, and will determine if it should `Issue.record` to trigger a test failure. For the most part you can write tests for Swift Testing exactly as you would for XCTest. However, -there is one major difference. Swift Testing does not (yet) have a substitute for `invokeTest`, -which we used alongside `withSnapshotTesting` to customize snapshotting for a full test class. - -There is an experimental version of this tool in Swift Testing, called `CustomExecutionTrait`, and -this library provides such a trait called ``Testing/Trait/snapshots(diffTool:record:)``. It allows -you to customize snapshots for a `@Test` or `@Suite`, but to get access to it you must perform an -`@_spi(Experimental)` import of snapshot testing: +there is one major difference. In order to override a snapshot's +[configuration]() for a particular test or an entire suite you +must use what are known as "test traits": ```swift -@_spi(Experimental) import SnapshotTesting +import SnapshotTesting @Suite(.snapshots(record: .all, diffTool: .ksdiff)) struct FeatureTests { @@ -169,7 +165,4 @@ struct FeatureTests { ``` That will override the `diffTool` and `record` options for the entire `FeatureTests` suite. - -> Important: As evident by the usage of `@_spi(Experimental)` this API is subject to change. As -soon as the Swift Testing library finalizes its API for `CustomExecutionTrait` we will update -the library accordingly and remove the `@_spi` annotation. +These traits can also be used on individual `@Test`s too. diff --git a/Sources/SnapshotTesting/Internal/RecordIssue.swift b/Sources/SnapshotTesting/Internal/RecordIssue.swift index a8dad29b5..214761180 100644 --- a/Sources/SnapshotTesting/Internal/RecordIssue.swift +++ b/Sources/SnapshotTesting/Internal/RecordIssue.swift @@ -1,9 +1,7 @@ import XCTest #if canImport(Testing) - // NB: We are importing only the implementation of Testing because that framework is not available - // in Xcode UI test targets. - @_implementationOnly import Testing + import Testing #endif var isSwiftTesting: Bool { diff --git a/Sources/SnapshotTesting/SnapshotsTestTrait.swift b/Sources/SnapshotTesting/SnapshotsTestTrait.swift index 95c4b7915..4b53db67c 100644 --- a/Sources/SnapshotTesting/SnapshotsTestTrait.swift +++ b/Sources/SnapshotTesting/SnapshotsTestTrait.swift @@ -1,9 +1,6 @@ #if canImport(Testing) - // NB: We are importing only the implementation of Testing because that framework is not available - // in Xcode UI test targets. - @_implementationOnly import Testing + import Testing - @_spi(Experimental) extension Trait where Self == _SnapshotsTestTrait { /// Configure snapshot testing in a suite or test. /// @@ -33,7 +30,6 @@ } /// A type representing the configuration of snapshot testing. - @_spi(Experimental) public struct _SnapshotsTestTrait: SuiteTrait, TestTrait { public let isRecursive = true let configuration: SnapshotTestingConfiguration diff --git a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift index 0a193452c..382db962f 100644 --- a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift +++ b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift @@ -2,7 +2,7 @@ import Testing import Foundation import InlineSnapshotTesting - @_spi(Experimental) import SnapshotTesting + import SnapshotTesting @Suite( .snapshots( @@ -21,6 +21,28 @@ } } + @Test func inlineSnapshotFailure() { + withKnownIssue { + assertInlineSnapshot(of: ["Hello", "World"], as: .dump) { + """ + ▿ 2 elements + - "Hello" + + """ + } + } matching: { issue in + issue.description == """ + Issue recorded: Snapshot did not match. Difference: … + + @@ −1,3 +1,4 @@ +  ▿ 2 elements +   - "Hello" + + - "World" +   + """ + } + } + @Test func inlineSnapshot_NamedTrailingClosure() { assertInlineSnapshot( of: ["Hello", "World"], as: .dump, diff --git a/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift b/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift index 385b0f2b8..aee524aff 100644 --- a/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift +++ b/Tests/SnapshotTestingTests/AssertSnapshotSwiftTests.swift @@ -1,7 +1,7 @@ #if canImport(Testing) import Testing import Foundation - @_spi(Experimental) import SnapshotTesting + import SnapshotTesting @Suite( .snapshots( diff --git a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift index 369e1c70a..3ac726003 100644 --- a/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift +++ b/Tests/SnapshotTestingTests/SnapshotsTraitTests.swift @@ -1,6 +1,6 @@ #if compiler(>=6) && canImport(Testing) import Testing - @_spi(Experimental) @_spi(Internals) import SnapshotTesting + @_spi(Internals) import SnapshotTesting struct SnapshotsTraitTests { @Test(.snapshots(diffTool: "ksdiff")) diff --git a/Tests/SnapshotTestingTests/SwiftTestingTests.swift b/Tests/SnapshotTestingTests/SwiftTestingTests.swift new file mode 100644 index 000000000..7127981c0 --- /dev/null +++ b/Tests/SnapshotTestingTests/SwiftTestingTests.swift @@ -0,0 +1,25 @@ +#if compiler(>=6) && canImport(Testing) +import Testing +import SnapshotTesting + +@Suite(.snapshots(diffTool: "ksdiff")) +struct SwiftTestingTests { + @Test func testSnapshot() { + assertSnapshot(of: ["Hello", "World"], as: .dump) + } + + @Test func testSnapshotFailure() { + withKnownIssue { + assertSnapshot(of: ["Goodbye", "World"], as: .dump) + } matching: { issue in + issue.description.hasSuffix(""" + @@ −1,4 +1,4 @@ +  ▿ 2 elements + − - "Hello" + + - "Goodbye" +   - "World" + """) + } + } +} +#endif diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshot.1.txt b/Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshot.1.txt new file mode 100644 index 000000000..3b0fb714f --- /dev/null +++ b/Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshot.1.txt @@ -0,0 +1,3 @@ +▿ 2 elements + - "Hello" + - "World" diff --git a/Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshotFailure.1.txt b/Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshotFailure.1.txt new file mode 100644 index 000000000..3b0fb714f --- /dev/null +++ b/Tests/SnapshotTestingTests/__Snapshots__/SwiftTestingTests/testSnapshotFailure.1.txt @@ -0,0 +1,3 @@ +▿ 2 elements + - "Hello" + - "World" From 42a086182681cf661f5c47c9b7dc3931de18c6d7 Mon Sep 17 00:00:00 2001 From: mbrandonw Date: Tue, 8 Oct 2024 17:06:37 +0000 Subject: [PATCH 11/11] Run swift-format --- Sources/SnapshotTesting/AssertSnapshot.swift | 5 +-- .../AssertInlineSnapshotSwiftTests.swift | 2 +- .../SwiftTestingTests.swift | 39 ++++++++++--------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Sources/SnapshotTesting/AssertSnapshot.swift b/Sources/SnapshotTesting/AssertSnapshot.swift index 25aed26f3..fefe1e6f7 100644 --- a/Sources/SnapshotTesting/AssertSnapshot.swift +++ b/Sources/SnapshotTesting/AssertSnapshot.swift @@ -419,10 +419,9 @@ public func verifySnapshot( if !attachments.isEmpty { #if !os(Linux) && !os(Windows) - if - ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS"), + if ProcessInfo.processInfo.environment.keys.contains("__XCODE_BUILT_PRODUCTS_DIR_PATHS"), !isSwiftTesting - { + { XCTContext.runActivity(named: "Attached Failure Diff") { activity in attachments.forEach { activity.add($0) diff --git a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift index 382db962f..9a5d324e3 100644 --- a/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift +++ b/Tests/InlineSnapshotTestingTests/AssertInlineSnapshotSwiftTests.swift @@ -27,7 +27,7 @@ """ ▿ 2 elements - "Hello" - + """ } } matching: { issue in diff --git a/Tests/SnapshotTestingTests/SwiftTestingTests.swift b/Tests/SnapshotTestingTests/SwiftTestingTests.swift index 7127981c0..d7fba7afc 100644 --- a/Tests/SnapshotTestingTests/SwiftTestingTests.swift +++ b/Tests/SnapshotTestingTests/SwiftTestingTests.swift @@ -1,25 +1,26 @@ #if compiler(>=6) && canImport(Testing) -import Testing -import SnapshotTesting + import Testing + import SnapshotTesting -@Suite(.snapshots(diffTool: "ksdiff")) -struct SwiftTestingTests { - @Test func testSnapshot() { - assertSnapshot(of: ["Hello", "World"], as: .dump) - } + @Suite(.snapshots(diffTool: "ksdiff")) + struct SwiftTestingTests { + @Test func testSnapshot() { + assertSnapshot(of: ["Hello", "World"], as: .dump) + } - @Test func testSnapshotFailure() { - withKnownIssue { - assertSnapshot(of: ["Goodbye", "World"], as: .dump) - } matching: { issue in - issue.description.hasSuffix(""" - @@ −1,4 +1,4 @@ -  ▿ 2 elements - − - "Hello" - + - "Goodbye" -   - "World" - """) + @Test func testSnapshotFailure() { + withKnownIssue { + assertSnapshot(of: ["Goodbye", "World"], as: .dump) + } matching: { issue in + issue.description.hasSuffix( + """ + @@ −1,4 +1,4 @@ +  ▿ 2 elements + − - "Hello" + + - "Goodbye" +   - "World" + """) + } } } -} #endif