Skip to content

Commit 8d7ebec

Browse files
committed
Polling Confirmations
Preliminary implementation of polling expectations Make Polling into a function along the lines of Confirmation Additionally, make PollingBehavior an implementation detail of polling, instead of exposed publicly Removes any timeouts involved for polling, as they become increasingly unreliable as the system runs more and more tests Take in configuration arguments, add polling interval Add traits for configuring polling Use consistent naming between confirmAlwaysPasses and the related configuration trait Stop unnecessarily waiting after the last polling attempt has finished. Allow for subsequent polling configuration traits which specified nil for a value to fall back to earlier polling configuration traits before falling back to the default. Add requirePassesEventually and requireAlwaysPasses These two mirror their confirm counterparts, only throwing an error (instead of recording an issue) when they fail. Rewrite confirmPassesEventually when returning an optional to remove the PollingRecorder actor. Now, this uses a separate method for evaluating polling to remove that actor. Clean up the duplicate Poller.evaluate/Poller.poll methods Removed the duplicate poll method, and made evaluate-returning-bool into a wrapper for evaluate-returning-optional Configure polling confirmations as timeout & polling interval This is less direct, but much more intuitive for test authors. Also add exit tests confirming that these values are non-negative Rename to actually use the confirmation name Follow more english-sentence-like guidance for function naming Simplify the polling confirmation API down to just 2 public functions, 1 enum, and 1 error type. Always throw an error when polling fails, get rid of the separate issue recording. Use a single polling confirmation configuration trait Instead of mulitple traits per stop condition, just have a single trait per stop condition.
1 parent b5487b4 commit 8d7ebec

File tree

5 files changed

+1091
-0
lines changed

5 files changed

+1091
-0
lines changed

Sources/Testing/Issues/Issue.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,15 @@ public struct Issue: Sendable {
3838
/// confirmed too few or too many times.
3939
indirect case confirmationMiscounted(actual: Int, expected: any RangeExpression & Sendable)
4040

41+
/// An issue due to a polling confirmation having failed.
42+
///
43+
/// This issue can occur when calling ``confirmation(_:until:within:pollingEvery:isolation:sourceLocation:_:)-455gr``
44+
/// or
45+
/// ``confirmation(_:until:within:pollingEvery:isolation:sourceLocation:_:)-5tnlk``
46+
/// whenever the polling fails, as described in ``PollingStopCondition``.
47+
@_spi(Experimental)
48+
case pollingConfirmationFailed
49+
4150
/// An issue due to an `Error` being thrown by a test function and caught by
4251
/// the testing library.
4352
///
@@ -303,6 +312,8 @@ extension Issue.Kind: CustomStringConvertible {
303312
}
304313
}
305314
return "Confirmation was confirmed \(actual.counting("time")), but expected to be confirmed \(String(describingForTest: expected)) time(s)"
315+
case .pollingConfirmationFailed:
316+
return "Polling confirmation failed"
306317
case let .errorCaught(error):
307318
return "Caught error: \(error)"
308319
case let .timeLimitExceeded(timeLimitComponents: timeLimitComponents):
@@ -442,6 +453,15 @@ extension Issue.Kind {
442453
/// too few or too many times.
443454
indirect case confirmationMiscounted(actual: Int, expected: Int)
444455

456+
/// An issue due to a polling confirmation having failed.
457+
///
458+
/// This issue can occur when calling ``confirmation(_:until:within:pollingEvery:isolation:sourceLocation:_:)-455gr``
459+
/// or
460+
/// ``confirmation(_:until:within:pollingEvery:isolation:sourceLocation:_:)-5tnlk``
461+
/// whenever the polling fails, as described in ``PollingStopCondition``.
462+
@_spi(Experimental)
463+
case pollingConfirmationFailed
464+
445465
/// An issue due to an `Error` being thrown by a test function and caught by
446466
/// the testing library.
447467
///
@@ -485,6 +505,8 @@ extension Issue.Kind {
485505
.expectationFailed(Expectation.Snapshot(snapshotting: expectation))
486506
case .confirmationMiscounted:
487507
.unconditional
508+
case .pollingConfirmationFailed:
509+
.pollingConfirmationFailed
488510
case let .errorCaught(error), let .valueAttachmentFailed(error):
489511
.errorCaught(ErrorSnapshot(snapshotting: error))
490512
case let .timeLimitExceeded(timeLimitComponents: timeLimitComponents):
@@ -503,6 +525,7 @@ extension Issue.Kind {
503525
case unconditional
504526
case expectationFailed
505527
case confirmationMiscounted
528+
case pollingConfirmationFailed
506529
case errorCaught
507530
case timeLimitExceeded
508531
case knownIssueNotRecorded
@@ -575,6 +598,8 @@ extension Issue.Kind {
575598
forKey: .confirmationMiscounted)
576599
try confirmationMiscountedContainer.encode(actual, forKey: .actual)
577600
try confirmationMiscountedContainer.encode(expected, forKey: .expected)
601+
case .pollingConfirmationFailed:
602+
try container.encode(true, forKey: .pollingConfirmationFailed)
578603
case let .errorCaught(error):
579604
var errorCaughtContainer = container.nestedContainer(keyedBy: _CodingKeys._ErrorCaughtKeys.self, forKey: .errorCaught)
580605
try errorCaughtContainer.encode(error, forKey: .error)
@@ -630,6 +655,8 @@ extension Issue.Kind.Snapshot: CustomStringConvertible {
630655
}
631656
case let .confirmationMiscounted(actual: actual, expected: expected):
632657
"Confirmation was confirmed \(actual.counting("time")), but expected to be confirmed \(expected.counting("time"))"
658+
case .pollingConfirmationFailed:
659+
"Polling confirmation failed"
633660
case let .errorCaught(error):
634661
"Caught error: \(error)"
635662
case let .timeLimitExceeded(timeLimitComponents: timeLimitComponents):

0 commit comments

Comments
 (0)