mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Rework how expectations and matchers work together
This commit is contained in:
parent
4948fe0c6f
commit
3035273e9a
12 changed files with 118 additions and 50 deletions
|
@ -9,7 +9,7 @@ module Spectator::DSL
|
|||
end
|
||||
|
||||
macro expect(actual)
|
||||
::Spectator::Expectation.new({{actual.stringify}}, {{actual}})
|
||||
::Spectator::Expectations::ValueExpectationPartial.new({{actual.stringify}}, {{actual}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
require "./matchers/matcher"
|
||||
|
||||
module Spectator
|
||||
class Expectation(T)
|
||||
getter actual : T
|
||||
|
||||
protected def label : String
|
||||
@label.empty? ? @actual.to_s : @label
|
||||
end
|
||||
|
||||
protected def initialize(@label : String, @actual : T)
|
||||
end
|
||||
|
||||
def to(matcher : Matchers::Matcher)
|
||||
unless matcher.match?(self)
|
||||
raise ExpectationFailed.new(matcher.message(self))
|
||||
end
|
||||
end
|
||||
|
||||
def to_not(matcher : Matchers::Matcher)
|
||||
if matcher.match?(self)
|
||||
raise ExpectationFailed.new(matcher.negated_message(self))
|
||||
end
|
||||
end
|
||||
|
||||
@[AlwaysInline]
|
||||
def not_to(matcher : Matchers::Matcher)
|
||||
to_not(matcher)
|
||||
end
|
||||
end
|
||||
end
|
7
src/spectator/expectations.cr
Normal file
7
src/spectator/expectations.cr
Normal file
|
@ -0,0 +1,7 @@
|
|||
require "./expectations/*"
|
||||
|
||||
module Spectator
|
||||
# Namespace that contains all expectations, partials, and handling of them.
|
||||
module Expectations
|
||||
end
|
||||
end
|
4
src/spectator/expectations/expectation.cr
Normal file
4
src/spectator/expectations/expectation.cr
Normal file
|
@ -0,0 +1,4 @@
|
|||
module Spectator::Expectations
|
||||
abstract class Expectation
|
||||
end
|
||||
end
|
22
src/spectator/expectations/expectation_partial.cr
Normal file
22
src/spectator/expectations/expectation_partial.cr
Normal file
|
@ -0,0 +1,22 @@
|
|||
module Spectator::Expectations
|
||||
# Base class for all expectation partials.
|
||||
# An "expectation partial" stores part of an expectation (obviously).
|
||||
# The part of the expectation this class covers is the actual value.
|
||||
# This can also cover a block's behavior.
|
||||
# Sub-types of this class are returned by the `DSL::ExampleDSL.expect` call.
|
||||
abstract class ExpectationPartial
|
||||
# User-friendly string displayed for the actual expression being tested.
|
||||
# For instance, in the expectation:
|
||||
# ```
|
||||
# expect(foo).to eq(bar)
|
||||
# ```
|
||||
# This property will be "foo".
|
||||
# It will be the literal string "foo",
|
||||
# and not the actual value of the foo.
|
||||
getter label : String
|
||||
|
||||
# Creates the base of the partial.
|
||||
private def initialize(@label)
|
||||
end
|
||||
end
|
||||
end
|
26
src/spectator/expectations/expectation_registry.cr
Normal file
26
src/spectator/expectations/expectation_registry.cr
Normal file
|
@ -0,0 +1,26 @@
|
|||
module Spectator::Expectations
|
||||
# Tracks the expectations and their outcomes in an example.
|
||||
# A single instance of this class should be associated with one example.
|
||||
class ExpectationRegistry
|
||||
private getter? raise_on_failure : Bool
|
||||
|
||||
private def initialize(@raise_on_failure = true)
|
||||
end
|
||||
|
||||
def report(expectation : Expectation) : Nil
|
||||
raise NotImplementedError.new("ExpectationRegistry#report")
|
||||
end
|
||||
|
||||
def self.current : ExpectationRegistry
|
||||
raise NotImplementedError.new("ExpectationRegistry.current")
|
||||
end
|
||||
|
||||
def self.start(example : Example) : ExpectationRegistry
|
||||
raise NotImplementedError.new("ExpectationRegistry.start")
|
||||
end
|
||||
|
||||
def self.finish : Nil # TODO: Define return type.
|
||||
raise NotImplementedError.new("ExpectationRegistry.finish")
|
||||
end
|
||||
end
|
||||
end
|
6
src/spectator/expectations/value_expectation.cr
Normal file
6
src/spectator/expectations/value_expectation.cr
Normal file
|
@ -0,0 +1,6 @@
|
|||
require "./expectation"
|
||||
|
||||
module Spectator::Expectations
|
||||
class ValueExpectation < Expectation
|
||||
end
|
||||
end
|
25
src/spectator/expectations/value_expectation_partial.cr
Normal file
25
src/spectator/expectations/value_expectation_partial.cr
Normal file
|
@ -0,0 +1,25 @@
|
|||
require "./expectation_partial"
|
||||
|
||||
module Spectator::Expectations
|
||||
class ValueExpectationPartial(ActualType) < ExpectationPartial
|
||||
getter actual
|
||||
|
||||
protected def initialize(label : String, @actual : ActualType)
|
||||
super(label)
|
||||
end
|
||||
|
||||
def to(matcher : Matchers::ValueMatcher(ExpectedType)) : Nil forall ExpectedType
|
||||
raise NotImplementedError.new("ValueExpectationPartial#to")
|
||||
end
|
||||
|
||||
def to_not(matcher : Matchers::ValueMatcher(ExpectedType)) : Nil forall ExpectedType
|
||||
raise NotImplementedError.new("ValueExpectationPartial#to_not")
|
||||
end
|
||||
|
||||
# ditto
|
||||
@[AlwaysInline]
|
||||
def not_to(matcher : Matchers::ValueMatcher(ExpectedType)) : Nil forall ExpectedType
|
||||
to_not(matcher)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,6 +7,7 @@
|
|||
# First the sub-modules.
|
||||
require "./internals"
|
||||
require "./dsl"
|
||||
require "./expectations"
|
||||
require "./matchers"
|
||||
require "./formatters"
|
||||
|
||||
|
@ -18,7 +19,6 @@ require "./pending_example"
|
|||
require "./example_hooks"
|
||||
require "./example_group"
|
||||
|
||||
require "./expectation"
|
||||
require "./expectation_failed"
|
||||
require "./test_results"
|
||||
require "./runner"
|
||||
|
|
|
@ -1,21 +1,17 @@
|
|||
require "./matcher"
|
||||
require "./value_matcher"
|
||||
|
||||
module Spectator::Matchers
|
||||
class EqualityMatcher(T) < Matcher
|
||||
def initialize(label, @expected : T)
|
||||
super(label)
|
||||
class EqualityMatcher(ExpectedType) < ValueMatcher(ExpectedType)
|
||||
def match?(partial : ValueExpectationPartial(ActualType)) : Bool forall ActualType
|
||||
partial.actual == expected
|
||||
end
|
||||
|
||||
def match?(expectation : Expectation)
|
||||
expectation.actual == @expected
|
||||
def message(partial : ValueExpectationPartial(ActualType)) : String forall ActualType
|
||||
"Expected #{partial.label} to equal #{label} (using ==)"
|
||||
end
|
||||
|
||||
def message(expectation : Expectation) : String
|
||||
"Expected #{expectation.label} to equal #{label} (using ==)"
|
||||
end
|
||||
|
||||
def negated_message(expectation : Expectation) : String
|
||||
"Expected #{expectation.label} to not equal #{label} (using ==)"
|
||||
def negated_message(partial : ValueExpectationPartial(ActualType)) : String forall ActualType
|
||||
"Expected #{partial.label} to not equal #{label} (using ==)"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -2,11 +2,7 @@ module Spectator::Matchers
|
|||
abstract class Matcher
|
||||
private getter label : String
|
||||
|
||||
private def initialize(@label : String)
|
||||
private def initialize(@label)
|
||||
end
|
||||
|
||||
abstract def match?(expectation : Expectation)
|
||||
abstract def message(expectation : Expectation) : String
|
||||
abstract def negated_message(expectation : Expectation) : String
|
||||
end
|
||||
end
|
||||
|
|
17
src/spectator/matchers/value_matcher.cr
Normal file
17
src/spectator/matchers/value_matcher.cr
Normal file
|
@ -0,0 +1,17 @@
|
|||
require "./matcher"
|
||||
|
||||
module Spectator::Matchers
|
||||
abstract class ValueMatcher(ExpectedType) < Matcher
|
||||
private getter expected
|
||||
|
||||
def initialize(label : String, @expected : ExpectedType)
|
||||
super(label)
|
||||
end
|
||||
|
||||
abstract def match?(partial : ValueExpectationPartial(ActualType)) : Bool forall ActualType
|
||||
|
||||
abstract def message(partial : ValueExpectationPartial(ActualType)) : String forall ActualType
|
||||
|
||||
abstract def negated_message(partial : ValueExpectationPartial(ActualType)) : String forall ActualType
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue