Repository navigation
The suite on AnyUnit, and a browser-wasm leg - #66
Conversation
…erts Every assertion call site is unchanged. AnyUnit supplies the classic asserts as extension methods on IAssert, and C# will not dispatch an extension method when an argument is dynamic (CS1973) - which is most of this suite, since what it tests is dynamic. Support/Helper.cs shadows the injected IAssert with ClassicAssert, whose ordinary instance methods forward to them; an instance call with dynamic arguments binds at run time, as it did against NUnit's static Assert. 222 tests, same as NUnit ran; the only failures are the wall-clock *Timed benchmarks that fail under NUnit too (#63 moves them to BenchmarkDotNet). Needs AnyUnit 1.3.0, unreleased: built here against a local feed. net47 and the NuGet.config cleanup are not done yet. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg
NUnit, NUnit3TestAdapter and Microsoft.NET.Test.Sdk give way to AnyUnit 1.3.0 on Microsoft.Testing.Platform. Every assertion call site is unchanged: AnyUnit supplies the classic asserts as extension methods on IAssert, and C# will not dispatch an extension method when an argument is dynamic (CS1973) - which is most of this suite, since what it tests is dynamic. Support/Helper.cs shadows the injected IAssert with ClassicAssert, whose ordinary instance methods forward to them; an instance call with dynamic arguments binds at run time, as it did against NUnit's static Assert. That the usings are now `using AnyUnit;` rather than a qualified AnyUnit.AssertionException is thanks to AnyUnit 1.3.0 giving its built-in style its own namespace - a change this port asked for. The wasm project links the same sources, less two files, for their dependencies rather than anything about proxies: Linq.cs needs IronPython and SingleMethodInvoke.cs needs Moq, whose Castle DynamicProxy is a second run-time emitter. 190 tests on net8.0 and net10.0, 196 on net47, 101 on browser-wasm. Closes #63. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Two critical issues and one moderate AOT coverage gap remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review effort: Lite
Findings: 2
Open (2)
What changed in this PR
Migrates the test suite from NUnit to AnyUnit/Microsoft.Testing.Platform and adds browser-WASM execution through Bun.
Changes:
- Replaces NUnit dependencies with AnyUnit and classic assertion compatibility.
- Adds a linked browser-WASM test project and Bun runner.
- Updates global test configuration and CI.
| File | Summary |
|---|---|
Tests/UnitTestImpromptuInterface/UnitTestImpromptuInterface.csproj |
Configures AnyUnit test execution. |
Tests/UnitTestImpromptuInterface/Support/Helper.cs |
Adds classic assertion forwarding. Critical (3 votes): the shared helper remains compiled by the NUnit-based Clay project, which lacks AnyUnit references and will fail to resolve these types. |
Tests/UnitTestImpromptuInterface/Support/FixtureSetup.cs |
Updates test-runner imports. |
Tests/UnitTestImpromptuInterface/SingleMethodInvoke.cs |
Updates test framework imports. |
Tests/UnitTestImpromptuInterface/Savable.cs |
Updates test framework imports. |
Tests/UnitTestImpromptuInterface/PrivateTest.cs |
Updates test framework imports. |
Tests/UnitTestImpromptuInterface/MimicTest.cs |
Updates imports and assertion-helper inheritance. |
Tests/UnitTestImpromptuInterface/Linq.cs |
Updates test framework imports. |
Tests/UnitTestImpromptuInterface/ImpromptuDynamic.cs |
Updates AnyUnit imports. |
Tests/UnitTestImpromptuInterface/Generics.cs |
Updates test framework imports. |
Tests/UnitTestImpromptuInterface/Collectable.cs |
Updates test framework imports. |
Tests/UnitTestImpromptuInterface/Basic.cs |
Updates AnyUnit imports. |
Tests/UnitTestImpromptuInterface.Wasm/wwwroot/runtests.mjs |
Boots and runs the WASM test assembly. |
Tests/UnitTestImpromptuInterface.Wasm/UnitTestImpromptuInterface.Wasm.csproj |
Defines the browser-WASM test project. |
global.json |
Selects Microsoft.Testing.Platform. |
.github/workflows/build.yml |
Adds the browser-WASM CI job. Critical (3 votes): the script copy path is incorrect for the configured working directory. Moderate (1 vote): the job does not publish or exercise AOT output despite claiming AOT coverage. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
…ready in the output Two real ones: - Microsoft.CSharp is inbox on net10.0-browser, and that is this project's only target framework, so referencing it is NU1510 — fatal once CI=true makes warnings errors, which is why it passed locally and failed in CI. - The workflow copied runtests.mjs from a path that does not exist from the working directory (three .. segments land in bin/wwwroot). The Blazor SDK already copies the project's wwwroot into the output, harness included, so the copy goes away rather than gets corrected. Verified with CI=true: builds clean, 101 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg
|
Both review points were real; fixed in the commit above. The wasm job's build failure was The Re-verified with On |
…the SDK I claimed the Blazor SDK copies wwwroot into the build output and removed the workflow's copy on that basis. It does not - only a publish does - and the file I saw in the output was one I had copied by hand while testing, so the check confirmed nothing. CI was right: "Module not found runtests.mjs". A None item with CopyToOutputDirectory does it, as the same harness in FSharp.Interop.Dlr's Tests.Wasm does, so the workflow stays a bare `bun runtests.mjs`. Verified from a clean bin/obj under CI=true: copied, 101 tests pass. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg
|
Correction to my previous comment: I was wrong that the Blazor SDK copies The harness is now copied by a Verified from a deleted The |
Savable.cs calls BuildProxy.SaveableProxyMaker("II_Generated"), so running
the tests from the repository root writes II_Generated.dll there, and a
`git add -A` took it along with the port commit. Second time today the
same way (see #65); the .gitignore entry stops the third.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg
…coverage Each leg now runs the test executable directly rather than through `dotnet test` - AnyUnit's MTP adapter makes it an exe, and that is what takes --report-anyunit-json - and uploads its results. A summary job renders every platform's results into one table in the run summary through anyunit-report, AnyUnit's own converter, and uploads an HTML report: 190 tests across 2 platforms - 291 results | Platform | ✅ | ❌ |⚠️ | ⊘ | ∅ | Not run | | net10-browser-wasm | 89 | 0 | 0 | 0 | 12 | 89 | | net8-osx-arm64 | 175 | 0 | 0 | 0 | 15 | 0 | The wasm row's "not run" is the two files that project leaves out, for IronPython and Moq. Coverage runs through coverlet's MTP extension, so the test exe instruments itself with no external collector, restricted to the library because coverlet instruments anything it can find sources for. Currently 84.0% of lines and 69.5% of branches. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg

Closes #63 (steps 3 and 4; steps 1, 2 and 5 landed in #64).
NUnit+NUnit3TestAdapter+Microsoft.NET.Test.Sdkgive way to AnyUnit 1.3.0 on Microsoft.Testing.Platform, and a browser-wasm project runs the same sources under bun.No assertion was rewritten
All 460 assertion call sites are untouched. AnyUnit supplies the classic asserts as extension methods on
IAssert, and C# will not dispatch an extension method when an argument isdynamic:That is 420 of the errors you get from a naive port, and it is unavoidable here, since what this suite tests is dynamic. NUnit's static
Assert.AreEqualnever hit it — a static call with dynamic arguments is simply bound at run time.Support/Helper.csgrowsClassicAssert: ordinary instance methods forwarding to AnyUnit's extensions, withHelpershadowing its inheritedAssertproperty with one. An instance call with dynamic arguments binds at run time exactly as the NUnit static call did. The engine assigns throughIAssertionHelper, which still binds to the base's property, so the runner is unaffected. It also restores the exact-arity overloads that method-group conversions need (new Action(Assert.Fail)).Sixty lines in one file, against rewriting 460 assertions or reshaping AnyUnit's public interface for a problem peculiar to this suite. Reported upstream as jbtule/AnyUnit#62, which is where the classic asserts came from.
The usings are plain
using AnyUnit;rather than a fully-qualifiedAnyUnit.AssertionExceptionbecause AnyUnit 1.3.0 moved its built-in style to its own namespace — jbtule/AnyUnit#66, a change this port asked for.The wasm leg
Tests/UnitTestImpromptuInterface.Wasmlinks the same sources, less two files — for their dependencies rather than anything about proxies:Linq.csneeds IronPython, a desktop-only hosting stackSingleMethodInvoke.csneeds Moq, whose Castle DynamicProxy is a second run-time emitterThis matters more than coverage: this library emits proxy types at run time, and whether that works on wasm was a bug report (#43) rather than a known boundary. It does work, interpreted and AOT-published alike, and this leg keeps it that way. CI runs it in its own ubuntu job, since it needs the
wasm-toolsworkload and a JS runtime.Still open afterwards
#62 (removing the Dynamitey package dependency) is untouched by this.
🤖 Generated with Claude Code
https://claude.ai/code/session_016mwfq4oeZW8SiD4HjTHYdg