rxpect/lib.rs
1//! # RXpect
2//! A Rust library for fluently building expectations in tests.
3//!
4//! ### What does it mean?
5//!
6//! Either _Rust Expect_ or _Raniz Expect_, pick whichever you like best.
7//!
8//! ## How do I use this thing?
9//!
10//! It's pretty simple actually,
11//! wrap whatever you're having expectations on with [expect] and then call the different
12//! extension methods.
13//!
14//! ```rust
15//! use rxpect::expect;
16//! use rxpect::expectations::EqualityExpectations;
17//!
18//! // Expect 1 plus 1 to equal 2
19//! expect(1 + 1).to_equal(2);
20//! ```
21//!
22//! ```shell
23//! running 1 test
24//! test tests::that_one_plus_one_equals_two ... ok
25//!
26//! test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
27//! ```
28//!
29//! Failures are neatly reported:
30//!
31//! ```rust,no_run
32//! use rxpect::expect;
33//! use rxpect::expectations::EqualityExpectations;
34//!
35//! // Expect 1 plus 1 to equal 3
36//! expect(1 + 1).to_equal(3);
37//! ```
38//!
39//! ```shell
40//! thread 'main' panicked at 'Expectation failed (expected == actual)
41//! expected: `3`
42//! actual: `2`'
43//! ```
44mod expectation_list;
45pub mod expectations;
46mod projection;
47mod root;
48
49pub use projection::ExpectProjection;
50pub use root::RootExpectations;
51use std::fmt::Debug;
52
53#[doc = include_str!("../README.md")]
54#[cfg(doctest)]
55pub struct ReadmeDoctests;
56
57#[derive(Clone, Debug)]
58pub enum CheckResult {
59 Pass,
60 Fail(String),
61}
62
63/// An expectation on a value
64pub trait Expectation<T: Debug> {
65 /// Check this expectation
66 /// Returns CheckResult::Pass if the expectation pass
67 /// and CheckResult::Fail with a descriptive message if it didn't
68 fn check(&self, value: &T) -> CheckResult;
69}
70
71/// Trait to enable fluent building of expectations
72pub trait ExpectationBuilder<'e, T: Debug> {
73 /// Expect the value to pass an expectation
74 /// This is intended to be used in extension methods to add expectations to the builder
75 fn to_pass(self, expectation: impl Expectation<T> + 'e) -> Self;
76}
77
78/// Create expectations for a value.
79/// Used as an entrypoint for fluently building expectations
80/// ```
81/// use rxpect::expect;
82/// use rxpect::expectations::EqualityExpectations;
83///
84/// expect(1).to_equal(1);
85/// ```
86pub fn expect<'e, T: Debug>(value: T) -> RootExpectations<'e, T> {
87 RootExpectations::new(value)
88}
89
90#[cfg(test)]
91pub(crate) mod tests {
92 use crate::{CheckResult, Expectation};
93 use std::fmt::Debug;
94 use std::rc::Rc;
95 use std::sync::Mutex;
96
97 pub(crate) struct TestExpectation {
98 pub asserted: Rc<Mutex<bool>>,
99 result: CheckResult,
100 }
101
102 impl TestExpectation {
103 pub fn new(result: CheckResult) -> (TestExpectation, Rc<Mutex<bool>>) {
104 let asserted = Rc::new(Mutex::new(false));
105 (
106 TestExpectation {
107 asserted: asserted.clone(),
108 result,
109 },
110 asserted,
111 )
112 }
113 }
114
115 impl<T: Debug> Expectation<T> for TestExpectation {
116 fn check(&self, _: &T) -> CheckResult {
117 let mut asserted = self.asserted.lock().unwrap();
118 *asserted = true;
119 self.result.clone()
120 }
121 }
122}