diff --git a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Tests/S7SpanReadParityTests.cs b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Tests/S7SpanReadParityTests.cs
index d6d752c8..2dc2152f 100644
--- a/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Tests/S7SpanReadParityTests.cs
+++ b/tests/Drivers/ZB.MOM.WW.OtOpcUa.Driver.S7.Tests/S7SpanReadParityTests.cs
@@ -451,7 +451,7 @@ public sealed class S7SpanReadParityTests
// The connect stamped a LastSuccessfulRead; the pass must move it PAST that value, so a
// frozen timestamp is distinguishable from a merely non-null one.
- var before = driver.GetHealth().LastSuccessfulRead;
+ var before = BaselineStamp(driver);
before.ShouldNotBeNull();
var results = await driver.ReadAsync(ScatteredRefs(3), ct);
@@ -502,7 +502,7 @@ public sealed class S7SpanReadParityTests
using var driver = new S7Driver(Options(tags, maxGap: 16), "s7-span-decode-fault", factory);
await driver.InitializeAsync("{}", ct);
- var before = driver.GetHealth().LastSuccessfulRead;
+ var before = BaselineStamp(driver);
var results = await driver.ReadAsync(["BadStr", "GoodWord"], ct);
// ONE block read served both members — this really is the span path, not two per-tag reads.
@@ -548,7 +548,7 @@ public sealed class S7SpanReadParityTests
using var driver = new S7Driver(Options(NarrowTags(), maxGap: -1), "s7-access-denied", factory);
await driver.InitializeAsync("{}", ct);
- var before = driver.GetHealth().LastSuccessfulRead;
+ var before = BaselineStamp(driver);
var results = await driver.ReadAsync(["A", "B", "C"], ct);
results[0].StatusCode.ShouldNotBe(0u);
@@ -589,7 +589,7 @@ public sealed class S7SpanReadParityTests
using var driver = new S7Driver(Options(NarrowTags(), maxGap: -1), "s7-escalation-message", factory);
await driver.InitializeAsync("{}", ct);
- var before = driver.GetHealth().LastSuccessfulRead;
+ var before = BaselineStamp(driver);
var results = await driver.ReadAsync(["A", "B", "C"], ct);
results[0].StatusCode.ShouldBe(StatusBadDeviceFailure);
@@ -632,7 +632,7 @@ public sealed class S7SpanReadParityTests
using var driver = new S7Driver(Options(tags, maxGap: -1), "s7-cancel-flush", factory);
await driver.InitializeAsync("{}", ct);
- var before = driver.GetHealth().LastSuccessfulRead;
+ var before = BaselineStamp(driver);
using var cts = new CancellationTokenSource();
var reading = driver.ReadAsync(["Narrow", "Wide"], cts.Token);
@@ -802,6 +802,21 @@ public sealed class S7SpanReadParityTests
// ── Fixture ──────────────────────────────────────────────────────────────────────────
/// Driver options over the given tags with the span-grouping knobs under test.
+ ///
+ /// The post-initialise LastSuccessfulRead stamp, taken only once the wall clock has
+ /// moved past it. The driver stamps DateTime.UtcNow at init and again at the read
+ /// pass; under CPU contention both can land in the same clock tick, so a strict
+ /// "LastSuccessfulRead advanced" assertion flaked (#589). Waiting out the tick makes
+ /// any later stamp strictly greater without a fixed delay.
+ ///
+ private static DateTime? BaselineStamp(S7Driver driver)
+ {
+ var stamp = driver.GetHealth().LastSuccessfulRead;
+ if (stamp is { } s)
+ SpinWait.SpinUntil(() => DateTime.UtcNow > s);
+ return stamp;
+ }
+
private static S7DriverOptions Options(IReadOnlyList tags, int maxGap) => new()
{
Host = "192.0.2.1",