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}