Skip to content

Commit df29e8b

Browse files
katiejotsmeta-codesync[bot]
authored andcommitted
Add comparison assertion macros with better errors
Summary: Add new assertion macros for numeric comparisons that provide clear error messages showing actual values instead of just "expected true, got false". New macros: - `?assertGreaterThan(Value, Threshold)` - `?assertLessThan(Value, Threshold)` - `?assertGreaterThanOrEqual(Value, Threshold)` - `?assertLessThanOrEqual(Value, Threshold)` - `?assertInRange(Value, Min, Max)` - `?assertEqualWithDelta(Expected, Actual, Delta)` All macros support an optional Comment argument for additional context. Example: - Old: `?assert(Size <= MaxSize)` → "expected true, got false" - New: `?assertLessThanOrEqual(Size, MaxSize)` → "expected value <= threshold, got value 11, threshold 10" Reviewed By: TheGeorge Differential Revision: D91136371 fbshipit-source-id: f18724da5eb543d67fda29c4214a9b366f75c6bd
1 parent b677383 commit df29e8b

2 files changed

Lines changed: 312 additions & 2 deletions

File tree

include/assert.hrl

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,4 +222,168 @@ end).
222222
?assertEqual(lists:sort(ExpectedList), lists:sort(ActualList), Comment)
223223
).
224224

225+
%%% -------------------------------------------------------------------
226+
%%% Comparison Assertions
227+
%%%
228+
%%% These macros provide meaningful assertion failures for numeric comparisons.
229+
%%% Instead of "expected true, got false", failures show the actual values
230+
%%% and the comparison that failed.
231+
%%% -------------------------------------------------------------------
232+
233+
%% @doc Assert that Value is less than Threshold.
234+
%% Example: ?assertLessThan(ErrorCount, FailoverLimit)
235+
-define(assertLessThan(Value, Threshold),
236+
?assert(
237+
(Value) < (Threshold),
238+
lists:flatten(
239+
io_lib:format(
240+
"expected value < threshold, got value ~p, threshold ~p",
241+
[(Value), (Threshold)]
242+
)
243+
)
244+
)
245+
).
246+
247+
-define(assertLessThan(Value, Threshold, Comment),
248+
?assert(
249+
(Value) < (Threshold),
250+
lists:flatten(
251+
io_lib:format(
252+
"~s: expected value < threshold, got value ~p, threshold ~p",
253+
[(Comment), (Value), (Threshold)]
254+
)
255+
)
256+
)
257+
).
258+
259+
%% @doc Assert that Value is less than or equal to Threshold.
260+
%% Example: ?assertLessThanOrEqual(Size, MaxSize)
261+
-define(assertLessThanOrEqual(Value, Threshold),
262+
?assert(
263+
(Value) =< (Threshold),
264+
lists:flatten(
265+
io_lib:format(
266+
"expected value =< threshold, got value ~p, threshold ~p",
267+
[(Value), (Threshold)]
268+
)
269+
)
270+
)
271+
).
272+
273+
-define(assertLessThanOrEqual(Value, Threshold, Comment),
274+
?assert(
275+
(Value) =< (Threshold),
276+
lists:flatten(
277+
io_lib:format(
278+
"~s: expected value =< threshold, got value ~p, threshold ~p",
279+
[(Comment), (Value), (Threshold)]
280+
)
281+
)
282+
)
283+
).
284+
285+
%% @doc Assert that Value is greater than Threshold.
286+
%% Example: ?assertGreaterThan(length(List), 0)
287+
-define(assertGreaterThan(Value, Threshold),
288+
?assert(
289+
(Value) > (Threshold),
290+
lists:flatten(
291+
io_lib:format(
292+
"expected value > threshold, got value ~p, threshold ~p",
293+
[(Value), (Threshold)]
294+
)
295+
)
296+
)
297+
).
298+
299+
-define(assertGreaterThan(Value, Threshold, Comment),
300+
?assert(
301+
(Value) > (Threshold),
302+
lists:flatten(
303+
io_lib:format(
304+
"~s: expected value > threshold, got value ~p, threshold ~p",
305+
[(Comment), (Value), (Threshold)]
306+
)
307+
)
308+
)
309+
).
310+
311+
%% @doc Assert that Value is greater than or equal to Threshold.
312+
%% Example: ?assertGreaterThanOrEqual(Balance, 0)
313+
-define(assertGreaterThanOrEqual(Value, Threshold),
314+
?assert(
315+
(Value) >= (Threshold),
316+
lists:flatten(
317+
io_lib:format(
318+
"expected value >= threshold, got value ~p, threshold ~p",
319+
[(Value), (Threshold)]
320+
)
321+
)
322+
)
323+
).
324+
325+
-define(assertGreaterThanOrEqual(Value, Threshold, Comment),
326+
?assert(
327+
(Value) >= (Threshold),
328+
lists:flatten(
329+
io_lib:format(
330+
"~s: expected value >= threshold, got value ~p, threshold ~p",
331+
[(Comment), (Value), (Threshold)]
332+
)
333+
)
334+
)
335+
).
336+
337+
%% @doc Assert that Value is within the range [Min, Max] (inclusive).
338+
%% Example: ?assertInRange(Percentage, 0, 100)
339+
-define(assertInRange(Value, Min, Max),
340+
?assert(
341+
(Value) >= (Min) andalso (Value) =< (Max),
342+
lists:flatten(
343+
io_lib:format(
344+
"expected ~p =< value =< ~p, got value ~p",
345+
[(Min), (Max), (Value)]
346+
)
347+
)
348+
)
349+
).
350+
351+
-define(assertInRange(Value, Min, Max, Comment),
352+
?assert(
353+
(Value) >= (Min) andalso (Value) =< (Max),
354+
lists:flatten(
355+
io_lib:format(
356+
"~s: expected ~p =< value =< ~p, got value ~p",
357+
[(Comment), (Min), (Max), (Value)]
358+
)
359+
)
360+
)
361+
).
362+
363+
%% @doc Assert that Actual is within Delta of Expected (for floating point comparisons).
364+
%% Example: ?assertEqualWithDelta(3.14159, calculate_pi(), 0.001)
365+
-define(assertEqualWithDelta(Expected, Actual, Delta),
366+
?assert(
367+
abs((Actual) - (Expected)) =< (Delta),
368+
lists:flatten(
369+
io_lib:format(
370+
"expected |actual - expected| =< delta, got expected ~p, actual ~p, delta ~p",
371+
[(Expected), (Actual), (Delta)]
372+
)
373+
)
374+
)
375+
).
376+
377+
-define(assertEqualWithDelta(Expected, Actual, Delta, Comment),
378+
?assert(
379+
abs((Actual) - (Expected)) =< (Delta),
380+
lists:flatten(
381+
io_lib:format(
382+
"~s: expected |actual - expected| =< delta, got expected ~p, actual ~p, delta ~p",
383+
[(Comment), (Expected), (Actual), (Delta)]
384+
)
385+
)
386+
)
387+
).
388+
225389
-endif.

test/wa_assert_SUITE.erl

Lines changed: 148 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@
3030
assert_match/1,
3131
assert_comparison/1,
3232
assert_map_comprehension/1,
33-
assert_call_with_bindings/1
33+
assert_call_with_bindings/1,
34+
assert_greater_than/1,
35+
assert_less_than/1,
36+
assert_greater_than_or_equal/1,
37+
assert_less_than_or_equal/1,
38+
assert_in_range/1,
39+
assert_equal_with_delta/1
3440
]).
3541

3642
all() ->
@@ -40,7 +46,13 @@ all() ->
4046
assert_match,
4147
assert_comparison,
4248
assert_map_comprehension,
43-
assert_call_with_bindings
49+
assert_call_with_bindings,
50+
assert_less_than,
51+
assert_less_than_or_equal,
52+
assert_greater_than,
53+
assert_greater_than_or_equal,
54+
assert_in_range,
55+
assert_equal_with_delta
4456
].
4557

4658
%%--------------------------------------------------------------------
@@ -87,3 +99,137 @@ actual(X) -> X.
8799

88100
actual_list() -> [1, 2, 3, 4, 5].
89101
expected_list() -> [1, 5, 3, 2, 4].
102+
103+
%%--------------------------------------------------------------------
104+
%% Comparison Assertion Tests
105+
%%
106+
%% Should be able to compare:
107+
%% - Timestamps (large integers)
108+
%% - Counts (small non-negative integers)
109+
%% - Percentages
110+
%% - Floats (for delta comparisons)
111+
%% - Negative numbers (for some range checks)
112+
%%--------------------------------------------------------------------
113+
114+
assert_less_than(_Config) ->
115+
%% Basic integer comparisons
116+
ok = ?assertLessThan(5, 10),
117+
ok = ?assertLessThan(0, 100),
118+
%% Counts (eg: queue sizes, error counts)
119+
QueueSize = 50,
120+
MaxQueue = 100,
121+
ok = ?assertLessThan(QueueSize, MaxQueue),
122+
%% Negative numbers
123+
ok = ?assertLessThan(-10, -5),
124+
%% Floats
125+
ok = ?assertLessThan(1.0, 1.5),
126+
ok = ?assertLessThan(0.0, 0.001),
127+
%% Failure cases
128+
?assertException(error, {assert, _}, ?assertLessThan(10, 5)),
129+
?assertException(error, {assert, _}, ?assertLessThan(10, 10)),
130+
%% With comment
131+
ok = ?assertLessThan(5, 10, "should be less").
132+
133+
assert_less_than_or_equal(_Config) ->
134+
%% Basic integer comparisons
135+
ok = ?assertLessThanOrEqual(5, 10),
136+
ok = ?assertLessThanOrEqual(10, 10),
137+
%% Counts (eg: capacity used =< max)
138+
Used = 80,
139+
Max = 100,
140+
ok = ?assertLessThanOrEqual(Used, Max),
141+
%% Negative numbers
142+
ok = ?assertLessThanOrEqual(-10, -5),
143+
ok = ?assertLessThanOrEqual(-5, -5),
144+
%% Floats
145+
ok = ?assertLessThanOrEqual(1.5, 1.5),
146+
ok = ?assertLessThanOrEqual(1.4, 1.5),
147+
%% Failure cases
148+
?assertException(error, {assert, _}, ?assertLessThanOrEqual(10, 5)),
149+
?assertException(error, {assert, _}, ?assertLessThanOrEqual(101, 100)),
150+
%% With comment
151+
ok = ?assertLessThanOrEqual(10, 10, "should not exceed threshold").
152+
153+
assert_greater_than(_Config) ->
154+
%% Basic integer comparisons
155+
ok = ?assertGreaterThan(10, 5),
156+
ok = ?assertGreaterThan(100, 0),
157+
%% Timestamp comparisons
158+
Ts1 = 1737471235,
159+
Ts2 = 1737471234,
160+
ok = ?assertGreaterThan(Ts1, Ts2),
161+
%% Negative numbers
162+
ok = ?assertGreaterThan(-5, -10),
163+
%% Floats
164+
ok = ?assertGreaterThan(1.5, 1.0),
165+
ok = ?assertGreaterThan(0.001, 0.0),
166+
%% Failure cases
167+
?assertException(error, {assert, _}, ?assertGreaterThan(5, 10)),
168+
?assertException(error, {assert, _}, ?assertGreaterThan(10, 10)),
169+
?assertException(error, {assert, _}, ?assertGreaterThan(Ts2, Ts2)),
170+
%% With comment
171+
ok = ?assertGreaterThan(10, 5, "should be greater").
172+
173+
assert_greater_than_or_equal(_Config) ->
174+
%% Basic integer comparisons
175+
ok = ?assertGreaterThanOrEqual(10, 5),
176+
ok = ?assertGreaterThanOrEqual(10, 10),
177+
%% Zero checks (eg: balance >= 0)
178+
Balance = 100,
179+
ok = ?assertGreaterThanOrEqual(Balance, 0),
180+
ok = ?assertGreaterThanOrEqual(0, 0),
181+
%% Negative numbers
182+
ok = ?assertGreaterThanOrEqual(-5, -10),
183+
ok = ?assertGreaterThanOrEqual(-5, -5),
184+
%% Floats
185+
ok = ?assertGreaterThanOrEqual(1.5, 1.5),
186+
ok = ?assertGreaterThanOrEqual(1.6, 1.5),
187+
%% Failure cases
188+
?assertException(error, {assert, _}, ?assertGreaterThanOrEqual(5, 10)),
189+
?assertException(error, {assert, _}, ?assertGreaterThanOrEqual(-1, 0)),
190+
%% With comment
191+
ok = ?assertGreaterThanOrEqual(10, 10, "should be at least threshold").
192+
193+
assert_in_range(_Config) ->
194+
%% Percentage range (0-100)
195+
Percentage = 75,
196+
ok = ?assertInRange(Percentage, 0, 100),
197+
ok = ?assertInRange(0, 0, 100),
198+
ok = ?assertInRange(100, 0, 100),
199+
%% HTTP status codes
200+
ok = ?assertInRange(200, 200, 299),
201+
ok = ?assertInRange(404, 400, 499),
202+
%% Negative ranges
203+
ok = ?assertInRange(-5, -10, 0),
204+
ok = ?assertInRange(-10, -10, -5),
205+
%% Floats
206+
ok = ?assertInRange(1.5, 1.0, 2.0),
207+
ok = ?assertInRange(0.5, 0.0, 1.0),
208+
%% Failure cases
209+
?assertException(error, {assert, _}, ?assertInRange(-1, 0, 100)),
210+
?assertException(error, {assert, _}, ?assertInRange(101, 0, 100)),
211+
?assertException(error, {assert, _}, ?assertInRange(199, 200, 299)),
212+
%% With comment
213+
ok = ?assertInRange(50, 0, 100, "percentage must be valid").
214+
215+
assert_equal_with_delta(_Config) ->
216+
%% Float comparisons with tolerance
217+
ok = ?assertEqualWithDelta(3.14159, 3.14, 0.01),
218+
ok = ?assertEqualWithDelta(3.14159, 3.141, 0.001),
219+
%% Integer approximations
220+
ok = ?assertEqualWithDelta(100, 100.5, 1),
221+
ok = ?assertEqualWithDelta(100, 99, 1),
222+
%% Zero handling
223+
ok = ?assertEqualWithDelta(0.0, 0.0, 0.001),
224+
ok = ?assertEqualWithDelta(0.0, 0.0001, 0.001),
225+
%% Negative values
226+
ok = ?assertEqualWithDelta(-5.0, -5.1, 0.2),
227+
ok = ?assertEqualWithDelta(-100, -99, 2),
228+
%% Large values with delta
229+
ok = ?assertEqualWithDelta(1000000, 1000001, 10),
230+
%% Failure cases
231+
?assertException(error, {assert, _}, ?assertEqualWithDelta(3.14159, 3.0, 0.01)),
232+
?assertException(error, {assert, _}, ?assertEqualWithDelta(100, 102, 1)),
233+
?assertException(error, {assert, _}, ?assertEqualWithDelta(0.0, 0.1, 0.01)),
234+
%% With comment
235+
ok = ?assertEqualWithDelta(3.14, 3.14159, 0.01, "pi approximation").

0 commit comments

Comments
 (0)