facet-assert
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 ifaandbare not structurally sameassert_same!(a, b, "message {}", x)— with custom messagedebug_assert_same!(...)— only in debug builds
Sponsors
Thanks to all individual sponsors:
...along with corporate sponsors:
...without whom this work could not exist.
Special thanks
The facet logo was drawn by Misiasart.
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.