Crate facet_assert

Crate facet_assert 

Source
Expand description

§facet-assert

Coverage Status crates.io documentation MIT/Apache-2.0 licensed Discord

Pretty assertions for Facet types.

§What makes this different?

§No PartialEq required

Standard Rust assertions need PartialEq:

assert_eq!(a, b); // Requires: PartialEq + Debug

facet-assert uses structural comparison via reflection:

assert_same!(a, b); // Requires: Facet (that's it!)

This works because Facet gives us full introspection into any type’s structure.

§Structural sameness, not type identity

Two values are “same” if they have the same structure and values — even if they have different type names:

#[derive(Facet)]
struct PersonV1 { name: String, age: u32 }

#[derive(Facet)]
struct PersonV2 { name: String, age: u32 }

let a = PersonV1 { name: "Alice".into(), age: 30 };
let b = PersonV2 { name: "Alice".into(), age: 30 };

assert_same!(a, b); // Passes! Same structure, same values.

This is useful for:

  • Comparing DTOs across API versions
  • Testing serialization roundtrips (JSON → struct → JSON)
  • Comparing values parsed from different formats (YAML vs TOML vs JSON)

§Smart structural diffs

When values differ, you get a structural diff — not just line-by-line text comparison. We know which fields changed:

.host:
  - localhost
  + prod.example.com
.port:
  - 8080
  + 443
.tags[1] (only in left):
  - api

Instead of a wall of red/green like traditional diff tools.

§Render diffs in your format

Want the diff in JSON or XML so another tool can consume it? Call check_same_report to get a SameReport. When values differ you receive a DiffReport that can render the change set in Rust, JSON, or XML layouts with or without ANSI colors.

use facet_assert::{SameReport, check_same_report};

let report = match check_same_report(&c_output, &rust_output) {
    SameReport::Different(report) => report,
    SameReport::Same => return,
    SameReport::Opaque { type_name } => panic!("opaque type {type_name}"),
};

let rust_view = report.legacy_string();
let json_view = report.render_plain_json();
let xml_view = report.render_plain_xml();

For full control, use render_with_options and pass your own BuildOptions, RenderOptions, or even a custom DiffFlavor implementation.

§Opaque types fail clearly

If a type cannot be inspected (opaque), the assertion fails with a clear message rather than silently giving wrong results:

assertion `assert_same!(left, right)` failed: cannot compare opaque type `SomeOpaqueType`

§Usage

use facet::Facet;
use facet_assert::assert_same;

#[derive(Facet)]
struct Config {
    host: String,
    port: u16,
    debug: bool,
}

#[test]
fn test_config_parsing() {
    let from_json: Config = parse_json("...");
    let from_yaml: Config = parse_yaml("...");

    assert_same!(from_json, from_yaml);
}

§Macros

  • assert_same!(a, b) — panics if a and b are not structurally same
  • assert_same!(a, b, "message {}", x) — with custom message
  • debug_assert_same!(...) — only in debug builds

§Sponsors

Thanks to all individual sponsors:

GitHub Sponsors Patreon

…along with corporate sponsors:

AWS Zed Depot

…without whom this work could not exist.

§Special thanks

The facet logo was drawn by Misiasart.

§License

Licensed under either of:

at your option. Pretty assertions for Facet types.

Unlike assert_eq! which requires PartialEq, assert_same! works with any Facet type by doing structural comparison via reflection.

Macros§

assert_same
Asserts that two values are structurally the same.
assert_same_with
Asserts that two values are structurally the same with custom options.
debug_assert_same
Asserts that two values are structurally the same (debug builds only).
debug_assert_same_with
Asserts that two values are structurally the same with custom options (debug builds only).

Structs§

AnsiBackend
ANSI backend - emits ANSI escape codes for terminal colors.
BuildOptions
Options for building a layout from a diff.
DiffReport
A reusable diff plus its original inputs, allowing rendering in different output styles.
JsonFlavor
JSON-style output flavor (JSONC with comments for type names).
PlainBackend
Plain backend - no styling, just plain text.
RenderOptions
Options for rendering a layout.
RustFlavor
Rust-style output flavor.
SameOptions
Options for customizing structural comparison behavior.
XmlFlavor
XML-style output flavor.

Enums§

SameReport
Detailed comparison result that retains the computed diff.
Sameness
Result of checking if two values are structurally the same.

Traits§

ColorBackend
A backend that decides how to render semantic colors.
DiffFlavor
A diff output flavor that knows how to format values and present fields.

Functions§

check_same
Check if two Facet values are structurally the same.
check_same_report
Check if two Facet values are structurally the same, returning a detailed report.
check_same_with
Check if two Facet values are structurally the same, with custom options.
check_same_with_report
Detailed comparison with custom options.