diff --git a/.github/dependabot.yml b/.github/dependabot.yml index aa1787b..31d0807 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -29,11 +29,12 @@ updates: - "PhoenixmlDb.*" # Test tooling churns often and rarely interestingly. One PR, not six. + # Microsoft.NET.Test.Sdk and coverlet.collector were dropped with the move to + # Microsoft.Testing.Platform; the MTP packages themselves arrive transitively through + # xunit.v3, so "xunit*" is the whole surface Dependabot can see here. test-tooling: patterns: - "xunit*" - - "Microsoft.NET.Test.Sdk" - - "coverlet*" ignore: # FluentAssertions 7.x and 8.x moved to the paid Xceed licence. docmd's core is diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dfcfac..d3a058c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,39 @@ stylesheet writes against is not stable until `1.0`. ## [Unreleased] +Test infrastructure only. **No product change**: nothing under `src/` was touched, and no shipped +package reference moved. + +### Changed + +- **xunit.v3 3.2.2 → 4.0.1**, which runs on Microsoft.Testing.Platform and drops VSTest. The + test platform moved with it; `dotnet test docmd.slnx` and the existing `--filter` expressions + are unchanged. + + The opt-in is `"test": { "runner": "Microsoft.Testing.Platform" }` in `global.json`. The + property the error message points at, `TestingPlatformDotnetTestSupport`, is the pre-.NET-10 + bridge and cannot help: MTP 2.4.0 raises the error from inside that bridge's own target, + guarded on the SDK major version alone. + + Three VSTest-only packages were removed rather than bumped, because under MTP they do nothing: + `Microsoft.NET.Test.Sdk`, `xunit.runner.visualstudio` and `coverlet.collector`. Test projects + gained `Exe`, which `Microsoft.NET.Test.Sdk` used to supply. + + Verified: 363 tests — 362 pass, 1 skip (the corpus audit) — which is the pre-migration count + of 362 plus the one performance test the old filter had excluded; `--locked-mode` restore + clean; the performance gate still runs in isolation. + + A run that executes no tests now exits 8 rather than passing, so a filter that matches nothing + fails CI instead of going green. Full reasoning in + [`docs/deferred-work.md`](docs/deferred-work.md). + +### Fixed + +- `src/Docmd.Cli/packages.lock.json` recorded `Ooxml.Md.Core` at `0.2.3` after the 0.2.4 release. + Regenerating the lock files corrected it. Worth knowing that `--locked-mode` does not catch + this: it validates package versions, not the project-reference versions in the same file, so + that field goes stale on every release and nothing complains. + ## [0.2.4] — 2026-09-29 Dependencies. **No behaviour change**: output is byte-identical across the 13-document corpus. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1969ef4..14774cf 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -57,6 +57,32 @@ deliberately not: `fixtures/real/sample.docx` is a genuine third-party-written d `word-noise` carries Word's own mess — `w:proofErr`, rsids, bookmarks between runs, words split mid-word at spell-check boundaries. Those two find bugs hand-written XML never does. +### The test platform + +Tests run on **Microsoft.Testing.Platform**, not VSTest. `dotnet test docmd.slnx` is unchanged, +and so is `--filter "FullyQualifiedName~Something"` — xunit.v3 4.x accepts VSTest filter syntax. +Three things are worth knowing: + +- **Each test project is an executable.** `OutputType` is `Exe`, set centrally in + `Directory.Build.props` for any project whose name ends in `.Tests`, and you can run one + without `dotnet test`: + + ```console + $ ./tests/Docmd.Word.Tests/bin/Release/net10.0/Docmd.Word.Tests + $ ./tests/Docmd.Word.Tests/bin/Release/net10.0/Docmd.Word.Tests -class Docmd.Word.Tests.TransformScalingTests + ``` + + Run that way it is xunit's own in-process console runner, whose options are single-dash and + different (`-class`, `-method`, `-trait`; `--help` lists them). The MTP options that + `dotnet test` accepts, `--filter` included, are rejected there with `unknown option`. +- **A run that executes no tests fails**, with exit code 8. Under VSTest a filter that matched + nothing was a silent pass, which is the vacuous pass above with CI's name on it. +- **A VSTest filter cannot be combined** with xunit's own `--filter-class` / `--filter-method` / + `--filter-query` forms. Pick one style per invocation. + +The opt-in is `"test": { "runner": "Microsoft.Testing.Platform" }` in `global.json`. Without it +the SDK runs the VSTest command, which on .NET 10 fails the build rather than falling back. + ### Running the corpus audit Against your own documents: diff --git a/Directory.Build.props b/Directory.Build.props index 71f7966..5916770 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -37,6 +37,20 @@ https://github.com/phoenixmldb/docmd true + + + Exe + + diff --git a/Directory.Packages.props b/Directory.Packages.props index 9352051..28f87df 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,10 +7,22 @@ - - - - + + diff --git a/docs/deferred-work.md b/docs/deferred-work.md index e244f03..aa7d312 100644 --- a/docs/deferred-work.md +++ b/docs/deferred-work.md @@ -60,11 +60,12 @@ already dead, while the anchor text survives. Recorded so the corpus audit can r - `docmd audit`, `-r`/`--recursive`, `--review`, `--style-map`, `--strict`, `--report` and `--revisions` all currently fail cleanly as not-yet-supported. -## xunit v3 4.0 needs a test-platform migration, not a version bump +## xunit v3 4.0 needed a test-platform migration, not a version bump -**Status:** open, deliberately deferred 2026-09-10. Pinned at xunit.v3 3.2.2. +**Status:** closed 2026-09-29. On xunit.v3 4.0.1, running on Microsoft.Testing.Platform 2.4.0. -xunit.v3 4.0.0 drops VSTest support on the .NET 10 SDK and requires Microsoft.Testing.Platform: +xunit.v3 4.0 drops VSTest on the .NET 10 SDK. The error names a property that sounds like the +fix and is not: ``` error : Testing with VSTest target is no longer supported by Microsoft.Testing.Platform @@ -72,19 +73,39 @@ on .NET 10 SDK and later. If you use dotnet test, you should opt-in to the new d test experience. ``` -Setting `TestingPlatformDotnetTestSupport` is not sufficient on its own; the `dotnet test` CLI -needs its own opt-in as well. Beyond that, MTP changes filter syntax, and `--filter -"FullyQualifiedName~X"` appears in `.github/workflows/ci.yml` (which runs the performance gate as -its own step), in `CONTRIBUTING.md` twice, and in the corpus-audit instructions. All of them -change together or none do. - -Deferred because it is orthogonal to shipping, and a hurried test-infrastructure migration -immediately before a first release is a poor trade: the thing that tells you whether the release -is sound is the last thing to rebuild in a hurry. Nothing about 3.2.2 is broken. - -**Closes with:** `dotnet.config` selecting the MTP runner, the property above, the filter -expressions rewritten in all four places, and a CI run proving the performance gate still runs -in isolation. +`TestingPlatformDotnetTestSupport=true` is the pre-.NET-10 bridge: it redirects the VSTest +target into `InvokeTestingPlatform`. MTP 2.4.0 removed that escape hatch, and the removal is +what produces the error above. `Microsoft.Testing.Platform.MSBuild.targets` raises it from +`_MTPBeforeVSTest`, guarded on nothing but the SDK major version and a variable named +`_SupportsGlobalJsonTestRunner` — so the property cannot suppress it, and the refusal is +conditioned on a *better* opt-in being available. The SDK agrees: `dotnet test --help` on +10.0.401 says to opt in "via global.json". + +**What it actually took**, which was less than this entry predicted: + +- `global.json` gains `"test": { "runner": "Microsoft.Testing.Platform" }`. Not `dotnet.config`, + which this entry guessed at; that is a different mechanism and not what this SDK reads. +- Three packages removed rather than bumped, all VSTest-only and inert under MTP: + `Microsoft.NET.Test.Sdk`, `xunit.runner.visualstudio`, `coverlet.collector`. Reasoning is in + `Directory.Packages.props`. Coverage, if anyone ever wants a number, is `coverlet.mtp` or + `Microsoft.Testing.Extensions.CodeCoverage`; nothing here has asked for one. +- `Exe` for test projects, which `Microsoft.NET.Test.Sdk` used to supply + implicitly. It is in `Directory.Build.props` conditioned on the project name, because + `IsTestProject` is set long after `.props` is evaluated and a condition on it never matches. +- **The filter rewrite was unnecessary.** This entry expected `--filter + "FullyQualifiedName~X"` to change in four places. xunit.v3 4.x ships `--filter` accepting + VSTest syntax, so CI, `CONTRIBUTING.md` and the corpus-audit instructions are unchanged and + still correct. The restriction is that a VSTest filter cannot be combined with xunit's own + `--filter-class` / `--filter-query` forms, which nothing here does. + +**What we gained rather than paid for:** a run that executes no tests now exits 8 instead of +passing. A filter typo used to be a silent green — measured, not assumed: +`--filter "FullyQualifiedName~NoSuchTestNameAtAll"` exits 8, and the real suite exits 0. + +Verified on 2026-09-29, against this commit: 363 tests — 362 pass, 1 skip (the corpus audit), +which is the pre-migration count of 362 plus the one performance test the old filter excluded. +`--locked-mode` restore clean; the performance gate still runs alone. The count is recorded as a +dated measurement rather than as a standing fact; the suite is the fact. ## Formats diff --git a/global.json b/global.json index 01cb658..a0703e8 100644 --- a/global.json +++ b/global.json @@ -2,5 +2,8 @@ "sdk": { "version": "10.0.400", "rollForward": "latestFeature" + }, + "test": { + "runner": "Microsoft.Testing.Platform" } } diff --git a/src/Docmd.Cli/packages.lock.json b/src/Docmd.Cli/packages.lock.json index 0ee553b..208dfae 100644 --- a/src/Docmd.Cli/packages.lock.json +++ b/src/Docmd.Cli/packages.lock.json @@ -61,7 +61,7 @@ "docmd.word": { "type": "Project", "dependencies": { - "Ooxml.Md.Core": "[0.2.3, )", + "Ooxml.Md.Core": "[0.2.4, )", "PhoenixmlDb.Xslt": "[2.4.1, )" } }, diff --git a/tests/Docmd.Word.Tests/Docmd.Word.Tests.csproj b/tests/Docmd.Word.Tests/Docmd.Word.Tests.csproj index ec56fa5..1947013 100644 --- a/tests/Docmd.Word.Tests/Docmd.Word.Tests.csproj +++ b/tests/Docmd.Word.Tests/Docmd.Word.Tests.csproj @@ -7,10 +7,7 @@ false - - -