Skip to content

Commit 444ca1a

Browse files
committed
feat: add MustBeGreaterThanOrApproximately
Signed-off-by: Kenny Pflug <kenny.pflug@live.de>
1 parent 0415304 commit 444ca1a

File tree

3 files changed

+615
-0
lines changed

3 files changed

+615
-0
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
using System;
2+
using FluentAssertions;
3+
using Xunit;
4+
5+
namespace Light.GuardClauses.Tests.ComparableAssertions;
6+
7+
public static class CheckMustBeGreaterThanOrApproximatelyTests
8+
{
9+
[Theory]
10+
[InlineData(17.4, 17.3)]
11+
[InlineData(19.9999999, 20.0)]
12+
[InlineData(-5.49998, -5.5)]
13+
[InlineData(0.0001, 0.0001)]
14+
public static void EqualOrGreater_Double(double first, double second) =>
15+
first.MustBeGreaterThanOrApproximately(second).Should().Be(first);
16+
17+
[Theory]
18+
[InlineData(15.91, 15.9, 0.1)]
19+
[InlineData(24.49999, 24.45, 0.0001)]
20+
[InlineData(-3.12, -3.2, 0.001)]
21+
[InlineData(2.369, 2.37, 0.05)]
22+
public static void EqualOrGreaterWithTolerance_Double(double first, double second, double tolerance) =>
23+
first.MustBeGreaterThanOrApproximately(second, tolerance).Should().Be(first);
24+
25+
[Theory]
26+
[InlineData(100.225f, 100.2f)]
27+
[InlineData(-5.9f, -5.900005f)]
28+
[InlineData(0f, -0.02f)]
29+
[InlineData(-0.00001f, 0f)]
30+
public static void EqualOrGreater_Float(float first, float second) =>
31+
first.MustBeGreaterThanOrApproximately(second).Should().Be(first);
32+
33+
[Theory]
34+
[InlineData(2.0f, 1.0f, 0.1f)]
35+
[InlineData(1.0f, 1.0f, 0.1f)]
36+
[InlineData(1.01f, 1.1f, 0.1f)]
37+
[InlineData(1.0f, 2.0f, 1.0f)]
38+
public static void EqualOrGreaterWithTolerance_Float(float first, float second, float tolerance) =>
39+
first.MustBeGreaterThanOrApproximately(second, tolerance).Should().Be(first);
40+
41+
[Theory]
42+
[InlineData(5.0, 5.3, 0.1)]
43+
[InlineData(100.0, 100.5, 0.1)]
44+
[InlineData(-20.0, -19.8, 0.1)]
45+
[InlineData(0.0001, 0.0003, 0.00005)]
46+
public static void NotGreaterThanOrApproximately_Double(double value, double other, double tolerance)
47+
{
48+
var act = () => value.MustBeGreaterThanOrApproximately(other, tolerance, nameof(value));
49+
50+
var exceptionAssertion = act.Should().Throw<ArgumentOutOfRangeException>().Which;
51+
exceptionAssertion.Message.Should().Contain(
52+
$"{nameof(value)} must be greater than or approximately equal to {other} with a tolerance of {tolerance}, but it actually is {value}."
53+
);
54+
exceptionAssertion.ParamName.Should().BeSameAs(nameof(value));
55+
}
56+
57+
[Theory]
58+
[InlineData(5.0f, 5.3f, 0.1f)]
59+
[InlineData(100.0f, 100.5f, 0.1f)]
60+
[InlineData(-20.0f, -19.8f, 0.1f)]
61+
[InlineData(0.0001f, 0.0003f, 0.00005f)]
62+
public static void NotGreaterThanOrApproximately_Float(float value, float other, float tolerance)
63+
{
64+
var act = () => value.MustBeGreaterThanOrApproximately(other, tolerance, nameof(value));
65+
66+
var exceptionAssertion = act.Should().Throw<ArgumentOutOfRangeException>().Which;
67+
exceptionAssertion.Message.Should().Contain(
68+
$"{nameof(value)} must be greater than or approximately equal to {other} with a tolerance of {tolerance}, but it actually is {value}."
69+
);
70+
exceptionAssertion.ParamName.Should().BeSameAs(nameof(value));
71+
}
72+
73+
[Fact]
74+
public static void DefaultTolerance_Double()
75+
{
76+
// Should pass - difference is 0.00005 which is less than default tolerance 0.0001
77+
const double value = 1.00005;
78+
value.MustBeGreaterThanOrApproximately(1.0).Should().Be(value);
79+
80+
// Should throw - difference is 0.0002 which is greater than default tolerance 0.0001
81+
Action act = () => 0.9998.MustBeGreaterThanOrApproximately(1.0, "parameter");
82+
act.Should().Throw<ArgumentOutOfRangeException>()
83+
.WithParameterName("parameter");
84+
}
85+
86+
[Fact]
87+
public static void DefaultTolerance_Float()
88+
{
89+
// Should pass - difference is 0.00005f which is less than default tolerance 0.0001f
90+
const float value = 1.00005f;
91+
value.MustBeGreaterThanOrApproximately(1.0f).Should().Be(value);
92+
93+
// Should throw - difference is 0.0002f which is greater than default tolerance 0.0001f
94+
Action act = () => 0.9998f.MustBeGreaterThanOrApproximately(1.0f, "parameter");
95+
act.Should().Throw<ArgumentOutOfRangeException>()
96+
.WithParameterName("parameter");
97+
}
98+
99+
[Fact]
100+
public static void CustomException_Double() =>
101+
Test.CustomException(
102+
5.0,
103+
5.3,
104+
(x, y, exceptionFactory) => x.MustBeGreaterThanOrApproximately(y, exceptionFactory)
105+
);
106+
107+
[Fact]
108+
public static void CustomExceptionWithTolerance_Double() =>
109+
Test.CustomException(
110+
5.0,
111+
5.5,
112+
0.1,
113+
(x, y, z, exceptionFactory) => x.MustBeGreaterThanOrApproximately(y, z, exceptionFactory)
114+
);
115+
116+
[Fact]
117+
public static void CustomException_Float() =>
118+
Test.CustomException(
119+
5.0f,
120+
5.3f,
121+
(x, y, exceptionFactory) => x.MustBeGreaterThanOrApproximately(y, exceptionFactory)
122+
);
123+
124+
[Fact]
125+
public static void CustomExceptionWithTolerance_Float() =>
126+
Test.CustomException(
127+
5.0f,
128+
5.5f,
129+
0.1f,
130+
(x, y, z, exceptionFactory) => x.MustBeGreaterThanOrApproximately(y, z, exceptionFactory)
131+
);
132+
133+
[Fact]
134+
public static void NoCustomExceptionThrown_Double() =>
135+
5.2.MustBeGreaterThanOrApproximately(5.1, (_, _) => null).Should().Be(5.2);
136+
137+
[Fact]
138+
public static void NoCustomExceptionThrownWithTolerance_Double() =>
139+
5.2.MustBeGreaterThanOrApproximately(5.0, 0.1, (_, _, _) => null).Should().Be(5.2);
140+
141+
[Fact]
142+
public static void NoCustomExceptionThrown_Float() =>
143+
5.2f.MustBeGreaterThanOrApproximately(5.0f, (_, _) => null).Should().Be(5.2f);
144+
145+
[Fact]
146+
public static void NoCustomExceptionThrownWithTolerance_Float() =>
147+
5.2f.MustBeGreaterThanOrApproximately(5.0f, 0.1f, (_, _, _) => null).Should().Be(5.2f);
148+
149+
[Fact]
150+
public static void CustomMessage_Double() =>
151+
Test.CustomMessage<ArgumentOutOfRangeException>(
152+
message => 100.0.MustBeGreaterThanOrApproximately(101.0, 0.5, message: message)
153+
);
154+
155+
[Fact]
156+
public static void CustomMessage_Float() =>
157+
Test.CustomMessage<ArgumentOutOfRangeException>(
158+
message => 100.0f.MustBeGreaterThanOrApproximately(101.0f, 0.5f, message: message)
159+
);
160+
161+
[Fact]
162+
public static void CallerArgumentExpression_Double()
163+
{
164+
const double seventyEightO1 = 78.1;
165+
166+
var act = () => seventyEightO1.MustBeGreaterThanOrApproximately(79.0);
167+
168+
act.Should().Throw<ArgumentOutOfRangeException>()
169+
.WithParameterName(nameof(seventyEightO1));
170+
}
171+
172+
[Fact]
173+
public static void CallerArgumentExpressionWithTolerance_Double()
174+
{
175+
const double pi = 3.14159;
176+
177+
var act = () => pi.MustBeGreaterThanOrApproximately(3.5, 0.1);
178+
179+
act.Should().Throw<ArgumentOutOfRangeException>()
180+
.WithParameterName(nameof(pi));
181+
}
182+
183+
[Fact]
184+
public static void CallerArgumentExpression_Float()
185+
{
186+
const float seventyEightO1 = 78.1f;
187+
188+
var act = () => seventyEightO1.MustBeGreaterThanOrApproximately(79.0f);
189+
190+
act.Should().Throw<ArgumentOutOfRangeException>()
191+
.WithParameterName(nameof(seventyEightO1));
192+
}
193+
194+
[Fact]
195+
public static void CallerArgumentExpressionWithTolerance_Float()
196+
{
197+
const float pi = 3.14159f;
198+
199+
var act = () => pi.MustBeGreaterThanOrApproximately(3.5f, 0.1f);
200+
201+
act.Should().Throw<ArgumentOutOfRangeException>()
202+
.WithParameterName(nameof(pi));
203+
}
204+
205+
#if NET8_0
206+
[Theory]
207+
[InlineData(15.91, 15.9, 0.1)]
208+
[InlineData(24.4999, 24.45, 0.0001)]
209+
[InlineData(-3.12, -3.2, 0.001)]
210+
[InlineData(2.369, 2.37, 0.05)]
211+
[InlineData(15.0, 14.0, 0.1)] // Greater than case
212+
[InlineData(14.95, 15.0, 0.1)] // Approximately equal case
213+
public static void EqualOrGreaterWithCustomTolerance_GenericDouble(double first, double second, double tolerance) =>
214+
first.MustBeGreaterThanOrApproximately<double>(second, tolerance).Should().Be(first);
215+
216+
[Theory]
217+
[InlineData(10, 5, 1)] // Greater than case
218+
[InlineData(5, 5, 1)] // Equal case
219+
[InlineData(5, 6, 1)] // Approximately equal case
220+
[InlineData(5, 7, 2)] // Not greater than or approximately equal case
221+
public static void EqualOrGreaterWithCustomTolerance_GenericInt32(int first, int second, int tolerance) =>
222+
first.MustBeGreaterThanOrApproximately(second, tolerance).Should().Be(first);
223+
224+
[Theory]
225+
[InlineData(10L, 5L, 1L)] // Greater than case
226+
[InlineData(5L, 5L, 1L)] // Equal case
227+
[InlineData(5L, 6L, 1L)] // Approximately equal case
228+
[InlineData(4L, 7L, 3L)] // Not greater than or approximately equal case
229+
public static void EqualOrGreaterWithCustomTolerance_GenericInt64(long first, long second, long tolerance) =>
230+
first.MustBeGreaterThanOrApproximately(second, tolerance).Should().Be(first);
231+
232+
[Theory]
233+
[MemberData(nameof(DecimalTestData))]
234+
public static void GenericDecimalWithCustomTolerance(
235+
decimal first,
236+
decimal second,
237+
decimal tolerance
238+
) =>
239+
first.MustBeGreaterThanOrApproximately(second, tolerance).Should().Be(first);
240+
241+
public static TheoryData<decimal, decimal, decimal> DecimalTestData() => new ()
242+
{
243+
{ 1.3m, 1.1m, 0.1m }, // Greater than case
244+
{ 1.1m, 1.1m, 0.1m }, // Equal case
245+
{ 1.0m, 1.1m, 0.2m }, // Approximately equal case
246+
{ 1.292m, 1.3m, 0.1m }, // Not greater than or approximately equal case
247+
};
248+
249+
[Theory]
250+
[InlineData(5.0, 5.3, 0.1)]
251+
[InlineData(100.0, 100.5, 0.1)]
252+
[InlineData(-20.0, -19.8, 0.1)]
253+
[InlineData(0.0001, 0.0003, 0.00005)]
254+
public static void NotGreaterThanOrApproximately_Generic(double value, double other, double tolerance)
255+
{
256+
var act = () => value.MustBeGreaterThanOrApproximately<double>(other, tolerance, nameof(value));
257+
258+
var exceptionAssertion = act.Should().Throw<ArgumentOutOfRangeException>().Which;
259+
exceptionAssertion.Message.Should().Contain(
260+
$"{nameof(value)} must be greater than or approximately equal to {other} with a tolerance of {tolerance}, but it actually is {value}."
261+
);
262+
exceptionAssertion.ParamName.Should().BeSameAs(nameof(value));
263+
}
264+
265+
[Fact]
266+
public static void CustomExceptionWithTolerance_Generic() =>
267+
Test.CustomException(
268+
5.0,
269+
5.5,
270+
0.1,
271+
(x, y, t, exceptionFactory) => x.MustBeGreaterThanOrApproximately<double>(y, t, exceptionFactory)
272+
);
273+
274+
[Fact]
275+
public static void NoCustomExceptionThrown_Generic() =>
276+
5.2.MustBeGreaterThanOrApproximately<double>(5.0, 0.1, (_, _, _) => null).Should().Be(5.2);
277+
278+
[Fact]
279+
public static void CustomMessage_Generic() =>
280+
Test.CustomMessage<ArgumentOutOfRangeException>(
281+
message => 100.0.MustBeGreaterThanOrApproximately<double>(101.0, 0.5, message: message)
282+
);
283+
284+
[Fact]
285+
public static void CallerArgumentExpressionWithTolerance_Generic()
286+
{
287+
const double seventyEightO1 = 78.1;
288+
289+
var act = () => seventyEightO1.MustBeGreaterThanOrApproximately<double>(79.0, 0.5);
290+
291+
act.Should().Throw<ArgumentOutOfRangeException>()
292+
.WithParameterName(nameof(seventyEightO1));
293+
}
294+
#endif
295+
}

0 commit comments

Comments
 (0)