Skip to content

Drive contract-base progress timing via ManualProgressTimerCore (Part B) - #280

Merged
Chris-Wolfgang merged 1 commit into
vNextfrom
feat/352-timer-harness
Aug 3, 2026
Merged

Drive contract-base progress timing via ManualProgressTimerCore (Part B)#280
Chris-Wolfgang merged 1 commit into
vNextfrom
feat/352-timer-harness

Conversation

@Chris-Wolfgang

Copy link
Copy Markdown
Owner

Drive contract-base progress timing via ManualProgressTimerCore

Implements Part B of the timer-injection work (tracked in Chris-Wolfgang/ETL-Abstractions#352 / #344). Additive — no downstream change required to adopt.

What

  • New public API (Wolfgang.Etl.TestKit): ManualProgressTimerCore + WithManualProgressTimer(...) extensions for extractor / loader / transformer, mirroring the existing ManualTimeSource / WithTimeSource pattern. Attach the timer, then fire the stage's progress callback deterministically with timer.Tick(). It drives the base's internal timer-core seam via the TestKit ⇆ Abstractions friend relationship — so a component needs no per-type IProgressTimer-injection plumbing to be timer-testable.
  • Contract bases reworked: Extractor/Loader/TransformerBaseContractTests timer tests now build the SUT with the standard CreateSut(...) and attach a ManualProgressTimerCore. They no longer require CreateSutWithTimer, which is demoted abstractvirtual (throws if the base impl runs). Existing downstream overrides still compile and run — nothing breaks on the TestKit bump.

Why

This is the enabler that lets each downstream repo delete its per-component timer boilerplate (~80 src/ files) at its own pace. Combined with Part A (convenience base classes, Abstractions 0.21.0), it supersedes the #96 source generator — the ceremony it targeted is now gone via base/TestKit defaults, no codegen.

Deprecation path

CreateSutWithTimer(IProgressTimer) is documented as deprecated and no longer called by the contract. It is intentionally not [Obsolete]-attributed yet (that would turn existing overrides into warnings→errors downstream under warnings-as-errors). Downstream removes its override + IProgressTimer ctor per repo; the member is dropped in a future major.

Verification

  • Full solution build 0 warn / 0 err.
  • TestKit.Xunit self-tests 313 (exercise the reworked contract timer tests via TestExtractor/TestLoader/TestTransformer), TestKit unit 244 (incl. new ManualProgressTimerCore harness tests), DocExamples green.
  • PublicAPI: new .TestKit entries; .TestKit.Xunit CreateSutWithTimer abstractvirtual.

Adds a Wolfgang.Etl.TestKit-owned manual progress timer that drives the base's
internal timer-core seam (reachable via the TestKit<->Abstractions friend
relationship), so a component needs NO per-type IProgressTimer-injection plumbing
to be timer-testable:

- ManualProgressTimerCore + WithManualProgressTimer(extractor/loader/transformer)
  extensions, mirroring ManualTimeSource / WithTimeSource. Tick() fires the
  stage's progress callback exactly once, deterministically.
- The three *BaseContractTests timer tests now build the SUT with the standard
  CreateSut(...) and attach a ManualProgressTimerCore; they no longer require
  CreateSutWithTimer. That member is demoted abstract -> virtual (throws if the
  base is invoked) so existing downstream overrides still compile — additive, no
  downstream change needed to adopt.

This is #344 Part B: it lets downstream drop the per-component timer boilerplate
(~80 files) and, with Part A (convenience bases), supersedes the #96 generator.

Full solution build 0/0; TestKit.Xunit self-tests 313, TestKit unit 244
(incl. new harness tests), DocExamples green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new deterministic, manual progress-timer mechanism to Wolfgang.Etl.TestKit and updates the xUnit contract-test bases to use it, deprecating the older CreateSutWithTimer(IProgressTimer) path while preserving source compatibility for downstream overrides.

Changes:

  • Introduces ManualProgressTimerCore plus WithManualProgressTimer(...) extension methods for extractor/loader/transformer stages.
  • Reworks *BaseContractTests progress-timer tests to attach ManualProgressTimerCore via the new extensions; demotes CreateSutWithTimer(IProgressTimer) from abstract to virtual (throwing) and documents it as deprecated.
  • Updates PublicAPI tracking and changelog; adds unit tests for the new timer core.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated no comments.

Show a summary per file
File Description
tests/Wolfgang.Etl.TestKit.Tests.Unit/ManualProgressTimerCoreTests.cs Adds unit coverage for ManualProgressTimerCore behavior and null-guarding of the new extensions.
src/Wolfgang.Etl.TestKit/PublicAPI.Unshipped.txt Records the new public API surface (ManualProgressTimerCore and ProgressTimerExtensions).
src/Wolfgang.Etl.TestKit/ProgressTimerExtensions.cs Adds WithManualProgressTimer(...) stage extensions that wire the base timer-core seam to the manual core.
src/Wolfgang.Etl.TestKit/ManualProgressTimerCore.cs Implements the manual timer core (captures the stage tick callback and invokes it synchronously via Tick()).
src/Wolfgang.Etl.TestKit.Xunit/ExtractorBaseContractTests.cs Updates contract timer tests to use ManualProgressTimerCore and deprecates CreateSutWithTimer.
src/Wolfgang.Etl.TestKit.Xunit/LoaderBaseContractTests.cs Updates contract timer tests to use ManualProgressTimerCore and deprecates CreateSutWithTimer.
src/Wolfgang.Etl.TestKit.Xunit/TransformerBaseContractTests.cs Updates contract timer tests to use ManualProgressTimerCore and deprecates CreateSutWithTimer.
src/Wolfgang.Etl.TestKit.Xunit/PublicAPI.Shipped.txt Reflects CreateSutWithTimer changing from abstract to virtual in the shipped API surface.
CHANGELOG.md Documents the new API, the contract-test behavior change, and the deprecation path.

@Chris-Wolfgang
Chris-Wolfgang merged commit 73a4818 into vNext Aug 3, 2026
21 checks passed
@Chris-Wolfgang
Chris-Wolfgang deleted the feat/352-timer-harness branch August 3, 2026 16:29
Chris-Wolfgang added a commit that referenced this pull request Aug 3, 2026
… gate)

Stage 1's per-class 90% coverage gate failed on ProgressTimerExtensions (88%)
— the #280 timer-harness extension. The extractor overload + the three
timer-null guards were covered; the loader/transformer happy-path bodies and
their stage-null guards were not.

Adds ProgressTimerExtensionsTests: loader/transformer overloads attach + return
the stage, and null-argument guards for the loader/transformer overloads →
ProgressTimerExtensions now 100%. Tests-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants