agentleFS
martincjarvismartincjarvis/development-skills/skills/dotnet-testing-assertions/SKILL.md

dotnet-testing-assertions

Skill4 starsChanged 10 months agoMITView on GitHub

Use when writing or reviewing .NET unit/integration test assertions - standardise on open-source assertion libraries, preferring AwesomeAssertions.

The file

Show its rules and text

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 13 are distinctive, and 0 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈13

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 0

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Verify the assertion library is open-source (check license)

    line 25
  2. Distinctive:

    Add AwesomeAssertions package reference to test projects

    line 26
  3. Distinctive:

    Update using statements to reference AwesomeAssertions namespace

    line 27
  4. Distinctive:

    Write fluent assertions using Should() extension methods

    line 28
  5. Distinctive:

    Use BeEquivalentTo for DTOs with exclusions for generated fields

    line 29
  6. Distinctive:

    Use BeCloseTo for time assertions to avoid brittle exact matches

    line 30
  7. Distinctive:

    Run tests to verify assertions work correctly

    line 31
  8. Distinctive:

    Prefer AwesomeAssertions (formerly FluentAssertions) for fluent assertions (open source).

    line 42
  9. Distinctive:

    Test framework selection is separate (e.g., xUnit) and may be governed elsewhere.

    line 43
  10. Distinctive:

    Do not introduce assertion libraries that are not open source.

    line 51
  11. Distinctive:

    Use precise assertions for time, GUIDs, collections, and nullable scenarios.

    line 58
  12. Distinctive:

    Avoid brittle assertions that over-specify implementation details.

    line 62
  13. Distinctive:

    Prefer structural assertions for API contract tests.

    line 63

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Overview

Standardise test assertions on open-source libraries, preferring AwesomeAssertions (the community fork of FluentAssertions) for fluent, readable assertions with better error messages. Enforce OSS license revalidation for all test dependencies.

When to Use

  • Establishing or reviewing test conventions for a new project
  • Introducing or upgrading assertion libraries in existing projects
  • Migrating from FluentAssertions to AwesomeAssertions
  • Reviewing PRs that add new test dependencies
  • Evaluating assertion library license compliance

Core Workflow

  1. Verify the assertion library is open-source (check license)
  2. Add AwesomeAssertions package reference to test projects
  3. Update using statements to reference AwesomeAssertions namespace
  4. Write fluent assertions using Should() extension methods
  5. Use BeEquivalentTo for DTOs with exclusions for generated fields
  6. Use BeCloseTo for time assertions to avoid brittle exact matches
  7. Run tests to verify assertions work correctly

Core

When to use

  • Establishing or reviewing test conventions.
  • Introducing or upgrading assertion libraries.

Defaults

  • Prefer AwesomeAssertions (formerly FluentAssertions) for fluent assertions (open source).
  • Test framework selection is separate (e.g., xUnit) and may be governed elsewhere.

Note: AwesomeAssertions is the community-maintained fork of FluentAssertions after the original project returned to open source governance. The API is largely compatible, making migration straightforward for existing FluentAssertions users.

Review rules

  • Do not introduce assertion libraries that are not open source.
  • Apply the OSS license revalidation gate (see dotnet-open-source-first-governance).

Load: examples

  • Assert equivalence for DTOs and read models.
  • Assert exception types and messages where stable.
  • Use precise assertions for time, GUIDs, collections, and nullable scenarios.

Load: advanced

  • Avoid brittle assertions that over-specify implementation details.
  • Prefer structural assertions for API contract tests.
  • For non-deterministic values (timestamps/IDs), assert invariants and ranges.

Load: enforcement

  • Reject PRs that introduce non-open-source assertion libraries.
  • Require a documented license verification for new/updated test dependencies.

Load: migration

Migration Checklist (FluentAssertions → AwesomeAssertions)

  • Update NuGet packages: Replace FluentAssertions with AwesomeAssertions
  • Update using statements: using FluentAssertions; → using AwesomeAssertions;
  • Run tests: Verify all existing tests pass (API is largely compatible)
  • Check breaking changes: Review release notes for any API differences
  • Update CI: Ensure package restore works in CI pipeline
  • Document decision: Add ADR noting the migration and rationale

Sample Assertion Diff

// Package reference
- <PackageReference Include="FluentAssertions" Version="6.12.0" />
+ <PackageReference Include="AwesomeAssertions" Version="7.0.0" />

// Using statement
- using FluentAssertions;
+ using AwesomeAssertions;

// Assertions remain the same
result.Should().NotBeNull();
result.Items.Should().HaveCount(3);
result.CreatedAt.Should().BeCloseTo(DateTime.UtcNow, TimeSpan.FromSeconds(1));

Common Assertion Patterns

// Object equivalence (ignoring specific properties)
actual.Should().BeEquivalentTo(expected, options => options
    .Excluding(x => x.Id)
    .Excluding(x => x.CreatedAt));

// Collection assertions
items.Should().ContainSingle(x => x.Name == "Test");
items.Should().BeInAscendingOrder(x => x.Priority);
items.Should().AllSatisfy(x => x.IsValid.Should().BeTrue());

// Exception assertions
action.Should().Throw<ValidationException>()
    .WithMessage("*required*");

// Async assertions
await action.Should().ThrowAsync<NotFoundException>();

xUnit vs AwesomeAssertions Comparison

xUnit AssertAwesomeAssertionsBenefit
Assert.Equal(expected, actual)actual.Should().Be(expected)Fluent, readable
Assert.NotNull(obj)obj.Should().NotBeNull()Chaining support
Assert.Contains(item, list)list.Should().Contain(item)Better error messages
Assert.Throws<T>(action)action.Should().Throw<T>()Message assertions

Red Flags - STOP

These statements indicate assertion anti-patterns:

ThoughtReality
"xUnit Assert is good enough"Fluent assertions provide better error messages and chaining
"Any assertion library will do"Ensure OSS license compliance; verify before adopting
"Assert exact timestamps"Use BeCloseTo for time; exact matches are brittle
"Assert full object equality"Use BeEquivalentTo with exclusions; ignore generated fields
"Over-specify implementation details"Assert behaviour and outcomes, not implementation
"Skip license verification"All test dependencies need OSS license revalidation

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.