Skip to content

Commit

Permalink
Add support for :roughly parameter on Float matching
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrudel committed Jan 30, 2025
1 parent 425ffaf commit 159612f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
25 changes: 22 additions & 3 deletions lib/machete/matchers/float_matcher.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ defmodule Machete.FloatMatcher do
strictly_negative: nil,
nonzero: nil,
min: nil,
max: nil
max: nil,
roughly: nil

@typedoc """
Describes an instance of this matcher
Expand All @@ -28,7 +29,8 @@ defmodule Machete.FloatMatcher do
{:strictly_negative, boolean()},
{:nonzero, boolean()},
{:min, float()},
{:max, float()}
{:max, float()},
{:roughly, float()}
]

@doc """
Expand All @@ -43,6 +45,7 @@ defmodule Machete.FloatMatcher do
* `nonzero`: When `true`, requires the matched float be nonzero
* `min`: Requires the matched float be greater than or equal to the specified value
* `max`: Requires the matched float be less than or equal to the specified value
* `roughly`: Requires the matched float be within 5% of the specified value. Raises if set to `0.0`
Examples:
Expand Down Expand Up @@ -108,6 +111,12 @@ defmodule Machete.FloatMatcher do
iex> assert 2.0 ~> float(max: 2.0)
true
iex> assert 95.0 ~> float(roughly: 100.0)
true
iex> refute 94.0 ~> float(roughly: 100.0)
false
"""
@spec float(opts()) :: t()
def float(opts \\ []), do: struct!(__MODULE__, opts)
Expand All @@ -121,7 +130,8 @@ defmodule Machete.FloatMatcher do
nil <- matches_strictly_negative(b, a.strictly_negative),
nil <- matches_nonzero(b, a.nonzero),
nil <- matches_min(b, a.min),
nil <- matches_max(b, a.max) do
nil <- matches_max(b, a.max),
nil <- matches_roughly(b, a.roughly) do
end
end

Expand Down Expand Up @@ -169,5 +179,14 @@ defmodule Machete.FloatMatcher do
do: mismatch("#{safe_inspect(b)} is greater than #{max}")

defp matches_max(_, _), do: nil

defp matches_roughly(_b, roughly) when roughly in [-0.0, +0.0],
do: raise("`roughly` parameter cannot be 0.0")

defp matches_roughly(b, roughly)
when is_float(roughly) and (b / roughly < 0.95 or b / roughly > 1.05),
do: mismatch("#{safe_inspect(b)} is more than 5% different than #{roughly}")

defp matches_roughly(_, _), do: nil
end
end
10 changes: 10 additions & 0 deletions test/machete/matchers/float_matcher_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,14 @@ defmodule FloatMatcherTest do
test "produces a useful mismatch for max mismatch" do
assert 2.0 ~>> float(max: 1.0) ~> mismatch("2.0 is greater than 1.0")
end

test "produces a useful mismatch for roughly mismatch" do
assert 94.0 ~>> float(roughly: 100.0) ~> mismatch("94.0 is more than 5% different than 100.0")
end

test "raises when provided with a roughly value of 0.0" do
assert_raise(RuntimeError, "`roughly` parameter cannot be 0.0", fn ->
assert 94.0 ~>> float(roughly: 0.0)
end)
end
end

0 comments on commit 159612f

Please sign in to comment.