Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save all artifacts to disk in the event of failure #902

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 35 additions & 3 deletions Sources/SnapshotTesting/AssertSnapshot.swift
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public func verifySnapshot<Value, Format>(
}
#endif

guard let (failure, attachments) = snapshotting.diffing.diff(reference, diffable) else {
guard let (failure, attachments, diffValue) = snapshotting.diffing.diff(reference, diffable) else {
return nil
}

Expand All @@ -413,9 +413,24 @@ public func verifySnapshot<Value, Format>(
)
let artifactsSubUrl = artifactsUrl.appendingPathComponent(fileName)
try fileManager.createDirectory(at: artifactsSubUrl, withIntermediateDirectories: true)
let failedSnapshotFileUrl = artifactsSubUrl.appendingPathComponent(
snapshotFileUrl.lastPathComponent)

func artifactFileURL(for artifactType: ArtifactType) -> String {
let baseFileName = "\(testName).\(identifier)"
let artifactFileName = "\(baseFileName)\(artifactType.suffix)"
let result = URL(fileURLWithPath: artifactFileName, isDirectory: false)
return result.appendingPathExtension(snapshotting.pathExtension ?? "").path
}

let failedSnapshotFileUrl = artifactsSubUrl.appendingPathComponent(artifactFileURL(for: .failure))
try snapshotting.diffing.toData(diffable).write(to: failedSnapshotFileUrl)
let referenceSnapshotFileURL = artifactsSubUrl.appendingPathComponent(artifactFileURL(for: .reference))
try snapshotting.diffing.toData(reference).write(to: referenceSnapshotFileURL)

if let diffValue {
let diffFileURL = artifactsSubUrl.appendingPathComponent(artifactFileURL(for: .diff))
try snapshotting.diffing.toData(diffValue).write(to: diffFileURL)
}


if !attachments.isEmpty {
#if !os(Linux) && !os(Windows)
Expand Down Expand Up @@ -498,3 +513,20 @@ private class CleanCounterBetweenTestCases: NSObject, XCTestObservation {
}
}
}

private enum ArtifactType {
case failure
case reference
case diff

var suffix: String {
switch self {
case .failure:
return "_failure"
case .reference:
return "_reference"
case .diff:
return "_diff"
}
}
}
5 changes: 3 additions & 2 deletions Sources/SnapshotTesting/Diffing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ public struct Diffing<Value> {

/// Compares two values. If the values do not match, returns a failure message and artifacts
/// describing the failure.
public var diff: (Value, Value) -> (String, [XCTAttachment])?
public typealias DiffingResult = (String, [XCTAttachment], Value?)
public var diff: (Value, Value) -> DiffingResult?

/// Creates a new `Diffing` on `Value`.
///
Expand All @@ -22,7 +23,7 @@ public struct Diffing<Value> {
public init(
toData: @escaping (_ value: Value) -> Data,
fromData: @escaping (_ data: Data) -> Value,
diff: @escaping (_ lhs: Value, _ rhs: Value) -> (String, [XCTAttachment])?
diff: @escaping (_ lhs: Value, _ rhs: Value) -> DiffingResult?
) {
self.toData = toData
self.fromData = fromData
Expand Down
2 changes: 1 addition & 1 deletion Sources/SnapshotTesting/Internal/Deprecations.swift
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public func _verifyInlineSnapshot<Value>(
let trimmedReference = reference.trimmingCharacters(in: .whitespacesAndNewlines)

// Always perform diff, and return early on success!
guard let (failure, attachments) = snapshotting.diffing.diff(trimmedReference, diffable) else {
guard let (failure, attachments, diffValue) = snapshotting.diffing.diff(trimmedReference, diffable) else {
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SnapshotTesting/Snapshotting/Data.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ extension Snapshotting where Value == Data, Format == Data {
old.count == new.count
? "Expected data to match"
: "Expected \(new) to match \(old)"
return (message, [])
return (message, [], nil)
}
)
}
Expand Down
3 changes: 2 additions & 1 deletion Sources/SnapshotTesting/Snapshotting/NSImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
differenceAttachment.name = "difference"
return (
message,
[oldAttachment, newAttachment, differenceAttachment]
[oldAttachment, newAttachment, differenceAttachment],
difference
)
}
}
Expand Down
33 changes: 17 additions & 16 deletions Sources/SnapshotTesting/Snapshotting/String.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@ extension Diffing where Value == String {
/// A line-diffing strategy for UTF-8 text.
public static let lines = Diffing(
toData: { Data($0.utf8) },
fromData: { String(decoding: $0, as: UTF8.self) }
) { old, new in
guard old != new else { return nil }
let hunks = chunk(
diff: SnapshotTesting.diff(
old.split(separator: "\n", omittingEmptySubsequences: false).map(String.init),
new.split(separator: "\n", omittingEmptySubsequences: false).map(String.init)
))
let failure =
hunks
.flatMap { [$0.patchMark] + $0.lines }
.joined(separator: "\n")
let attachment = XCTAttachment(
data: Data(failure.utf8), uniformTypeIdentifier: "public.patch-file")
return (failure, [attachment])
}
fromData: { String(decoding: $0, as: UTF8.self) },
diff: { old, new in
guard old != new else { return nil }
let hunks = chunk(
diff: SnapshotTesting.diff(
old.split(separator: "\n", omittingEmptySubsequences: false).map(String.init),
new.split(separator: "\n", omittingEmptySubsequences: false).map(String.init)
))
let failure =
hunks
.flatMap { [$0.patchMark] + $0.lines }
.joined(separator: "\n")
let attachment = XCTAttachment(
data: Data(failure.utf8), uniformTypeIdentifier: "public.patch-file")
return (failure, [attachment], nil)
}
)
}
3 changes: 2 additions & 1 deletion Sources/SnapshotTesting/Snapshotting/UIImage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
differenceAttachment.name = "difference"
return (
message,
[oldAttachment, newAttachment, differenceAttachment]
[oldAttachment, newAttachment, differenceAttachment],
difference
)
}
}
Expand Down