prop/test/microwaveprop/format_property_test.exs

57 lines
1.8 KiB
Elixir

defmodule Microwaveprop.FormatPropertyTest do
use ExUnit.Case, async: true
use ExUnitProperties
alias Microwaveprop.Format
# Any finite non-negative number is legitimate input for distance_km/1.
# StreamData floats default to the full representable range — we keep
# that but reject negatives since negative distances are meaningless
# (the algorithm callers always pass an already-absolute km value).
defp non_negative_number do
one_of([
integer(0..1_000_000_000),
map(float(min: 0.0), fn f -> f end),
map(integer(0..1_000_000), &(&1 * 1.0))
])
end
describe "distance_km/1" do
property "returns a binary for nil" do
# Not really a property, just pinned for discoverability alongside
# the numeric properties.
assert Format.distance_km(nil) == ""
end
property "always returns a non-empty binary for any non-negative number" do
check all(n <- non_negative_number()) do
result = Format.distance_km(n)
assert is_binary(result)
assert result != ""
end
end
property "output contains both `mi` and `km` units" do
check all(n <- non_negative_number()) do
result = Format.distance_km(n)
assert result =~ "mi"
assert result =~ "km"
end
end
property "accepts Decimal input without crashing" do
check all(n <- integer(0..10_000)) do
decimal = Decimal.new(n)
assert is_binary(Format.distance_km(decimal))
end
end
property "accepts negative distances without crashing" do
# Not a valid input at the call site, but we don't want arbitrary
# numeric data (e.g. a sign slip in a caller) to crash the view.
check all(n <- float(min: -1.0e6, max: -0.01)) do
assert is_binary(Format.distance_km(n))
end
end
end
end