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}