chicago_tdd_tools/core/macros/assert/
result.rs

1//! Result Assertion Macros
2//!
3//! Assertions for testing `Result` types with enhanced error messages.
4
5/// Assert that a result is successful with detailed error message
6///
7/// Provides better error messages than standard `assert!` when testing Results.
8///
9/// # Example
10///
11/// ```rust
12/// use chicago_tdd_tools::assert_ok;
13///
14/// let result: Result<u32, String> = Ok(42);
15/// assert_ok!(result);
16///
17/// // With custom message
18/// let result2: Result<u32, String> = Ok(42);
19/// assert_ok!(result2, "Expected successful operation");
20/// ```
21#[macro_export]
22macro_rules! assert_ok {
23    ($result:expr) => {
24        match $result {
25            Ok(_) => {}
26            Err(e) => panic!("Expected Ok, but got Err: {:?}", e),
27        }
28    };
29    ($result:expr, $msg:expr) => {
30        match $result {
31            Ok(_) => {}
32            Err(e) => panic!("{}: Expected Ok, but got Err: {:?}", $msg, e),
33        }
34    };
35}
36
37/// Assert that a result is an error with detailed message
38///
39/// Provides better error messages when testing error cases.
40///
41/// # Example
42///
43/// ```rust
44/// use chicago_tdd_tools::assert_err;
45///
46/// let result: Result<u32, String> = Err("error".to_string());
47/// assert_err!(result);
48///
49/// // With custom message
50/// let result2: Result<u32, String> = Err("error".to_string());
51/// assert_err!(result2, "Expected error case");
52/// ```
53#[macro_export]
54macro_rules! assert_err {
55    ($result:expr) => {
56        match $result {
57            Ok(v) => panic!("Expected Err, but got Ok: {:?}", v),
58            Err(_) => {}
59        }
60    };
61    ($result:expr, $msg:expr) => {
62        match $result {
63            Ok(v) => panic!("{}: Expected Err, but got Ok: {:?}", $msg, v),
64            Err(_) => {}
65        }
66    };
67}
68
69/// Assert that a function call fails, returning the error value
70///
71/// Convenience macro for testing error paths. Calls the function and asserts it returns `Err`,
72/// then returns the error value for further assertions.
73///
74/// **Ergonomics**: With `test!` macro's new `Result` return type support, this provides
75/// a concise way to test error cases without intermediate variables.
76///
77/// # Example
78///
79/// ```rust
80/// use chicago_tdd_tools::{assert_fail, test};
81///
82/// # fn fallible_function() -> Result<u32, String> { Err("error".to_string()) }
83/// test!(test_should_fail, {
84///     // Arrange: Function that should fail
85///
86///     // Act & Assert: Verify function fails and extract error
87///     let error = assert_fail!(fallible_function());
88///     assert_eq!(error, "error");
89/// });
90/// ```
91///
92/// # Example with custom message
93///
94/// ```rust
95/// use chicago_tdd_tools::{assert_fail, test};
96///
97/// # fn fallible_function() -> Result<u32, String> { Err("error".to_string()) }
98/// test!(test_should_fail_with_msg, {
99///     // Act & Assert: Verify function fails with custom message
100///     let error = assert_fail!(fallible_function(), "Operation should fail");
101///     assert_eq!(error, "error");
102/// });
103/// ```
104#[macro_export]
105macro_rules! assert_fail {
106    ($call:expr) => {
107        match $call {
108            Ok(v) => panic!("Expected function to fail, but got Ok: {:?}", v),
109            Err(e) => e,
110        }
111    };
112    ($call:expr, $msg:expr) => {
113        match $call {
114            Ok(v) => panic!("{}: Expected function to fail, but got Ok: {:?}", $msg, v),
115            Err(e) => e,
116        }
117    };
118}
119
120#[cfg(test)]
121#[allow(clippy::panic)] // Test code - panic is appropriate for test failures
122mod tests {
123    use crate::test;
124
125    test!(test_assert_ok_macro, {
126        // Arrange: Create successful result
127        let result: Result<u32, String> = Ok(42);
128
129        // Act & Assert: Verify assert_ok! macro works
130        assert_ok!(result);
131        assert_ok!(result, "Should succeed");
132    });
133
134    #[test]
135    #[should_panic(expected = "Expected Ok")]
136    fn test_assert_ok_macro_fails() {
137        // Arrange: Create error result
138        let result: Result<u32, String> = Err("error".to_string());
139
140        // Act & Assert: Should panic
141        assert_ok!(result);
142    }
143
144    test!(test_assert_err_macro, {
145        // Arrange: Create error result
146        let result: Result<u32, String> = Err("error".to_string());
147
148        // Act & Assert: Verify assert_err! macro works
149        assert_err!(result);
150        assert_err!(result, "Should fail");
151    });
152
153    #[test]
154    #[should_panic(expected = "Expected Err")]
155    fn test_assert_err_macro_fails() {
156        // Arrange: Create successful result
157        let result: Result<u32, String> = Ok(42);
158
159        // Act & Assert: Should panic
160        assert_err!(result);
161    }
162
163    test!(test_assert_fail_macro, {
164        // Arrange: Function that returns error
165        fn fallible_function() -> Result<u32, String> {
166            Err("error".to_string())
167        }
168
169        // Act & Assert: Verify assert_fail! macro works and returns error
170        let error = assert_fail!(fallible_function());
171        assert_eq!(error, "error");
172
173        // With custom message
174        let error2 = assert_fail!(fallible_function(), "Operation should fail");
175        assert_eq!(error2, "error");
176    });
177
178    #[test]
179    #[should_panic(expected = "Expected function to fail")]
180    fn test_assert_fail_macro_fails() {
181        // Arrange: Function that succeeds
182        fn successful_function() -> Result<u32, String> {
183            Ok(42)
184        }
185
186        // Act & Assert: Should panic
187        let _ = assert_fail!(successful_function());
188    }
189}