[![Tests Workflow Status (main)](https://img.shields.io/github/actions/workflow/status/lostatc/xpct/test.yaml?branch=main&label=Tests&style=for-the-badge&logo=github)](https://github.com/lostatc/xpct/actions/workflows/test.yaml) [![Crates.io](https://img.shields.io/crates/v/xpct?logo=rust&style=for-the-badge)](https://crates.io/crates/xpct) [![docs.rs](https://img.shields.io/docsrs/xpct?logo=docs.rs&style=for-the-badge)](https://docs.rs/xpct) # xpct xpct is an extensible test assertion library for Rust. It's designed to be ergonomic, batteries-included, and test framework agnostic. Want to get started? [Check out the tutorial](https://docs.rs/xpct/latest/xpct/docs/tutorial/index.html). ## About xpct is extensible. In addition to allowing you to write custom matchers, it separates the logic of matchers from how they format their output, meaning you can: 1. Hook into existing formatters to write custom matchers with pretty output without having to worry about formatting. 2. Customize the formatting of existing matchers without having to reimplement their logic. This crate aims to provide many useful matchers out of the box. Check out the full [list of provided matchers](https://docs.rs/xpct/latest/xpct/docs/matcher_list/index.html). ## Docs - [API Docs](https://docs.rs/xpct/latest/xpct/index.html) - [User Docs](https://docs.rs/xpct/latest/xpct/docs/index.html) - [Tutorial](https://docs.rs/xpct/latest/xpct/docs/tutorial/index.html) - [Provided Matchers](https://docs.rs/xpct/latest/xpct/docs/matcher_list/index.html) - [Cargo Features](https://docs.rs/xpct/latest/xpct/docs/cargo_features/index.html) - [Writing Custom Matchers](https://docs.rs/xpct/latest/xpct/docs/writing_matchers/index.html) - [Writing Custom Formatters](https://docs.rs/xpct/latest/xpct/docs/writing_formatters/index.html) ## Examples A simple equality assertion, like `assert_eq`: ```rust,should_panic use xpct::{expect, equal}; expect!("disco").to(equal("Disco")); ``` stderr from failed assertion [*Image transcript*](https://raw.githubusercontent.com/lostatc/xpct/main/examples/equality.txt) Unwrapping a `Some` value to make an assertion on the wrapped value: ```rust,should_panic use xpct::{be_gt, be_some, expect}; expect!(Some(41)) .to(be_some()) .to(be_gt(57)); ``` stderr from failed assertion [*Image transcript*](https://raw.githubusercontent.com/lostatc/xpct/main/examples/chaining.txt) Making assertions about individual fields of a struct: ```rust,should_panic use xpct::{be_empty, be_in, be_true, expect, fields, have_prefix, match_fields, not, why}; struct Player { id: String, name: String, level: u32, is_superstar: bool, } let player = Player { id: String::from("REV12-62-05-JAM41"), name: String::from(""), level: 21, is_superstar: false, }; expect!(player).to(match_fields(fields!(Player { id: have_prefix("REV"), name: not(be_empty()), level: be_in(1..=20), is_superstar: why(be_true(), "only superstars allowed"), }))); ``` stderr from failed assertion [*Image transcript*](https://raw.githubusercontent.com/lostatc/xpct/main/examples/fields.txt) Making assertions about elements in a collection: ```rust,should_panic use xpct::{be_in, contain_substr, equal, expect, have_len, match_elements}; let items = vec!["apple", "pear", "banana"]; expect!(items) .to(have_len(3)) .to(match_elements([ contain_substr("ana"), equal("pear"), be_in(["mango", "orange"]), ])); ``` stderr from failed assertion [*Image transcript*](https://raw.githubusercontent.com/lostatc/xpct/main/examples/collections.txt) Showing rich diffs of data structures: ```rust,should_panic use xpct::{eq_diff, expect}; expect!(["apple", "banana"]).to(eq_diff(["banana", "orage"])); ``` stderr from failed assertion [*Image transcript*](https://raw.githubusercontent.com/lostatc/xpct/main/examples/diff.txt) ## MSRV Policy The last two stable Rust releases are supported. Older releases may be supported as well. The MSRV will only be increased when necessary—not every time there is a new Rust release. An increase in the MSRV will be accompanied by a minor semver bump if >=1.0.0 or a patch semver bump if <1.0.0. ## Semver Policy Prior to version 1.0.0, breaking changes will be accompanied by a minor version bump, and new features and bug fixes will be accompanied by a patch version bump.