mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Add relative change matcher
This commit is contained in:
parent
c19f442e6c
commit
4e15487a0f
2 changed files with 73 additions and 0 deletions
|
@ -7,6 +7,7 @@ require "./successful_match_data"
|
|||
module Spectator::Matchers
|
||||
# Matcher that tests whether an expression changed.
|
||||
struct ChangeMatcher(ExpressionType) < Matcher
|
||||
# The expression that is expected to (not) change.
|
||||
private getter expression
|
||||
|
||||
# Creates a new change matcher.
|
||||
|
@ -57,6 +58,21 @@ module Spectator::Matchers
|
|||
ChangeToMatcher.new(@expression, value)
|
||||
end
|
||||
|
||||
# Specifies that t he resulting value must be some amount different.
|
||||
def by(amount : T) forall T
|
||||
ChangeRelativeMatcher.new(@expression, "by #{amount}") { |before, after| amount == after - before }
|
||||
end
|
||||
|
||||
# Specifies that the resulting value must be at least some amount different.
|
||||
def by_at_least(minimum : T) forall T
|
||||
ChangeRelativeMatcher.new(@expression, "by at least #{minimum}") { |before, after| minimum <= after - before }
|
||||
end
|
||||
|
||||
# Specifies that the resulting value must be at most some amount different.
|
||||
def by_at_most(maximum : T) forall T
|
||||
ChangeRelativeMatcher.new(@expression, "by at most #{maximum}") { |before, after| maximum >= after - before }
|
||||
end
|
||||
|
||||
# Performs the change and reports the before and after values.
|
||||
private def change(actual)
|
||||
before = expression.value # Retrieve the expression's initial value.
|
||||
|
|
57
src/spectator/matchers/change_relative_matcher.cr
Normal file
57
src/spectator/matchers/change_relative_matcher.cr
Normal file
|
@ -0,0 +1,57 @@
|
|||
require "./failed_match_data"
|
||||
require "./matcher"
|
||||
require "./successful_match_data"
|
||||
|
||||
module Spectator::Matchers
|
||||
# Matcher that tests whether an expression changed by an amount.
|
||||
struct ChangeRelativeMatcher(ExpressionType) < Matcher
|
||||
# The expression that is expected to (not) change.
|
||||
private getter expression
|
||||
|
||||
# Creates a new change matcher.
|
||||
def initialize(@expression : TestBlock(ExpressionType), @relativity : String,
|
||||
&evaluator : ExpressionType, ExpressionType -> Bool)
|
||||
@evaluator = evaluator
|
||||
end
|
||||
|
||||
# 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
|
||||
"changes #{expression.label} #{@relativity}"
|
||||
end
|
||||
|
||||
# Actually performs the test against the expression.
|
||||
def match(actual : TestExpression(T)) : MatchData forall T
|
||||
before, after = change(actual)
|
||||
if before == after
|
||||
FailedMatchData.new("#{actual.label} did not change #{expression.label}",
|
||||
before: before.inspect,
|
||||
after: after.inspect
|
||||
)
|
||||
elsif @evaluator.call(before, after)
|
||||
SuccessfulMatchData.new
|
||||
else
|
||||
FailedMatchData.new("#{actual.label} did not change #{expression.label} #{@relativity}",
|
||||
before: before.inspect,
|
||||
after: after.inspect
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Performs the test against the expression, but inverted.
|
||||
# A successful match with `#match` should normally fail for this method, and vice-versa.
|
||||
def negated_match(actual : TestExpression(T)) : MatchData forall T
|
||||
{% raise "The `expect { }.to_not change { }.by_...()` syntax is not supported (ambiguous)." %}
|
||||
end
|
||||
|
||||
# Performs the change and reports the before and after values.
|
||||
private def change(actual)
|
||||
before = expression.value # Retrieve the expression's initial value.
|
||||
actual.value # Invoke action that might change the expression's value.
|
||||
after = expression.value # Retrieve the expression's value again.
|
||||
|
||||
{before, after}
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue