Inside Axiom Assertions: A Journey into Building a .NET Testing Library

By

I wrote a .NET assertion library called Axiom Assertions as a way to truly understand how assertion libraries work under the hood. It began as a personal project driven by curiosity, then evolved into an experiment exploring deterministic output, explicit batching, analyzer-backed migration, and optional packages for specialized tests like JSON, HTTP, vectors, and AI scenarios. The result is a fluent, familiar API that doesn't try to replace existing tools, but offers fresh perspectives on test failure messages and batch processing. In this Q&A, I share the motivations, design choices, and key features of Axiom.

Why did you build your own assertion library from scratch?

The main reason was simple: I wanted to deeply understand how assertion libraries work. Reading docs for libraries like FluentAssertions or Shouldly gives you the 'what' but not the 'how'. Using them for years still leaves questions: How do they format values? How do they compare collections? How do they generate those nice failure messages? I realized the best way to learn was to build one myself. It's a great way to appreciate the complexity behind seemingly simple syntax like name.Should().NotBeNull(). I didn't intend to replace anything—just to satisfy my curiosity and see what new ideas I could explore along the way.

Inside Axiom Assertions: A Journey into Building a .NET Testing Library
Source: dev.to

What is Axiom Assertions and how do you use it?

Axiom Assertions is a fluent assertion library for .NET tests. The basic syntax is intentionally familiar to make onboarding easy:

using Axiom.Assertions;
user.Name.Should().NotBeNull();
user.Email.Should().Contain("@");

This simple API is meant to feel natural to anyone who has used other .NET assertion libraries. The real innovation lies in the extras around it: deterministic failure output, explicit batching, analyzer support for migration, and optional packages for domain-specific assertions like JSON paths or HTTP responses. You can use the core library alone, or add packages as needed.

What experimental areas did you focus on?

I concentrated on four main areas:

  • Deterministic output – Stable, predictable failure messages that remain readable in CI and consistent across runs.
  • Explicit batching – Instead of failing fast, let the user collect multiple assertion failures and see them all at once.
  • Analyzer-backed migration – Roslyn analyzers to help teams move from other libraries to Axiom (or understand its features).
  • Optional packages – Separate NuGet packages for JSON, HTTP, vectors, and retrieval tests, so you only pull in what you need.

These were driven by real pain points I've encountered: noisy, inconsistent test output; wanting to see all failures in a single test run; needing tooling to migrate large test suites; and keeping the core library lightweight.

Why did deterministic output matter to you?

Test failures are already frustrating—noisy, inconsistent, or hard-to-parse messages only make it worse. I wanted failure output that is stable, predictable, and helpful. 'Stable' means the same failure always produces the same exact text (no random formatting). 'Predictable' means you can rely on the structure. 'Helpful' means it actually tells you what broke without extra mental effort. In CI, where you can't interactively expand diff views, a clear failure message is critical. Axiom treats deterministic output as a design constraint from the start: every message is crafted to be easily diffed, compared, and understood—even at 5:10 PM on a Friday.

Inside Axiom Assertions: A Journey into Building a .NET Testing Library
Source: dev.to

What is explicit batching in assertion tests?

Explicit batching means that instead of failing on the first assertion failure (fail-fast), Axiom allows you to collect multiple failures and report them together. This is useful when you want to see all the problems in a complex object at once, rather than fixing one, re-running, discovering the next, and so on. For example, you can wrap several assertions in a batch, and if any fail, Axiom presents all failures in one consolidated message. This approach is especially valuable for large integration tests or when validating many properties of a response. It saves iteration time by giving you the full picture in one go.

How does Axiom handle optional packages?

Axiom is designed with a modular architecture. The core library (Axiom.Assertions) provides the fluent API and basic assertions (null checks, equality, collections, etc.). Specialized packages exist for common testing domains: Axiom.Assertions.Json for JSON path validation, Axiom.Assertions.Http for HTTP response checks, Axiom.Assertions.Vectors for numeric vectors, and Axiom.Assertions.Retrieval for RAG (Retrieval-Augmented Generation) tests. This way, teams only install what they actually need, keeping the dependency tree small. The packages are built on the same core, so they all benefit from deterministic output and batching.

What about AI-focused test assertions?

One of the experimental areas is providing assertions tailored for AI and machine learning workloads. For instance, comparing embeddings, checking vector similarity, or validating outputs from LLMs. The current package for this is Axiom.Assertions.Retrieval, which includes assertions for retrieval tasks like checking that a response contains expected contexts or that similarity scores meet thresholds. This is still early-stage, but the goal is to give developers clean, readable assertions for scenarios that don't fit traditional equality or collection comparisons. As AI testing becomes more common, having a dedicated assertion library can help standardize how we validate these results.

Related Articles

Recommended

Discover More

Microsoft Defender False Positive Tags Legitimate DigiCert Root Certificates as TrojanEverything About Open source package with 1 million monthly downloads stole u...Streaming Content Interfaces Face Critical Usability Crisis: Experts Warn of Layout Shift and Scroll ChaosUpgrading Fedora Silverblue to Fedora Linux 44: A Comprehensive GuideMinimizing PFAS in Your Baby's Formula: A Practical Guide