clearcheck/matchers/mod.rs
1//! Matchers provide the granular tools for carrying out the assertions.
2//! They examine the data and verify that the data conforms to specific criteria.
3//!
4//! Let's take an example of a collection matcher.
5//!
6//! ```
7//! use clearcheck::matchers::collection::membership::contain_all;
8//! use clearcheck::matchers::Matcher;
9//!
10//! let collection = vec!["clearcheck", "testify", "assert4j", "xunit"];
11//! let all_to_be_contained = vec!["testify", "assert4j", "xunit"];
12//!
13//! let matcher = contain_all(all_to_be_contained);
14//! assert!(matcher.test(&collection).passed());
15//! ```
16
17pub mod bool;
18pub mod char;
19pub mod collection;
20pub mod compose;
21#[cfg(feature = "date")]
22pub mod date;
23pub mod equal;
24#[cfg(feature = "file")]
25pub mod file;
26#[cfg(feature = "num")]
27pub mod float;
28#[cfg(feature = "num")]
29pub mod int;
30pub mod map;
31pub mod option;
32pub mod ordered;
33pub mod range;
34pub mod result;
35pub mod string;
36
37/// Should provides a convenient way to express positive assertions within tests, indicating that a value should meet a certain condition.
38pub trait Should<T> {
39 /// - Takes a matcher as input and performs an assertion against the value itself.
40 /// - Panics if the assertion fails, indicating that the value did not match the matcher's expectations.
41 fn should(&self, matcher: &dyn Matcher<T>);
42}
43
44/// ShouldNot provides a convenient way to express negative assertions within tests, indicating that a value should not meet a certain condition.
45pub trait ShouldNot<T> {
46 /// - Takes a matcher as input and performs an inverted assertion against the value itself.
47 /// - Inverts the result of the matcher's test method, ensuring the value does not match.
48 /// - Panics if the inverted assertion fails, indicating that the value unexpectedly matched the matcher.
49 fn should_not(&self, matcher: &dyn Matcher<T>);
50}
51
52impl<T> Should<T> for T {
53 fn should(&self, matcher: &dyn Matcher<T>) {
54 let matcher_result = matcher.test(self);
55 if !matcher_result.passed {
56 panic!("assertion failed: {}", matcher_result.failure_message);
57 }
58 }
59}
60
61impl<T> ShouldNot<T> for T {
62 fn should_not(&self, matcher: &dyn Matcher<T>) {
63 let matcher_result = matcher.test(self);
64 let passed = !matcher_result.passed;
65 if !passed {
66 panic!(
67 "assertion failed: {}",
68 matcher_result.inverted_failure_message
69 );
70 }
71 }
72}
73
74/// Matcher defines the core functionality of matchers. All the matchers implement `Matcher<T>` trait.
75pub trait Matcher<T> {
76 fn test(&self, value: &T) -> MatcherResult;
77}
78
79/// BoxWrap provides a `boxed` method to wrap a Matcher into Box object.
80///
81/// It is used to compose matchers in [`crate::matchers::compose::Matchers`].
82///
83/// BoxWrap is implemented for any `T: Matcher<M>`.
84pub trait BoxWrap<W> {
85 fn boxed(self) -> Box<dyn Matcher<W>>;
86}
87
88impl<M, T: Matcher<M> + 'static> BoxWrap<M> for T {
89 fn boxed(self) -> Box<dyn Matcher<M>> {
90 Box::new(self)
91 }
92}
93
94/// MatcherResult defines the result of a matcher execution.
95pub struct MatcherResult {
96 passed: bool,
97 failure_message: String,
98 inverted_failure_message: String,
99}
100
101impl MatcherResult {
102 /// Creates a new instance of MatcherResult using failure_message and inverted_failure_message of type &'static str.
103 pub fn new(
104 passed: bool,
105 failure_message: &'static str,
106 inverted_failure_message: &'static str,
107 ) -> Self {
108 MatcherResult::formatted(
109 passed,
110 failure_message.to_string(),
111 inverted_failure_message.to_string(),
112 )
113 }
114
115 /// Creates a new instance of MatcherResult using failure_message and inverted_failure_message of type String.
116 pub fn formatted(
117 passed: bool,
118 failure_message: String,
119 inverted_failure_message: String,
120 ) -> Self {
121 MatcherResult {
122 passed,
123 failure_message,
124 inverted_failure_message,
125 }
126 }
127
128 /// Returns true if the result of a matcher execution was successful, false otherwise.
129 pub fn passed(&self) -> bool {
130 self.passed
131 }
132}