Update CaseMatcher to use MatchData

This commit is contained in:
Michael Miller 2019-03-03 19:05:20 -07:00
parent 50a782b803
commit e38bcd544a
2 changed files with 175 additions and 140 deletions

View file

@ -1,153 +1,172 @@
require "../spec_helper" require "../spec_helper"
describe Spectator::Matchers::CaseMatcher do describe Spectator::Matchers::CaseMatcher do
describe "#match?" do describe "#match" do
it "compares using #===" do it "compares using #===" do
spy = SpySUT.new spy = SpySUT.new
partial = new_partial(42) partial = new_partial(42)
matcher = Spectator::Matchers::CaseMatcher.new(spy) matcher = Spectator::Matchers::CaseMatcher.new(spy)
matcher.match?(partial).should be_true matcher.match(partial)
spy.case_eq_call_count.should be > 0 spy.case_eq_call_count.should be > 0
end end
context "with identical values" do context "returned MatchData" do
it "is true" do describe "#matched?" do
value = 42 context "with identical values" do
partial = new_partial(value) it "is true" do
matcher = Spectator::Matchers::CaseMatcher.new(value) value = 42
matcher.match?(partial).should be_true partial = new_partial(value)
end matcher = Spectator::Matchers::CaseMatcher.new(value)
end match_data = matcher.match(partial)
match_data.matched?.should be_true
end
end
context "with different values" do context "with different values" do
it "is false" do it "is false" do
value1 = 42 value1 = 42
value2 = 777 value2 = 777
partial = new_partial(value1) partial = new_partial(value1)
matcher = Spectator::Matchers::CaseMatcher.new(value2) matcher = Spectator::Matchers::CaseMatcher.new(value2)
matcher.match?(partial).should be_false match_data = matcher.match(partial)
end match_data.matched?.should be_false
end end
end
context "with the same instance" do context "with the same instance" do
it "is true" do it "is true" do
# Box is used because it is a reference type and doesn't override the == method. # Box is used because it is a reference type and doesn't override the == method.
ref = Box.new([] of Int32) ref = Box.new([] of Int32)
partial = new_partial(ref) partial = new_partial(ref)
matcher = Spectator::Matchers::CaseMatcher.new(ref) matcher = Spectator::Matchers::CaseMatcher.new(ref)
matcher.match?(partial).should be_true match_data = matcher.match(partial)
end match_data.matched?.should be_true
end end
end
context "with different instances" do context "with different instances" do
context "with same contents" do context "with same contents" do
it "is true" do it "is true" do
array1 = [1, 2, 3] array1 = [1, 2, 3]
array2 = [1, 2, 3] array2 = [1, 2, 3]
partial = new_partial(array1) partial = new_partial(array1)
matcher = Spectator::Matchers::CaseMatcher.new(array2) matcher = Spectator::Matchers::CaseMatcher.new(array2)
matcher.match?(partial).should be_true match_data = matcher.match(partial)
match_data.matched?.should be_true
end
end
context "with different contents" do
it "is false" do
array1 = [1, 2, 3]
array2 = [4, 5, 6]
partial = new_partial(array1)
matcher = Spectator::Matchers::CaseMatcher.new(array2)
match_data = matcher.match(partial)
match_data.matched?.should be_false
end
end
context "with the same type" do
it "is true" do
value1 = "foobar"
value2 = String
partial = new_partial(value1)
matcher = Spectator::Matchers::CaseMatcher.new(value2)
match_data = matcher.match(partial)
match_data.matched?.should be_true
end
end
context "with a different type" do
it "is false" do
value1 = "foobar"
value2 = Array
partial = new_partial(value1)
matcher = Spectator::Matchers::CaseMatcher.new(value2)
match_data = matcher.match(partial)
match_data.matched?.should be_false
end
end
end end
end end
context "with different contents" do describe "#message" do
it "is false" do it "mentions ===" do
array1 = [1, 2, 3] value = 42
array2 = [4, 5, 6] partial = new_partial(value)
partial = new_partial(array1) matcher = Spectator::Matchers::CaseMatcher.new(value)
matcher = Spectator::Matchers::CaseMatcher.new(array2) match_data = matcher.match(partial)
matcher.match?(partial).should be_false match_data.message.should contain("===")
end
it "contains the actual label" do
value = 42
label = "everything"
partial = new_partial(value, label)
matcher = Spectator::Matchers::CaseMatcher.new(value)
match_data = matcher.match(partial)
match_data.message.should contain(label)
end
it "contains the expected label" do
value = 42
label = "everything"
partial = new_partial(value)
matcher = Spectator::Matchers::CaseMatcher.new(value, label)
match_data = matcher.match(partial)
match_data.message.should contain(label)
end
context "when expected label is omitted" do
it "contains stringified form of expected value" do
value1 = 42
value2 = 777
partial = new_partial(value1)
matcher = Spectator::Matchers::CaseMatcher.new(value2)
match_data = matcher.match(partial)
match_data.message.should contain(value2.to_s)
end
end end
end end
context "with the same type" do describe "#negated_message" do
it "is true" do it "mentions ===" do
value1 = "foobar" value = 42
value2 = String partial = new_partial(value)
partial = new_partial(value1) matcher = Spectator::Matchers::CaseMatcher.new(value)
matcher = Spectator::Matchers::CaseMatcher.new(value2) match_data = matcher.match(partial)
matcher.match?(partial).should be_true match_data.negated_message.should contain("===")
end end
end
context "with a different type" do it "contains the actual label" do
it "is false" do value = 42
value1 = "foobar" label = "everything"
value2 = Array partial = new_partial(value, label)
partial = new_partial(value1) matcher = Spectator::Matchers::CaseMatcher.new(value)
matcher = Spectator::Matchers::CaseMatcher.new(value2) match_data = matcher.match(partial)
matcher.match?(partial).should be_false match_data.negated_message.should contain(label)
end end
end
end
end
describe "#message" do it "contains the expected label" do
it "mentions ===" do value = 42
value = 42 label = "everything"
partial = new_partial(value) partial = new_partial(value)
matcher = Spectator::Matchers::CaseMatcher.new(value) matcher = Spectator::Matchers::CaseMatcher.new(value, label)
matcher.message(partial).should contain("===") match_data = matcher.match(partial)
end match_data.negated_message.should contain(label)
end
it "contains the actual label" do context "when expected label is omitted" do
value = 42 it "contains stringified form of expected value" do
label = "everything" value1 = 42
partial = new_partial(value, label) value2 = 777
matcher = Spectator::Matchers::CaseMatcher.new(value) partial = new_partial(value1)
matcher.message(partial).should contain(label) matcher = Spectator::Matchers::CaseMatcher.new(value2)
end match_data = matcher.match(partial)
match_data.negated_message.should contain(value2.to_s)
it "contains the expected label" do end
value = 42 end
label = "everything"
partial = new_partial(value)
matcher = Spectator::Matchers::CaseMatcher.new(value, label)
matcher.message(partial).should contain(label)
end
context "when expected label is omitted" do
it "contains stringified form of expected value" do
value1 = 42
value2 = 777
partial = new_partial(value1)
matcher = Spectator::Matchers::CaseMatcher.new(value2)
matcher.message(partial).should contain(value2.to_s)
end
end
end
describe "#negated_message" do
it "mentions ===" do
value = 42
partial = new_partial(value)
matcher = Spectator::Matchers::CaseMatcher.new(value)
matcher.negated_message(partial).should contain("===")
end
it "contains the actual label" do
value = 42
label = "everything"
partial = new_partial(value, label)
matcher = Spectator::Matchers::CaseMatcher.new(value)
matcher.negated_message(partial).should contain(label)
end
it "contains the expected label" do
value = 42
label = "everything"
partial = new_partial(value)
matcher = Spectator::Matchers::CaseMatcher.new(value, label)
matcher.negated_message(partial).should contain(label)
end
context "when expected label is omitted" do
it "contains stringified form of expected value" do
value1 = 42
value2 = 777
partial = new_partial(value1)
matcher = Spectator::Matchers::CaseMatcher.new(value2)
matcher.negated_message(partial).should contain(value2.to_s)
end end
end end
end end

View file

@ -5,27 +5,43 @@ module Spectator::Matchers
# The values are compared with the === operator. # The values are compared with the === operator.
struct CaseMatcher(ExpectedType) < ValueMatcher(ExpectedType) struct CaseMatcher(ExpectedType) < ValueMatcher(ExpectedType)
# Determines whether the matcher is satisfied with the value given to it. # Determines whether the matcher is satisfied with the value given to it.
# True is returned if the match was successful, false otherwise. private def match?(actual)
def match?(partial) expected === actual
expected === partial.actual
end end
# Determines whether the matcher is satisfied with the partial given to it. # Determines whether the matcher is satisfied with the partial given to it.
# `MatchData` is returned that contains information about the match. # `MatchData` is returned that contains information about the match.
def match(partial) : MatchData def match(partial)
raise NotImplementedError.new("#match") values = ExpectedActual.new(partial, self)
MatchData.new(match?(values.actual), values)
end end
# Describes the condition that satisfies the matcher. # Match data specific to this matcher.
# This is informational and displayed to the end-user. private struct MatchData(ExpectedType, ActualType) < MatchData
def message(partial) # Creates the match data.
"Expected #{partial.label} to semantically equal #{label} (using ===)" def initialize(matched, @values : ExpectedActual(ExpectedType, ActualType))
end super(matched)
end
# Describes the condition that won't satsify the matcher. # Information about the match.
# This is informational and displayed to the end-user. def values
def negated_message(partial) {
"Expected #{partial.label} to not semantically equal #{label} (using ===)" expected: @values.expected,
actual: @values.actual,
}
end
# Describes the condition that satisfies the matcher.
# This is informational and displayed to the end-user.
def message
"#{@values.actual_label} equals #{@values.expected_label} (using ===)"
end
# Describes the condition that won't satsify the matcher.
# This is informational and displayed to the end-user.
def negated_message
"#{@values.actual_label} does not equal #{@values.expected_label} (using ===)"
end
end end
end end
end end