Insert StandardMatcher into Matcher hierarchy

This is to remove all the unused abstract methods.
This commit is contained in:
Michael Miller 2019-08-06 22:33:13 -06:00
parent ab147d00fb
commit e7b19ee591
4 changed files with 77 additions and 74 deletions

View File

@ -1,30 +1,22 @@
require "./value_matcher" require "../test_value"
require "./failed_match_data"
require "./matcher"
require "./successful_match_data"
require "./unordered_array_matcher" require "./unordered_array_matcher"
module Spectator::Matchers module Spectator::Matchers
# Matcher for checking that the contents of one array (or similar type) # Matcher for checking that the contents of one array (or similar type)
# has the exact same contents as another and in the same order. # has the exact same contents as another and in the same order.
struct ArrayMatcher(ExpectedType) < ValueMatcher(Enumerable(ExpectedType)) struct ArrayMatcher(ExpectedType) < Matcher
private getter expected : TestValue(ExpectedType)
def initialize(@expected)
end
def description def description
"contains exactly #{expected.label}" "contains exactly #{expected.label}"
end end
private def failure_message(actual)
{% raise "This method should never be called" %}
end
private def failure_message_when_negated(actual)
{% raise "This method should never be called" %}
end
private def match?(actual)
{% raise "This method should never be called" %}
end
private def does_not_match?(actual)
{% raise "This method should never be called" %}
end
def match(actual) def match(actual)
actual_elements = actual.value.to_a actual_elements = actual.value.to_a
expected_elements = expected.value.to_a expected_elements = expected.value.to_a
@ -67,7 +59,7 @@ module Spectator::Matchers
end end
end end
def failed_size_mismatch(expected_elements, actual_elements, actual_label) private def failed_size_mismatch(expected_elements, actual_elements, actual_label)
FailedMatchData.new("#{actual_label} does not contain exactly #{expected.label} (size mismatch)", FailedMatchData.new("#{actual_label} does not contain exactly #{expected.label} (size mismatch)",
[ [
LabeledValue.new(expected_elements.inspect, "expected"), LabeledValue.new(expected_elements.inspect, "expected"),
@ -77,7 +69,7 @@ module Spectator::Matchers
]) ])
end end
def failed_content_mismatch(expected_elements, actual_elements, index, actual_label) private def failed_content_mismatch(expected_elements, actual_elements, index, actual_label)
FailedMatchData.new("#{actual_label} does not contain exactly #{expected.label} (element mismatch)", FailedMatchData.new("#{actual_label} does not contain exactly #{expected.label} (element mismatch)",
[ [
LabeledValue.new(expected_elements[index].inspect, "expected"), LabeledValue.new(expected_elements[index].inspect, "expected"),
@ -86,7 +78,7 @@ module Spectator::Matchers
]) ])
end end
def failed_content_identical(expected_elements, actual_elements, actual_label) private def failed_content_identical(expected_elements, actual_elements, actual_label)
FailedMatchData.new("#{actual.label} contains exactly #{expected.label}", FailedMatchData.new("#{actual.label} contains exactly #{expected.label}",
[ [
LabeledValue.new("Not #{expected_elements.inspect}", "expected"), LabeledValue.new("Not #{expected_elements.inspect}", "expected"),

View File

@ -1,6 +1,4 @@
require "../test_value" require "./match_data"
require "./failed_match_data"
require "./successful_match_data"
module Spectator::Matchers module Spectator::Matchers
# Common base class for all expectation conditions. # Common base class for all expectation conditions.
@ -16,54 +14,8 @@ module Spectator::Matchers
# The phrasing should be such that it reads "it ___." # The phrasing should be such that it reads "it ___."
abstract def description : String abstract def description : String
# Message displayed when the matcher isn't satisifed. abstract def match(actual) : MatchData
# This is only called when `#matches?` returns false.
private abstract def failure_message(actual) : String
# Message displayed when the matcher isn't satisifed and is negated. abstract def negated_match(actual) : MatchData
# This is only called when `#does_not_match?` returns false.
#
# A default implementation of this method is provided,
# which causes compilation to fail.
# If the matcher supports negation, it must override this method.
private def failure_message_when_negated(actual) : String
{% raise "Negation with #{@type.name} is not supported." %}
end
# Checks whether the matcher is satisifed.
private abstract def match?(actual) : Bool
# If the expectation is negated, then this method is called instead of `#match?`.
# The default implementation of this method is to invert the result of `#match?`.
# If the matcher requires custom handling of negated matches,
# then this method should be overriden.
# Remember to override `#failure_message_when_negated` as well.
private def does_not_match?(actual) : Bool
!matches?(actual)
end
private def values(actual) : Array(LabeledValue)
[LabeledValue.new(actual.value.inspect, "actual")]
end
private def negated_values(actual) : Array(LabeledValue)
values
end
def match(actual)
if match?(actual)
SuccessfulMatchData.new
else
FailedMatchData.new(failure_message(actual), values(actual))
end
end
def negated_match(actual)
if does_not_match?(actual)
SuccessfulMatchData.new
else
FailedMatchData.new(failure_message_when_negated(actual), negated_values(actual))
end
end
end end
end end

View File

@ -0,0 +1,59 @@
require "../test_value"
require "./failed_match_data"
require "./matcher"
require "./successful_match_data"
module Spectator::Matchers
# Provides common methods for matchers.
abstract struct StandardMatcher < Matcher
# Message displayed when the matcher isn't satisifed.
# This is only called when `#matches?` returns false.
private abstract def failure_message(actual) : String
# Message displayed when the matcher isn't satisifed and is negated.
# This is only called when `#does_not_match?` returns false.
#
# A default implementation of this method is provided,
# which causes compilation to fail.
# If the matcher supports negation, it must override this method.
private def failure_message_when_negated(actual) : String
{% raise "Negation with #{@type.name} is not supported." %}
end
# Checks whether the matcher is satisifed.
private abstract def match?(actual) : Bool
# If the expectation is negated, then this method is called instead of `#match?`.
# The default implementation of this method is to invert the result of `#match?`.
# If the matcher requires custom handling of negated matches,
# then this method should be overriden.
# Remember to override `#failure_message_when_negated` as well.
private def does_not_match?(actual) : Bool
!matches?(actual)
end
private def values(actual) : Array(LabeledValue)
[LabeledValue.new(actual.value.inspect, "actual")]
end
private def negated_values(actual) : Array(LabeledValue)
values
end
def match(actual)
if match?(actual)
SuccessfulMatchData.new
else
FailedMatchData.new(failure_message(actual), values(actual))
end
end
def negated_match(actual)
if does_not_match?(actual)
SuccessfulMatchData.new
else
FailedMatchData.new(failure_message_when_negated(actual), negated_values(actual))
end
end
end
end

View File

@ -1,9 +1,9 @@
require "./matcher" require "./standard_matcher"
module Spectator::Matchers module Spectator::Matchers
# Category of matcher that uses a value. # Category of matcher that uses a value.
# Matchers of this type expect that a SUT applies to the value in some way. # Matchers of this type expect that a SUT applies to the value in some way.
abstract struct ValueMatcher(ExpectedType) < Matcher abstract struct ValueMatcher(ExpectedType) < StandardMatcher
# Expected value. # Expected value.
# Sub-types may use this value to test the expectation and generate message strings. # Sub-types may use this value to test the expectation and generate message strings.
private getter expected : TestValue(ExpectedType) private getter expected : TestValue(ExpectedType)