easy_assert/custom_assertions.rs
1//! ## Usage
2//!
3//! ``` rust
4//! use easy_assert::{actual_with, expected_with};
5//! use easy_assert::custom_assertions::CustomAssert;
6//!
7//! struct TestStruct {
8//! a: i32,
9//! b: String,
10//! c: bool,
11//! }
12//!
13//! fn custom_match(val1: &TestStruct, val2: &TestStruct) -> bool {
14//! val1.a == val2.a && val1.b.eq(&val2.b) && val1.c == val2.c
15//! }
16//!
17//! fn custom_description(value: &TestStruct) -> String {
18//! format!(
19//! "TestStruct:\n a = {}\n, b = {}\n, c = {}",
20//! value.a, value.b, value.c
21//! )
22//! }
23//!
24//! #[test]
25//! fn my_test() {
26//! let val1 = TestStruct {
27//! a: 1,
28//! b: String::from("a"),
29//! c: false,
30//! };
31//! let val2 = TestStruct {
32//! a: 1,
33//! b: String::from("a"),
34//! c: false,
35//! };
36//!
37//! CustomAssert::assert_that(actual_with(val1, custom_description))
38//! .matches_by(custom_match)
39//! .to(expected_with(val2, custom_description));
40//! }
41//! ```
42
43use crate::assertions::Matches;
44use crate::{test_failed, Actual, Expected};
45
46pub struct CustomAssert<T> {
47 actual: Actual<T>,
48}
49
50impl<T> CustomAssert<T>
51where
52 T: 'static,
53{
54 pub fn assert_that(actual: Actual<T>) -> CustomAssert<T> {
55 CustomAssert { actual }
56 }
57
58 pub fn matches_by(self, matcher: fn(&T, &T) -> bool) -> Box<dyn Matches<T>> {
59 Box::new(CustomMatcher {
60 actual: self.actual,
61 matcher,
62 })
63 }
64}
65
66struct CustomMatcher<T> {
67 actual: Actual<T>,
68 matcher: fn(&T, &T) -> bool,
69}
70
71impl<T> Matches<T> for CustomMatcher<T> {
72 fn to(&self, expected: Expected<T>) {
73 let success = (self.matcher)(&self.actual.value, &expected.value);
74 if !success {
75 let error_message = format!(
76 "\n Actual: {} \n not matches with \n Expected: {} \n",
77 self.actual, expected
78 );
79 test_failed(&error_message);
80 }
81 }
82}