mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Add docs and some more type annotations
This commit is contained in:
parent
db4eaca291
commit
39f253952d
4 changed files with 134 additions and 9 deletions
|
@ -12,26 +12,34 @@ module Spectator::Expectations
|
|||
def initialize(@match_data : Matchers::MatchData, @source : Source)
|
||||
end
|
||||
|
||||
# Indicates whether the matcher was satisified.
|
||||
def satisfied?
|
||||
@match_data.matched?
|
||||
end
|
||||
|
||||
# Indicates that the expectation was not satisified.
|
||||
def failure?
|
||||
!satisfied?
|
||||
end
|
||||
|
||||
# Description of why the match failed.
|
||||
# If nil, then the match was successful.
|
||||
def failure_message?
|
||||
@match_data.as?(Matchers::FailedMatchData).try(&.failure_message)
|
||||
end
|
||||
|
||||
# Description of why the match failed.
|
||||
def failure_message
|
||||
failure_message?.not_nil!
|
||||
end
|
||||
|
||||
# Additional information about the match, useful for debug.
|
||||
# If nil, then the match was successful.
|
||||
def values?
|
||||
@match_data.as?(Matchers::FailedMatchData).try(&.values)
|
||||
end
|
||||
|
||||
# Additional information about the match, useful for debug.
|
||||
def values
|
||||
values?.not_nil!
|
||||
end
|
||||
|
@ -47,6 +55,7 @@ module Spectator::Expectations
|
|||
end
|
||||
end
|
||||
|
||||
# Adds failure information to a JSON structure.
|
||||
private def failed_to_json(failed : Matchers::FailedMatchData, json : ::JSON::Builder)
|
||||
json.field("failure", failed.failure_message)
|
||||
json.field("values") do
|
||||
|
|
|
@ -12,10 +12,14 @@ module Spectator::Matchers
|
|||
# it { is_expected.to do_something }
|
||||
# ```
|
||||
# The phrasing should be such that it reads "it ___."
|
||||
# where the blank is what is returned by this method.
|
||||
abstract def description : String
|
||||
|
||||
# Actually performs the test against the expression (value or block).
|
||||
abstract def match(actual : TestExpression(T)) : MatchData forall T
|
||||
|
||||
# Performs the test against the expression (value or block), but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
abstract def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,41 +5,103 @@ require "./successful_match_data"
|
|||
|
||||
module Spectator::Matchers
|
||||
# Provides common methods for matchers.
|
||||
#
|
||||
# The `#match` and `#negated_match` methods have an implementation
|
||||
# that is suitable for most matchers.
|
||||
# Matchers based on this class need to define `#match?` and `#failure_message`.
|
||||
# If the matcher can be negated,
|
||||
# the `#failure_message_when_negated` method needs to be overriden.
|
||||
# Additionally, the `#does_not_match?` method can be specified
|
||||
# if there's custom behavior for negated matches.
|
||||
# If the matcher operates on or has extra data that is useful for debug,
|
||||
# then the `#values` and `#negated_values` methods can be overriden.
|
||||
# Finally, define a `#description` message that can be used for the one-liner "it" syntax.
|
||||
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
|
||||
#
|
||||
# This is only called when `#match?` returns false.
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private abstract def failure_message(actual : TestExpression(T)) : String forall T
|
||||
|
||||
# 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
|
||||
#
|
||||
# The message should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values`.
|
||||
private def failure_message_when_negated(actual : TestExpression(T)) : String forall T
|
||||
{% raise "Negation with #{@type.name} is not supported." %}
|
||||
end
|
||||
|
||||
# Checks whether the matcher is satisifed.
|
||||
private abstract def match?(actual) : Bool
|
||||
private abstract def match?(actual : TestExpression(T)) : Bool forall T
|
||||
|
||||
# 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
|
||||
private def does_not_match?(actual : TestExpression(T)) : Bool forall T
|
||||
!match?(actual)
|
||||
end
|
||||
|
||||
private def values(actual)
|
||||
# Additional information about the match failure.
|
||||
#
|
||||
# By default, just the actual value is produced.
|
||||
# The return value must be a NamedTuple with Strings for each value.
|
||||
# The tuple can be of any size,
|
||||
# but the keys must be known at compile-time (as Symbols),
|
||||
# and the values must be strings.
|
||||
# Generally, the string values are produced by calling `#inspect` on the relevant object.
|
||||
# It should look like this:
|
||||
# ```
|
||||
# {
|
||||
# expected: "foo",
|
||||
# actual: "bar",
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# The values should typically only contain the test expression values, not the labels.
|
||||
# Labeled should be returned by `#failure_message`.
|
||||
private def values(actual : TestExpression(T)) forall T
|
||||
{actual: actual.value.inspect}
|
||||
end
|
||||
|
||||
private def negated_values(actual)
|
||||
# Additional information about the match failure when negated.
|
||||
#
|
||||
# By default, just the actual value is produced (same as `#values`).
|
||||
# The return value must be a NamedTuple with Strings for each value.
|
||||
# The tuple can be of any size,
|
||||
# but the keys must be known at compile-time (as Symbols),
|
||||
# and the values must be strings.
|
||||
# Generally, the string values are produced by calling `#inspect` on the relevant object.
|
||||
# It should look like this:
|
||||
# ```
|
||||
# {
|
||||
# expected: "Not foo",
|
||||
# actual: "bar",
|
||||
# }
|
||||
# ```
|
||||
#
|
||||
# The values should typically only contain the test expression values, not the labels.
|
||||
# Labeled should be returned by `#failure_message_when_negated`.
|
||||
private def negated_values(actual : TestExpression(T)) forall T
|
||||
values(actual)
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression (value or block).
|
||||
#
|
||||
# This method calls the abstract `#match?` method.
|
||||
# If it returns true, then a `SuccessfulMatchData` instance is returned.
|
||||
# Otherwise, a `FailedMatchData` instance is returned.
|
||||
# Additionally, `#failure_message` and `#values` are called for a failed match.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
if match?(actual)
|
||||
SuccessfulMatchData.new
|
||||
|
@ -48,6 +110,13 @@ module Spectator::Matchers
|
|||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression (value or block), but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
#
|
||||
# This method calls the abstract `#does_not_match?` method.
|
||||
# If it returns true, then a `SuccessfulMatchData` instance is returned.
|
||||
# Otherwise, a `FailedMatchData` instance is returned.
|
||||
# Additionally, `#failure_message_when_negated` and `#negated_values` are called for a failed match.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
if does_not_match?(actual)
|
||||
SuccessfulMatchData.new
|
||||
|
|
|
@ -3,6 +3,18 @@ require "./standard_matcher"
|
|||
module Spectator::Matchers
|
||||
# Category of matcher that uses a value.
|
||||
# Matchers of this type expect that a SUT applies to the value in some way.
|
||||
#
|
||||
# Matchers based on this class need to define `#match?` and `#failure_message`.
|
||||
# If the matcher can be negated,
|
||||
# the `#failure_message_when_negated` method needs to be overriden.
|
||||
# Additionally, the `#does_not_match?` method can be specified
|
||||
# if there's custom behavior for negated matches.
|
||||
# If the matcher operates on or has extra data that is useful for debug,
|
||||
# then the `#values` and `#negated_values` methods can be overriden.
|
||||
# Finally, define a `#description` message that can be used for the one-liner "it" syntax.
|
||||
#
|
||||
# The failure messages should typically only contain the test expression labels.
|
||||
# Actual values should be returned by `#values` and `#negated_values`.
|
||||
abstract struct ValueMatcher(ExpectedType) < StandardMatcher
|
||||
# Expected value.
|
||||
# Sub-types may use this value to test the expectation and generate message strings.
|
||||
|
@ -13,11 +25,42 @@ module Spectator::Matchers
|
|||
def initialize(@expected : TestValue(ExpectedType))
|
||||
end
|
||||
|
||||
private def values(actual)
|
||||
# Additional information about the match failure.
|
||||
#
|
||||
# By default, just the actual and expected values are produced.
|
||||
# The return value must be a NamedTuple with Strings for each value.
|
||||
# The tuple can be of any size,
|
||||
# but the keys must be known at compile-time (as Symbols),
|
||||
# and the values must be strings.
|
||||
# Generally, the string values are produced by calling `#inspect` on the relevant object.
|
||||
# It should look like this:
|
||||
# ```
|
||||
# {
|
||||
# expected: "foo",
|
||||
# actual: "bar",
|
||||
# }
|
||||
# ```
|
||||
private def values(actual : TestExpression(T)) forall T
|
||||
super.merge(expected: expected.value.inspect)
|
||||
end
|
||||
|
||||
private def negated_values(actual)
|
||||
# Additional information about the match failure when negated.
|
||||
#
|
||||
# By default, just the actual and expected values are produced (same as `#values`).
|
||||
# However, the expected value is prefixed with the word "Not".
|
||||
# The return value must be a NamedTuple with Strings for each value.
|
||||
# The tuple can be of any size,
|
||||
# but the keys must be known at compile-time (as Symbols),
|
||||
# and the values must be strings.
|
||||
# Generally, the string values are produced by calling `#inspect` on the relevant object.
|
||||
# It should look like this:
|
||||
# ```
|
||||
# {
|
||||
# expected: "Not foo",
|
||||
# actual: "bar",
|
||||
# }
|
||||
# ```
|
||||
private def negated_values(actual : TestExpression(T)) forall T
|
||||
super.merge(expected: "Not #{expected.value.inspect}")
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue