fluent_assertions/assertions/
numeric_assertion.rs1use super::Assertion;
2use num_traits::{Float, Zero};
3use std::cmp::PartialOrd;
4use std::fmt::{Debug, Display};
5use std::ops::RangeBounds;
6
7impl<T> Assertion<T>
9where
10 T: PartialOrd + Display + Zero + Copy,
11{
12 #[track_caller]
21 pub fn be_greater_than_or_equal_to(self, other: T) -> Self {
22 assert!(
23 self.value >= other,
24 "Expected value to be greater than or equal to {}, but got {}",
25 other,
26 self.value
27 );
28 self
29 }
30
31 #[track_caller]
40 pub fn be_greater_than(self, other: T) -> Self {
41 assert!(
42 self.value > other,
43 "Expected value to be greater than {}, but got {}",
44 other,
45 self.value
46 );
47 self
48 }
49
50 #[track_caller]
59 pub fn be_less_than_or_equal_to(self, other: T) -> Self {
60 assert!(
61 self.value <= other,
62 "Expected value to be less than or equal to {}, but got {}",
63 other,
64 self.value
65 );
66 self
67 }
68
69 #[track_caller]
78 pub fn be_less_than(self, other: T) -> Self {
79 assert!(
80 self.value < other,
81 "Expected value to be less than {}, but got {}",
82 other,
83 self.value
84 );
85 self
86 }
87
88 #[track_caller]
97 pub fn be_positive(self) -> Self {
98 assert!(
99 self.value > T::zero(),
100 "Expected positive value, but found {}",
101 self.value
102 );
103 self
104 }
105
106 #[track_caller]
115 pub fn be_negative(self) -> Self {
116 assert!(
117 self.value < T::zero(),
118 "Expected negative value, but found {}",
119 self.value
120 );
121 self
122 }
123
124 #[track_caller]
133 pub fn be_in_range(self, range: impl RangeBounds<T> + Debug) -> Self {
134 assert!(
135 range.contains(&self.value),
136 "Expected value {} to be in range {:?}, but it wasn't",
137 self.value,
138 range
139 );
140 self
141 }
142
143 #[track_caller]
152 pub fn not_be_in_range(self, range: impl RangeBounds<T> + Debug) -> Self {
153 assert!(
154 !range.contains(&self.value),
155 "Expected value {} to not be in range {:?}, but it was",
156 self.value,
157 range
158 );
159 self
160 }
161}
162
163impl<T> Assertion<T>
165where
166 T: Float + Display,
167{
168 #[track_caller]
181 pub fn be_close_to(self, expected: T, tolerance: T) -> Self {
182 assert!(
183 (self.value - expected).abs() <= tolerance,
184 "Expected value {} to be close to {} (tolerance {}), but it wasn't",
185 self.value,
186 expected,
187 tolerance
188 );
189 self
190 }
191}
192
193#[cfg(test)]
194mod tests {
195 use crate::assertions::*;
196 use rstest::*;
197
198 #[rstest]
199 #[case(43, 42)]
200 #[case(1, 0)]
201 fn should_be_greater_and_positive(#[case] input: isize, #[case] value: isize) {
202 input.should().be_greater_than(value).be_positive();
203 }
204
205 #[rstest]
206 #[case(42.0, 41.99)]
207 #[case(1.0, 0.9)]
208 fn should_be_greater_f64(#[case] input: f64, #[case] value: f64) {
209 input.should().be_greater_than(value);
210 }
211
212 #[rstest]
213 #[case(-42)]
214 #[case(-3)]
215 fn should_be_negative_i8(#[case] input: i8) {
216 input
217 .should()
218 .be_greater_than(-43)
219 .be_negative()
220 .not_be(32)
221 .be(input);
222 }
223
224 #[test]
225 fn should_be_in_inclusive_range() {
226 5.should().be_in_range(1..=10);
227 }
228
229 #[test]
230 fn should_be_in_exclusive_range() {
231 5.should().be_in_range(1..10);
232 }
233
234 #[test]
235 #[should_panic(expected = "to be in range")]
236 fn be_in_range_panics_at_exclusive_end() {
237 10.should().be_in_range(1..10);
238 }
239
240 #[test]
241 fn should_not_be_in_range() {
242 20.should().not_be_in_range(1..=10);
243 }
244
245 #[rstest]
246 #[case(1.0f64, 1.0001, 0.001)]
247 #[case(1.0f64, 0.9999, 0.001)]
248 fn should_be_close_to_f64(#[case] input: f64, #[case] expected: f64, #[case] tolerance: f64) {
249 input.should().be_close_to(expected, tolerance);
250 }
251
252 #[rstest]
253 #[case(1.0f32, 1.05, 0.1)]
254 fn should_be_close_to_f32(#[case] input: f32, #[case] expected: f32, #[case] tolerance: f32) {
255 input.should().be_close_to(expected, tolerance);
256 }
257
258 #[test]
259 #[should_panic(expected = "to be close to")]
260 fn be_close_to_panics_when_outside_tolerance() {
261 1.0f64.should().be_close_to(1.5, 0.1);
262 }
263}