Skip to content

Commit 0a670ab

Browse files
authored
Swift Testing: Reset file counter for each test (#966)
* Swift Testing: Reset file counter for each test This introduces a new task local to the test scoping trait to allow a test to be repeatedly run. Fixes #963. * wip
1 parent 050a19f commit 0a670ab

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

Sources/SnapshotTesting/AssertSnapshot.swift

+40-10
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,9 @@ public func verifySnapshot<Value, Format>(
318318
if let name = name {
319319
identifier = sanitizePathComponent(name)
320320
} else {
321-
let counter = counterQueue.sync { () -> Int in
322-
let key = snapshotDirectoryUrl.appendingPathComponent(testName)
323-
counterMap[key, default: 0] += 1
324-
return counterMap[key]!
325-
}
326-
identifier = String(counter)
321+
identifier = String(
322+
counter.next(for: snapshotDirectoryUrl.appendingPathComponent(testName).absoluteString)
323+
)
327324
}
328325

329326
let testName = sanitizePathComponent(testName)
@@ -504,8 +501,19 @@ public func verifySnapshot<Value, Format>(
504501

505502
// MARK: - Private
506503

507-
private let counterQueue = DispatchQueue(label: "co.pointfree.SnapshotTesting.counter")
508-
private var counterMap: [URL: Int] = [:]
504+
private var counter: File.Counter {
505+
#if canImport(Testing)
506+
if Test.current != nil {
507+
return File.counter
508+
} else {
509+
return _counter
510+
}
511+
#else
512+
return _counter
513+
#endif
514+
}
515+
516+
private let _counter = File.Counter()
509517

510518
func sanitizePathComponent(_ string: String) -> String {
511519
return
@@ -546,8 +554,30 @@ private class CleanCounterBetweenTestCases: NSObject, XCTestObservation {
546554
}
547555

548556
func testCaseDidFinish(_ testCase: XCTestCase) {
549-
counterQueue.sync {
550-
counterMap = [:]
557+
_counter.reset()
558+
}
559+
}
560+
561+
enum File {
562+
@TaskLocal static var counter = Counter()
563+
564+
final class Counter: @unchecked Sendable {
565+
private var counts: [String: Int] = [:]
566+
private let lock = NSLock()
567+
568+
init() {}
569+
570+
func next(for key: String) -> Int {
571+
lock.lock()
572+
defer { lock.unlock() }
573+
counts[key, default: 0] += 1
574+
return counts[key]!
575+
}
576+
577+
func reset() {
578+
lock.lock()
579+
defer { lock.unlock() }
580+
counts.removeAll()
551581
}
552582
}
553583
}

Sources/SnapshotTesting/SnapshotsTestTrait.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,11 @@
88
}
99

1010
extension Trait where Self == _SnapshotsTestTrait {
11+
/// Configure snapshot testing in a suite or test.
12+
public static var snapshots: Self {
13+
snapshots()
14+
}
15+
1116
/// Configure snapshot testing in a suite or test.
1217
///
1318
/// - Parameters:
@@ -46,7 +51,9 @@
4651
record: configuration.record,
4752
diffTool: configuration.diffTool
4853
) {
49-
try await function()
54+
try await File.$counter.withValue(File.Counter()) {
55+
try await function()
56+
}
5057
}
5158
}
5259
}

0 commit comments

Comments
 (0)