Namespace and package
| GitHub package asset | vanilla-test 2.1.0 |
|---|---|
| Target framework | net8.0 |
| Namespace | VanillaTest |
| Runtime dependencies | None beyond the .NET base class library |
| Public types | VanillaTestSuite, TestResult, VanillaTestException, VanillaTestError |
dotnet add package vanilla-test --version 2.1.0 --source ./packagesVanillaTestSuite
A sealed, single-use, sequential suite. Its public parameterless constructor creates an empty instance with no active case.
| Member | Return | Contract |
|---|---|---|
VanillaTestSuite() | — | Creates an empty isolated suite. |
Expects(string description) | void | Starts one case. Descriptions use ordinal, case-sensitive uniqueness; an empty string is allowed. |
Pass() | void | Records the active case as passed when it has no earlier decision. |
Fail() | void | Records the active case as failed when it has no earlier decision. |
Done() | void | Closes the active case; no decision defaults to failure. |
Report() | TestResult | Rejects an active case, otherwise seals the suite and returns the same cached result thereafter. |
First-decision rule
test.Expects("first decision wins");
test.Pass();
test.Fail();
test.Done();
Console.WriteLine(test.Report().Ok); // TrueCalling Pass() or Fail() again while the same case is active is a no-op. Calling either method without an active case throws VanillaTestException.
TestResult
A sealed immutable summary. Users obtain it from Report(); its constructor is internal.
| Property | Type | Meaning |
|---|---|---|
Passed | IReadOnlyList<string> | Read-only numbered rows that passed, in original case order. |
Failed | IReadOnlyList<string> | Read-only numbered rows that failed, in original case order. |
Total | int | Completed passed plus failed cases. |
FailureCount | int | Number of failed cases. |
Ok | bool | true when FailureCount is zero, including an empty suite. |
Report | string | Plain-text summary with totals followed by failed and passed rows. |
Rendered rows preserve their original one-based number and exact description:
1) .expects first passes
2) .expects second failsPassed and Failed are backed by read-only snapshots. Casting them to a mutable collection does not make mutation valid.
VanillaTestException and VanillaTestError
VanillaTestException is a sealed InvalidOperationException with an Error property containing the stable enum value. A rejected lifecycle transition does not otherwise advance the suite.
| Error | Thrown when | Message |
|---|---|---|
SuiteAlreadyReported | Expects() follows a successful report. | this vanilla-test suite has already reported |
TestAlreadyActive | Expects() is called while a case is active. | a test is already active; call Done() first |
DuplicateDescription | An exact description is reused in one suite. | test descriptions must be unique |
NoActiveTest | Pass(), Fail(), or Done() has no active case. | there is no active test; call Expects() first |
ActiveTestNotDone | Report() is called while a case is active. | the active test is not complete; call Done() before Report() |
Expects(null) throws ArgumentNullException. Constructing VanillaTestException with an undefined enum value throws ArgumentOutOfRangeException.
Lifecycle state
| State | Allowed next calls | Rejected calls |
|---|---|---|
| Empty or between cases | Expects(), Report() | Pass(), Fail(), Done() |
| Case active | Pass(), Fail(), Done() | Expects(), Report() |
| Reported | Report() returns cached result | Expects(); decision/completion calls still have no active case |
A suite owns one mutable active case and is not a concurrent scheduler. Use a separate VanillaTestSuite instance for each independent flow.
vanilla-test.tool 2.1.0
Run the full native test suite with the standard .NET host. Install the .NET 10 global tool only for a browser test or benchmark AppBundle:
dotnet test
dotnet tool install --global vanilla-test.tool --version 2.1.0 --add-source ./packages
dotnet vanilla-test --browser [--bench] [--project PATH] [--out-dir PATH] [--page PATH]| Option | Contract |
|---|---|
--browser | Required explicit build mode. |
--bench | Builds a benchmark executable whose --browser-sample mode runs one validated workload and returns an integer status. |
--project PATH | Selects an MSTest or benchmark .csproj. Without it, the current directory must contain exactly one project. |
--out-dir PATH | AppBundle output relative to the selected project. Default: dist/vanilla-test, or dist/vanilla-test-benchmark with --bench. |
--page PATH | Compatible custom test HTML page relative to the selected project; rejected with --bench. |
--help, -h | Prints usage and exits successfully. |
--version, -V | Prints the tool version and exits successfully. |
Unknown options, missing values, missing projects/pages, ambiguous default projects, non-executable benchmark projects, unsafe nonempty output directories, metadata failures, publish failures, and incomplete AppBundles are reported as tool errors with exit code 2.
Generated browser host contract
The tool publishes a generated net10.0, browser-wasm, self-contained AppBundle. It references the selected project and MSTest.TestFramework 4.3.3. It does not invoke Microsoft.Testing.Platform.
| Supported | Deliberately outside the host |
|---|---|
Public instance [TestMethod] discovery on [TestClass] | MTP and adapter protocol emulation |
Parameterless synchronous, Task, and ValueTask methods | Parameterized and data-row expansion |
[Ignore], test initialization and cleanup | TestContext or other runner injection |
| Per-method construction and sync/async disposal | Native filters and rich adapter diagnostics |
Discovery order is ordinal by declaring type full name and then method name. The host prints PASS, FAIL, or SKIP lines, followed by total, failed, succeeded, and skipped counts. Any failure produces a nonzero result.
Benchmark mode creates a separate generated host with VanillaTestBrowserBenchmark.Run() exported to JavaScript. Each call invokes the selected executable with one --browser-sample argument. That project owns the workload, result validation, and status; the AppBundle supplies only the .NET runtime and managed export boundary.
Compatible page hooks
| Hook | Purpose |
|---|---|
data-csharp-browser-result | Receives the aggregate human-readable result. |
data-csharp-browser-score | Receives MSTest and browser-check totals. |
data-csharp-browser-checks | Receives one row per browser-side check. |
data-csharp-browser-target | Must visibly contain browser-wasm. |
data-csharp-browser-console | Receives captured .NET and adapter console output. |
data-csharp-browser-site-check | Names a visible element assertion. |
data-csharp-browser-expected | Optionally requires exact visible text. |
<script type="module" src="./browser.js"> | Loads the generated adapter beside the page. |
The tool validates the result, score, checks, target, and module hooks before publishing. The console and site-check hooks make a custom page fully observable.