Repository navigation
Add CurrentTest and TestOutputLoggerProvider to DependencyModules.Testing - #119
Merged
Merged
Conversation
…ting Each runner package installs an ICurrentTestProvider over its test framework's own context: TestContext.Current for xUnit, and TestExecutionContext.CurrentContext for NUnit. A library can then read the test that runs, and write to its output, with no reference to a test framework. Hardened can drop [HardenedTest] and its two runner packages for [ModuleTest]. xUnit's output helper throws when a background task writes after its test has finished. The xUnit provider drops that line, so a logger does not throw into the application under test. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
ipjohnson
added a commit
that referenced
this pull request
Sep 25, 2026
* Add DependencyModules.xUnit4 for xunit.v3 4.x xunit.v3 4.0 changed ISelfExecutingXunitTestCase.Run and made the old RunXunitTestCase throw. A ModuleTestCase built against 3.x therefore does not load on 4.x, and a run-time lookup cannot supply a missing interface method. DependencyModules.xUnit stays on [3.2.2,4.0.0). DependencyModules.xUnit4 compiles the same sources against [4.0.0,5.0.0), and Impl/ModuleTestCase.XunitMajor.cs holds the code that differs. The xUnit test projects run on both majors through XunitMajor. The 4.x leg uses xunit.v3.mtp-off, because Microsoft.Testing.Platform v2 refuses VSTest dotnet test on the .NET 10 SDK. A weekly workflow runs the tests on the newest xunit.v3, prereleases included. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> * Add CurrentTest and TestOutputLoggerProvider to DependencyModules.Testing (#119) Each runner package installs an ICurrentTestProvider over its test framework's own context: TestContext.Current for xUnit, and TestExecutionContext.CurrentContext for NUnit. A library can then read the test that runs, and write to its output, with no reference to a test framework. Hardened can drop [HardenedTest] and its two runner packages for [ModuleTest]. xUnit's output helper throws when a background task writes after its test has finished. The xUnit provider drops that line, so a logger does not throw into the application under test. Co-authored-by: Ian Johnson <ianjohnson@mac.mynetworksettings.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Ian Johnson <ianjohnson@mac.mynetworksettings.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #118. Merge that first. I will rebase this branch onto main when it merges.
What
ICurrentTestProviderinDependencyModules.Testing.Attributes.Interfaces:Key,DisplayName,Assembly, andTryWriteLinefor the test that runs.CurrentTestinDependencyModules.Testing.Impl: a static accessor that reads throughCurrentTest.Provider.TestOutputLoggerProviderinDependencyModules.Testing.Impl: anILoggerProviderthat writes each entry to the output of the test that runs, in the single-line format of the console logger (info: Category[0] message).XunitCurrentTestProviderreadsTestContext.Currentin both xUnit builds.NUnitCurrentTestProviderreadsTestExecutionContext.CurrentContext.DependencyModules.TestingtakesMicrosoft.Extensions.Logging.Abstractions, framework-matched at 8.0.0 and 10.0.0.Why
Hardened.Shared.Testing.xUnit and Hardened.Shared.Testing.NUnit exist to supply three things:
[HardenedTest], a provider over the framework's context, and a logger for the test output. With the provider and the logger here, Hardened.Shared.Testing readsCurrentTest, and its users write[ModuleTest]from the runner package they pick.[HardenedTest]adds nothing to[ModuleTest]except the provider install, which the runners now do. Hardened then needs no release for a new xUnit major.Notes
Keyis the framework's own object for the test, as Hardened uses today:TestContext.Current.Teston xUnit and the NUnitTeston NUnit. The framework holds it while the test runs, so a weak table can key per-test state on it.KeyandDisplayNameare null andTryWriteLinereturns false. On NUnit they have values there. Tests pin both, and the docs say so.[Repeat]or[Retry]share oneKey. Each iteration still gets its own container.WriteLinethen throwsInvalidOperationException: There is no currently active test.The xUnit provider catches it. With the catch removed, a pair of tests fails with that exception. Hardened's currentXUnitLoggerhas no such catch.Verified, together with #118
scripts/coverage.sh 85: 1081, 171, 46, and 2 tests pass on net8.0 and net10.0, at 92.3% line coverage.scripts/test-xunit.sh 4: 1082, 171, and 2 tests pass on both TFMs.scripts/verify-packages.sh,dotnet csharpier check ., andnpm run buildpass.After the release
Hardened replaces its own
CurrentTestwith this one, deletes its two runner packages, and changes[HardenedTest]to[ModuleTest]in its tests, thehardened-webtemplate, and its docs (ipjohnson/Hardened.Framework#400).🤖 Generated with Claude Code