This file provides guidance to coding agents when working with code in this repository.
- Preferred entry point: run
./build.ps1from the repository root. This script bootstraps the pinned SDK fromglobal.jsonif needed, packs both library projects, and then runs the test suite inRelease. - Package without tests: run
./build.ps1 -SkipTests. - Run all tests directly:
dotnet test --configuration Release. - Run the xUnit v2 test project only:
dotnet test tests/Logging.XUnit.Tests/MartinCostello.Logging.XUnit.Tests.csproj --configuration Release. - Run the xUnit v3 test project only:
dotnet test tests/Logging.XUnit.v3.Tests/MartinCostello.Logging.XUnit.v3.Tests.csproj --configuration Release. - Run a single test in the v2 suite:
dotnet test tests/Logging.XUnit.Tests/MartinCostello.Logging.XUnit.Tests.csproj --configuration Release --filter "FullyQualifiedName~HttpApplicationTests.Http_Get_Many". - Run a single test in the v3 suite:
dotnet test tests/Logging.XUnit.v3.Tests/MartinCostello.Logging.XUnit.v3.Tests.csproj --configuration Release --filter "FullyQualifiedName~HttpApplicationTests.Http_Get_Many". - Local linting mirrors GitHub Actions:
- PowerShell:
pwsh -NoProfile -Command "$settings = @{ IncludeDefaultRules = $true; Severity = @('Error', 'Warning') }; Invoke-ScriptAnalyzer -Path . -Recurse -ReportSummary -Settings $settings" - Markdown:
markdownlint-cli2 "**/*.md"ifmarkdownlint-cli2is installed. - Workflow files: CI enforces
actionlintandzizmor; run them locally if installed.
- PowerShell:
- The repository ships two NuGet packages:
src/Logging.XUnitfor xUnit v2 andsrc/Logging.XUnit.v3for xUnit v3. - The implementation is intentionally shared. Both package projects link
src/Shared/**/*.csinstead of maintaining separate source trees. Most behavioral changes belong insrc/Shared, not in the per-package project folders. - The v3 project sets the
XUNIT_V3compilation constant. Shared files use#if XUNIT_V3only for the API differences between xUnit v2 and v3, such asITestOutputHelpernamespace changes and v3-specific test cancellation APIs. - The main extension surface lives in shared partial types:
XUnitLoggerExtensions.*addsAddXUnit(...)overloads forILoggingBuilderandILoggerFactory.XUnitLoggerProvider.*adapts either anITestOutputHelperor anIMessageSinkintoILoggerProvider.XUnitLogger.*formats log output, applies filters, adds scopes, and writes to the current output helper or message sink.XUnitLoggerOptionscarries the configurable filter, scope, timestamp, and message factory behavior.AmbientTestOutputHelperAccessor,TestOutputHelperAccessor, andMessageSinkAccessorare the bridge objects used to hand xUnit output infrastructure into the logger.
- Tests follow the same shared-source pattern as production code.
tests/Logging.XUnit.Testsandtests/Logging.XUnit.v3.Testsboth linktests/Shared/**/*.cs, so most test edits should be made once intests/Shared. tests/SampleAppis a small ASP.NET Core app used by the shared integration tests undertests/Shared/Integration. If a change affects end-to-end logging behavior, check those integration tests, not just the unit-style logger tests.
- The v2 and v3 projects deliberately share the same root namespace:
MartinCostello.Logging.XUnit. Do not infer package identity from namespaces alone; use the project/package and theXUNIT_V3symbol. - When changing library behavior, keep v2 and v3 in sync by editing shared files first and then running both test projects. A change that compiles in one project can still break the other because the same source is built twice with different dependencies and symbols.
- The shared tests are also compiled twice. Use
#if XUNIT_V3inside shared tests only when the test API surface genuinely differs between xUnit versions. AddXUnit()without arguments relies onAmbientTestOutputHelperAccessor, which stores the currentITestOutputHelperinAsyncLocal. Tests and fixtures that set or clear the current output helper are exercising this behavior intentionally.- Formatting behavior in
XUnitLoggeris important: timestamps, short log-level names (crit,fail,dbug,info,warn,trce), multiline indentation, and optional scope rendering are all covered by shared tests. - The build is expected to stay warning-free.
.editorconfig,stylecop.json, and the repo ruleset enforce CRLF line endings, a required file header in C# files, file-scoped namespaces, 4-space indentation for code, and 2-space indentation for project/config files. - Outside Visual Studio,
Directory.Build.propsenables coverage collection with a 93% threshold and excludesSampleAppand xUnit assemblies from coverage. If you add tests or move code, keep that coverage behavior in mind. - Tests use
Shouldlyfor assertions andNSubstitutefor doubles. Follow those existing patterns instead of introducing a different assertion or mocking style in shared tests.
- Always ensure code compiles with no warnings or errors and tests pass locally before pushing changes.
- Do not change the public API unless specifically requested.
- Do not use APIs marked with
[Obsolete]. - Bug fixes should always include a test that would fail without the corresponding fix.
- Do not introduce new dependencies unless specifically requested.
- Do not update existing dependencies unless specifically requested.