UniTest is a .NET testing framework that generates and verifies execution paths from model states and available actions.
Define the actions and expected results for each state instead of listing every path manually. UniTest explores subsequent states using the execution history.
- State-based path generation: create the Labs available in the current Model and explore subsequent states.
- AAA verification: separate preparation, actual behavior, and verification with Arrange, Act, and Assert.
- Independent state composition: combine tests across state axes with TestCase, Merge, and Extend.
- Failure reproduction: replay saved Lab ID paths or investigate failures using detached debug nodes.
- Continuous execution and JSON reports: inspect long execution paths and save independent diagnostic snapshots after execution.
The library targets netstandard2.1 and has no external runtime package dependencies. Building, testing, and running samples in this repository requires the .NET 10 SDK. All projects use C# 9.
Keep the validated BlackThunder.UniTest.0.4.0.nupkg in the consuming repository's packages directory. Add the following root NuGet.config, then add the package. Packages are distributed through repository-local files and are not published to a public NuGet feed.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add key="local" value="packages" />
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>dotnet add package BlackThunder.UniTest --version "[0.4.0]"The package ID, namespace, and DLL name are BlackThunder.UniTest, BlackThunder.UniTest, and BlackThunder.UniTest.dll, respectively. Hosts that load DLLs directly use the DLL under lib/netstandard2.1.
Run the following code in a console project that references the package. It creates a real Counter and a Model with its expected value, then verifies the Increment path to depth 3.
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using BlackThunder.UniTest;
namespace Example.CounterTests
{
public class Counter
{
public int Value { get; private set; }
public void Increment() => Value++;
}
public class CounterModel : Model
{
public Counter Counter => (Counter)Subject;
public int ExpectedValue;
public CounterModel() => Subject = new Counter();
}
public class CounterProject : CompactProject<CounterModel>
{
public override IEnumerable<CompactLab<CounterModel>> CreateCompactLabs(CounterModel model)
{
yield return new CompactLab<CounterModel>("Increment",
arranger: current => current.ExpectedValue++,
actor: current => current.Counter.Increment(),
asserter: current =>
{
if (current.Counter.Value != current.ExpectedValue)
throw new InvalidOperationException("Counter state mismatched.");
});
}
}
public static class Program
{
public static async Task Main()
{
var root = await new CounterProject().Execute(3);
Console.WriteLine(root.GetReport().ToJson());
}
}
}For runnable examples with multiple actions and combined states, see the sample guide.
dotnet run --project samples/BlackThunder.UniTest.Samples.csproj
dotnet run --project samples/BlackThunder.UniTest.Samples.csproj -- singleWithout arguments, the app opens the sample> prompt. With a command argument, it runs once and exits. Reports are saved in SampleOutput beside the sample executable.
Model: holds the actual subject, expected state, and execution history.Project<TModel>andCompactProject<TModel>: generate state-specific Labs and execute paths.Lab<TModel>,CompactLab<TModel>, andCompositeLab<TModel>: define and compose preparation, actions, and assertions.TestCase,Merge, andExtend: combine conditions and actions across state axes.ExecuteandExecuteContinuously: execute full paths, ID paths, or continuous paths.GetReport,GetFailedReports, andExportJson: inspect execution results and save JSON.
- Testing methodology: state-action tables and test scope
- Overview: purpose, core structure, and representative flow
- Implementation: component responsibilities, execution, and shutdown
- Extensions: failure stopping, replay, and continuous execution
- Usage: API selection and single-state/multi-state tutorials
- Test authoring workflow: test authoring, project setup, CLI execution, and result recording
- Contributing: shared conventions, development environment, and package verification
See test structure and results for the scope of ordinary unit tests and UniTest-based self-tests, along with the overall execution results.
dotnet restore BlackThunder.UniTest.sln
dotnet build BlackThunder.UniTest.sln --configuration Release --no-restore -m:1
dotnet test BlackThunder.UniTest.sln --configuration Release --no-build --no-restore -m:1
pwsh -File .github/scripts/verify-samples.ps1CI runs the same build, full tests, and sample CLI checks on Windows and Ubuntu. TRX results are retained for seven days; packages are not published.
Distributed under the MIT license. See LICENSE.md.