Test helpers for Rust
Rust has powerful and easy-to-use unit-testing mechanisms, but there are some missing elements, particularly around the use of floating-point values - f32 and f64 - that are provided by this crate for asserting approximate equality, as in:
use test_helpers::{
assert_scalar_eq_approx,
assert_vector_eq_approx,
margin,
multiplier,
};
#[test]
fn example_test_of_scalar_evaluation() {
let expected = 3.0;
let actual = 3.0001;
assert_scalar_eq_approx!(expected, actual, margin(0.0001));
}
#[test]
fn example_test_of_vector_evaluation() {
let expected = &[ 3.0, -40404.0, 1.23456 ];
let actual = Vec::from([ 3.0, -40410.0, 1.234567 ]);
assert_vector_eq_approx!(expected, actual, multiplier(0.00015));
}Reference in Cargo.toml in the usual way:
test_help-rs = { version = "0.2.1" }The following constants are defined in constants:
DEFAULT_MARGIN— default absolute margin (0.0001, i.e. 1e-4) used by the stock two-argument assertion macros when no custom evaluator is supplied;DEFAULT_MULTIPLIER— default relative multiplier (0.000001, i.e. 1e-6) used together withDEFAULT_MARGINby the stockzero_margin_or_multiplier()evaluator path;
The following enumerations are defined:
ComparisonResult— outcome of comparing two scalarf64values:ExactlyEqual— the values are identical (including matching infinities and, when the"nan-equality"feature is enabled, bothNaN);ApproximatelyEqual— the values differ but are within the margin or multiplier tolerance of the evaluator;Unequal— the values are not equal under the evaluator;
VectorComparisonResult— outcome of comparing two vectors off64values:ExactlyEqual— same length and every element pair is exactly equal;ApproximatelyEqual— same length and every element pair is equal within the evaluator tolerance;DifferentLengths { expected_length, actual_length }— the vectors have different lengths;UnequalElements { index_of_first_unequal_element, expected_value_of_first_unequal_element, actual_value_of_first_unequal_element }— same length but at least one element pair is unequal under the evaluator;
The following optional features are defined in Cargo.toml:
-
Crate-specific features:
full— enables all crate-specific features; use a nightly toolchain because it includesnightly-constants;nan-equality— allows twof64::NANvalues to be treated as equal for stock comparisons (does not affect customApproximateEqualityEvaluatorimplementations);
-
nightly-constants— enables unit tests for additionalstd::f64constants that require the unstablemore_float_constantsfeature; build and test with pinned nightly-2026-09-10 via./scripts/test-nightly-constants(this feature is for crate development only and is not required by downstream consumers); -
General features:
null-feature— a feature that has no effect (and, thus, is useful for simplifying driver scripts);
The following functions are defined:
margin() -> impl ApproximateEqualityEvaluator— creates a margin-based evaluator;multiplier() -> impl ApproximateEqualityEvaluator— creates a multiplier-based evaluator;zero_margin_or_multiplier() -> impl ApproximateEqualityEvaluator— applies a margin when either comparand is zero and a multiplier otherwise;evaluate_scalar_eq_approx()— compares scalar values that are logicallyf64without asserting;evaluate_vector_eq_approx()— compares vectors of values that are logicallyf64without asserting;
The following macros are defined (re-exported at the crate root via test_helpers):
assert_scalar_eq_approx!(expected, actual)— asserts approximate equality using the stockzero_margin_or_multiplier()evaluator (DEFAULT_MULTIPLIER/DEFAULT_MARGIN);assert_scalar_eq_approx!(expected, actual, evaluator)— asserts approximate equality using a customApproximateEqualityEvaluator;assert_scalar_ne_approx!(expected, actual)— asserts approximate inequality using the stock evaluator;assert_scalar_ne_approx!(expected, actual, evaluator)— asserts approximate inequality using a custom evaluator;assert_vector_eq_approx!(expected, actual)— asserts approximate equality of two vectors (slices, arrays, orVec) using the stock evaluator;assert_vector_eq_approx!(expected, actual, evaluator)— asserts approximate vector equality using a custom evaluator;assert_vector_ne_approx!(expected, actual)— asserts approximate vector inequality using the stock evaluator;assert_vector_ne_approx!(expected, actual, evaluator)— asserts approximate vector inequality using a custom evaluator;
No public structures are defined at this time.
The following traits are defined:
ApproximateEqualityEvaluator— prescribes the non-mutatingevaluate()method, allowing custom evaluators to be used with the assertion macros;TestableAsF64— prescribes the non-mutatingtestable_as_f64() -> f64method, with an implementation for any type that implements theToF64trait defined in the base-traits crate;
Example programs are provided in the examples directory:
- examples/scalars.rs — scalar approximate equality and inequality:
cargo run --example scalars- examples/strings.rs — string-view equality and inequality using a custom
AsStrimplementation:
cargo run --example strings- examples/vectors.rs — vector approximate equality and inequality (slice and
Vec):
cargo run --example vectorsscalars exercises assert_scalar_eq_approx!() and
assert_scalar_ne_approx!() with margin- and multiplier-based evaluators.
strings demonstrates custom AsStr implementations. vectors includes
the README introduction example and similar pass/fail demonstrations for
vector assertions.
Defect reports, feature requests, and pull requests are welcome on https://github.com/synesissoftware/test_help-rs.
The declared Minimum Supported Rust Version (MSRV) for test_help-rs is 1.74.
This MSRV guarantee applies to the library crate itself, its runtime dependencies ([dependencies]), and its build dependencies ([build-dependencies]). Downstream consumers compiling this crate as a dependency are guaranteed that it builds cleanly on the declared MSRV toolchain.
Development dependencies ([dev-dependencies], such as benchmarking frameworks like criterion) may require newer Rust toolchains for local development or performance testing. These dev-dependencies are never fetched or compiled by downstream consumers and do not affect the library's MSRV guarantee.
Libraries upon which test_help-rs depends:
- base-traits —
ToF64trait used byTestableAsF64;
The committed Cargo.lock is retained for reproducible development and CI builds; locked Cargo commands are used throughout the workflow.
Libraries used only when building test_help-rs (not required by downstream consumers):
- bt-rs —
rustc::compiler_version()in build.rs to detect Rust 1.94+ and set therustc_1_94_or_newercfg for unit tests of stablestd::f64::constsadded in that release;
None currently.
Projects that depend on test_help-rs (typically as a dev-dependency for unit tests):
- shwild.Rust defines functionality for matching strings against SHell-compatible WILDcard patterns, including matching assertion macros that are useful in unit-testing;
test_help-rs is released under the 3-clause BSD license. See LICENSE for details.