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)
|
def initialize(@match_data : Matchers::MatchData, @source : Source)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Indicates whether the matcher was satisified.
|
||||||
def satisfied?
|
def satisfied?
|
||||||
@match_data.matched?
|
@match_data.matched?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Indicates that the expectation was not satisified.
|
||||||
def failure?
|
def failure?
|
||||||
!satisfied?
|
!satisfied?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Description of why the match failed.
|
||||||
|
# If nil, then the match was successful.
|
||||||
def failure_message?
|
def failure_message?
|
||||||
@match_data.as?(Matchers::FailedMatchData).try(&.failure_message)
|
@match_data.as?(Matchers::FailedMatchData).try(&.failure_message)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Description of why the match failed.
|
||||||
def failure_message
|
def failure_message
|
||||||
failure_message?.not_nil!
|
failure_message?.not_nil!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Additional information about the match, useful for debug.
|
||||||
|
# If nil, then the match was successful.
|
||||||
def values?
|
def values?
|
||||||
@match_data.as?(Matchers::FailedMatchData).try(&.values)
|
@match_data.as?(Matchers::FailedMatchData).try(&.values)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Additional information about the match, useful for debug.
|
||||||
def values
|
def values
|
||||||
values?.not_nil!
|
values?.not_nil!
|
||||||
end
|
end
|
||||||
|
@ -47,6 +55,7 @@ module Spectator::Expectations
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Adds failure information to a JSON structure.
|
||||||
private def failed_to_json(failed : Matchers::FailedMatchData, json : ::JSON::Builder)
|
private def failed_to_json(failed : Matchers::FailedMatchData, json : ::JSON::Builder)
|
||||||
json.field("failure", failed.failure_message)
|
json.field("failure", failed.failure_message)
|
||||||
json.field("values") do
|
json.field("values") do
|
||||||
|
|
|
@ -12,10 +12,14 @@ module Spectator::Matchers
|
||||||
# it { is_expected.to do_something }
|
# it { is_expected.to do_something }
|
||||||
# ```
|
# ```
|
||||||
# The phrasing should be such that it reads "it ___."
|
# The phrasing should be such that it reads "it ___."
|
||||||
|
# where the blank is what is returned by this method.
|
||||||
abstract def description : String
|
abstract def description : String
|
||||||
|
|
||||||
|
# Actually performs the test against the expression (value or block).
|
||||||
abstract def match(actual : TestExpression(T)) : MatchData forall T
|
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
|
abstract def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,41 +5,103 @@ require "./successful_match_data"
|
||||||
|
|
||||||
module Spectator::Matchers
|
module Spectator::Matchers
|
||||||
# Provides common methods for 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
|
abstract struct StandardMatcher < Matcher
|
||||||
# Message displayed when the matcher isn't satisifed.
|
# 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.
|
# Message displayed when the matcher isn't satisifed and is negated.
|
||||||
|
#
|
||||||
# This is only called when `#does_not_match?` returns false.
|
# This is only called when `#does_not_match?` returns false.
|
||||||
#
|
#
|
||||||
# A default implementation of this method is provided,
|
# A default implementation of this method is provided,
|
||||||
# which causes compilation to fail.
|
# which causes compilation to fail.
|
||||||
# If the matcher supports negation, it must override this method.
|
# 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." %}
|
{% raise "Negation with #{@type.name} is not supported." %}
|
||||||
end
|
end
|
||||||
|
|
||||||
# Checks whether the matcher is satisifed.
|
# 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?`.
|
# 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?`.
|
# The default implementation of this method is to invert the result of `#match?`.
|
||||||
# If the matcher requires custom handling of negated matches,
|
# If the matcher requires custom handling of negated matches,
|
||||||
# then this method should be overriden.
|
# then this method should be overriden.
|
||||||
# Remember to override `#failure_message_when_negated` as well.
|
# 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)
|
!match?(actual)
|
||||||
end
|
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}
|
{actual: actual.value.inspect}
|
||||||
end
|
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)
|
values(actual)
|
||||||
end
|
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
|
def match(actual : TestExpression(T)) : MatchData forall T
|
||||||
if match?(actual)
|
if match?(actual)
|
||||||
SuccessfulMatchData.new
|
SuccessfulMatchData.new
|
||||||
|
@ -48,6 +110,13 @@ module Spectator::Matchers
|
||||||
end
|
end
|
||||||
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
|
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||||
if does_not_match?(actual)
|
if does_not_match?(actual)
|
||||||
SuccessfulMatchData.new
|
SuccessfulMatchData.new
|
||||||
|
|
|
@ -3,6 +3,18 @@ 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.
|
||||||
|
#
|
||||||
|
# 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
|
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.
|
||||||
|
@ -13,11 +25,42 @@ module Spectator::Matchers
|
||||||
def initialize(@expected : TestValue(ExpectedType))
|
def initialize(@expected : TestValue(ExpectedType))
|
||||||
end
|
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)
|
super.merge(expected: expected.value.inspect)
|
||||||
end
|
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}")
|
super.merge(expected: "Not #{expected.value.inspect}")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue