shard-spectator/spec/docs/custom_matchers_spec.cr

91 lines
3.2 KiB
Crystal

require "../spec_helper"
# https://gitlab.com/arctic-fox/spectator/-/wikis/Custom-Matchers
Spectator.describe "Custom Matchers Docs" do
context "value matcher" do
# Sub-type of Matcher to suit our needs.
# Notice this is a struct.
struct MultipleOfMatcher(ExpectedType) < Spectator::Matchers::ValueMatcher(ExpectedType)
# Short text about the matcher's purpose.
# This explains what condition satisfies the matcher.
# The description is used when the one-liner syntax is used.
def description : String
"is a multiple of #{expected.label}"
end
# Checks whether the matcher is satisfied with the expression given to it.
private def match?(actual : Spectator::Expression(T)) : Bool forall T
actual.value % expected.value == 0
end
# Message displayed when the matcher isn't satisfied.
# The message should typically only contain the test expression labels.
private def failure_message(actual : Spectator::Expression(T)) : String forall T
"#{actual.label} is not a multiple of #{expected.label}"
end
# Message displayed when the matcher isn't satisfied and is negated.
# This is essentially what would satisfy the matcher if it wasn't negated.
# The message should typically only contain the test expression labels.
private def failure_message_when_negated(actual : Spectator::Expression(T)) : String forall T
"#{actual.label} is a multiple of #{expected.label}"
end
end
# The DSL portion of the matcher.
# This captures the test expression and creates an instance of the matcher.
macro be_a_multiple_of(expected)
%value = ::Spectator::Value.new({{expected}}, {{expected.stringify}})
MultipleOfMatcher.new(%value)
end
specify do
expect(9).to be_a_multiple_of(3)
# or negated:
expect(5).to_not be_a_multiple_of(2)
end
specify "failure messages" do
expect { expect(9).to be_a_multiple_of(5) }.to raise_error(Spectator::ExpectationFailed, "9 is not a multiple of 5")
expect { expect(6).to_not be_a_multiple_of(3) }.to raise_error(Spectator::ExpectationFailed, "6 is a multiple of 3")
end
end
context "standard matcher" do
struct OddMatcher < Spectator::Matchers::StandardMatcher
def description : String
"is odd"
end
private def match?(actual : Spectator::Expression(T)) : Bool forall T
actual.value % 2 == 1
end
private def failure_message(actual : Spectator::Expression(T)) : String forall T
"#{actual.label} is not odd"
end
private def failure_message_when_negated(actual : Spectator::Expression(T)) : String forall T
"#{actual.label} is odd"
end
private def does_not_match?(actual : Spectator::Expression(T)) : Bool forall T
actual.value % 2 == 0
end
end
macro be_odd
OddMatcher.new
end
specify do
expect(9).to be_odd
expect(2).to_not be_odd
end
specify "failure messages" do
expect { expect(2).to be_odd }.to raise_error(Spectator::ExpectationFailed, "2 is not odd")
expect { expect(3).to_not be_odd }.to raise_error(Spectator::ExpectationFailed, "3 is odd")
end
end
end