Skip to content

Latest commit

Β 

History

412 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

JustDummies

🌍 Languages:
πŸ‡¬πŸ‡§ English (this file) | πŸ‡«πŸ‡· FranΓ§ais

Build ci
Quality Quality Gate Coverage
Security codeql OpenSSF Best Practices OpenSSF Scorecard
Package NuGet .NET Standard 2.0
Project License Conventional Commits

A fluent DSL for generating arbitrary yet valid test values: dummies.

🚨 The problem

Every test is full of values it does not care about.

string reference = "ORD-12345678";
int    quantity  = 3;

A reader cannot tell whether 3 matters or whether 7 would do. Every literal looks equally load-bearing, so nobody dares change one β€” and the test only ever covers that one case. A defect needing a different shape of input is a defect this test can never find.

βœ… The solution

Say what the value must satisfy, and let the library draw one that does:

string reference = Any.String().StartingWith("ORD-").WithLength(12).Generate();
int    quantity  = Any.Int32().Between(1, 100).Generate();
Guid   id        = Any.Guid().NonEmpty().Generate();

The test now states its assumptions. Everything else varies between runs, which is what makes it find things.

An Any.* call returns a generator β€” an immutable recipe β€” and .Generate() draws a value from it. A value object with a stricter contract is built by transforming a constrained primitive through its real factory:

OrderReference orderRef = Any.String()
    .StartingWith("ORD-")
    .WithLength(12)
    .As(OrderReference.Create)
    .Generate();

The one rule that matters: a constraint states an invariant of the domain, never what the test asserts. Contradictory constraints fail fast, with a message naming both sides.

πŸ“¦ Install

dotnet add package JustDummies

No runtime dependency, and the 29 analyzer rules come bundled inside β€” they start working on your next build.

πŸ” Reproducible by construction

Random values in tests are only acceptable if a failure can be replayed. Wrap the test body:

Any.Reproducibly(() => {
    decimal orderTotal = Any.Decimal().Between(0m, 10_000m).WithScale(2).Generate();

    Assert.InRange(Shipping.FeeFor(orderTotal), 0m, 4.90m);
});

When it goes red β€” and only then β€” the seed that produced the run is reported:

[JustDummies] These arbitrary values were seeded with 1743029518. Reproduce this run with Any.Reproducibly(1743029518, ...).

Copy that number in front of the body. Same test, one argument more, and the exact run comes back β€” value for value:

Any.Reproducibly(1743029518, () => {
    // the same body as above; only the seed was added
});

Fix the defect, then delete the seed so the test varies again.

With xUnit v3, [Reproducible] replaces the wrapping entirely β€” see the adapter. From 1.0.0-preview.1 a seed replays across every patch and minor of a major version, enforced by a golden master (ADR-0049).

πŸ›  Scaffold one for your own type

Writing an IAny<T> by hand for each of your domain types is the tedious part. dum writes the first draft:

dotnet tool install --global JustDummies.Cli
dum generate Order
  reference  OrderReference  Any.String().NonEmpty().As(OrderReference.Create)  factory, guard
  customer   Customer        β€”                                                  TODO
  quantity   int             Any.Int32().Positive()                             guard

βœ“ AnyOrder.cs β€” 5 of 6 parameters inferred, 1 TODO.

It reads your compilation, tightens what the constructor's own guard clauses tell it (quantity <= 0 β†’ .Positive()), and emits ordinary code you then own. What it could not infer it leaves as an identifier that does not exist β€” so your build names the gap, at the line, instead of a plausible value being drawn behind your back.

β†’ JustDummies.Cli

πŸ“š Documentation

β†’ Start with the ten-minute guide

Documentation index everything, organised, in English and French
Core concepts recipe versus value, and the golden rule
Generator reference every Any.* factory and its constraints
Reproducibility seeds, scopes and replay
Composition dummies for your own types
Analyzer rules one page per diagnostic
Design principles what it refuses on purpose, and why

🧩 Packages

Package What it is
JustDummies the library, with its 29 rules bundled in
JustDummies.Xunit the xUnit v3 adapter: [Reproducible]
JustDummies.DiagnosticCatalog the JD001–JD029 rules as compile-checked constants
JustDummies.Cli dum, the scaffolder β€” a global tool, never a project reference

The three libraries target netstandard2.0; JustDummies additionally carries a net8.0 asset with the modern generators (DateOnly, TimeOnly, Int128, UInt128, Half). The supported .NET Framework floor is 4.7.2 (ADR-0007). dum is a tool rather than a library: it targets net8.0 and rolls forward, whatever the project it analyzes targets.

Preview. The public surface is declared in PublicAPI.Unshipped.txt: nothing about it is promised yet, and a stable release is what will freeze it. The seed contract is the exception β€” see above. Which versions are on nuget.org is not repeated here, because a copy of that goes stale the day after a release: read the package listing.

🀝 Contributing

Issues and pull requests are welcome. Start with CONTRIBUTING.md for the commit conventions and the test-bed rules, and SECURITY.md to report a vulnerability.

dotnet build JustDummies.sln -c Release
dotnet test  JustDummies.sln -c Release

The repository targets the .NET 10 SDK (pinned in global.json). Maintainer material β€” architecture decisions, workflows, specifications β€” is under doc/handwritten/for-maintainers/.

πŸ“œ History and licence

This repository was extracted from Reefact/first-class-errors on 2026-07-31 with git filter-repo, preserving authors, dates and commit messages. Commit hashes therefore differ from the source repository, and issue/PR numbers in commit messages dated before the extraction refer to Reefact/first-class-errors. The full record is in doc/handwritten/for-maintainers/migration/; the decision is ADR-0044.

Licensed under Apache 2.0.

About

Generate test values that satisfy your constraints, so your tests can focus on what matters. Just dummies. Seriously powerful ones.

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages