mirror of
https://gitea.invidious.io/iv-org/shard-spectator.git
synced 2024-08-15 00:53:35 +00:00
Rework result types
This commit is contained in:
parent
788b12a8bc
commit
4462f27316
10 changed files with 89 additions and 188 deletions
18
src/spectator/error_result.cr
Normal file
18
src/spectator/error_result.cr
Normal file
|
@ -0,0 +1,18 @@
|
|||
require "./fail_result"
|
||||
|
||||
module Spectator
|
||||
# Outcome that indicates running an example generated an error.
|
||||
# This occurs when an unexpected exception was raised while running an example.
|
||||
# This is different from a "failed" result in that the error was not from a failed assertion.
|
||||
class ErrorResult < FailResult
|
||||
# Calls the `error` method on *visitor*.
|
||||
def accept(visitor)
|
||||
visitor.error
|
||||
end
|
||||
|
||||
# One-word description of the result.
|
||||
def to_s(io)
|
||||
io << "error"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,50 +0,0 @@
|
|||
require "./failed_result"
|
||||
|
||||
module Spectator
|
||||
# Outcome that indicates running an example generated an error.
|
||||
# This type of result occurs when an exception was raised.
|
||||
# This is different from a "failed" result
|
||||
# in that the error was not from a failed expectation.
|
||||
class ErroredResult < FailedResult
|
||||
# Calls the `error` method on *interface*.
|
||||
def call(interface)
|
||||
interface.error
|
||||
end
|
||||
|
||||
# Calls the `error` method on *interface*
|
||||
# and passes the yielded value.
|
||||
def call(interface)
|
||||
value = yield self
|
||||
interface.error(value)
|
||||
end
|
||||
|
||||
# One-word descriptor of the result.
|
||||
def to_s(io)
|
||||
io << "error"
|
||||
end
|
||||
|
||||
# Adds the common JSON fields for all result types
|
||||
# and fields specific to errored results.
|
||||
private def add_json_fields(json : ::JSON::Builder)
|
||||
super
|
||||
json.field("exceptions") do
|
||||
exception = error
|
||||
json.array do
|
||||
while exception
|
||||
error_to_json(exception, json) if exception
|
||||
exception = error.cause
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Adds a single exception to a JSON builder.
|
||||
private def error_to_json(error : Exception, json : ::JSON::Builder)
|
||||
json.object do
|
||||
json.field("type", error.class.to_s)
|
||||
json.field("message", error.message)
|
||||
json.field("backtrace", error.backtrace)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,6 +1,8 @@
|
|||
require "./example_context_delegate"
|
||||
require "./example_group"
|
||||
require "./example_node"
|
||||
require "./pass_result"
|
||||
require "./pending_result"
|
||||
require "./result"
|
||||
require "./source"
|
||||
|
||||
|
@ -11,8 +13,7 @@ module Spectator
|
|||
getter? finished : Bool = false
|
||||
|
||||
# Retrieves the result of the last time the example ran.
|
||||
# TODO: Make result not nil and default to pending.
|
||||
getter! result : Result
|
||||
getter result : Result = PendingResult.new
|
||||
|
||||
# Creates the example.
|
||||
# The *delegate* contains the test context and method that runs the test case.
|
||||
|
@ -30,8 +31,11 @@ module Spectator
|
|||
# The result will also be stored in `#result`.
|
||||
def run : Result
|
||||
Log.debug { "Running example #{self}" }
|
||||
elapsed = Time.measure do
|
||||
@delegate.call(self)
|
||||
raise NotImplementedError.new("#run")
|
||||
end
|
||||
@finished = true
|
||||
@result = PassResult.new(elapsed)
|
||||
end
|
||||
|
||||
# Exposes information about the example useful for debugging.
|
||||
|
@ -47,7 +51,7 @@ module Spectator
|
|||
io << s
|
||||
end
|
||||
|
||||
# TODO: Add result.
|
||||
io << result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
28
src/spectator/fail_result.cr
Normal file
28
src/spectator/fail_result.cr
Normal file
|
@ -0,0 +1,28 @@
|
|||
require "./result"
|
||||
|
||||
module Spectator
|
||||
# Outcome that indicates an example failed.
|
||||
# This typically means an assertion did not pass.
|
||||
class FailResult < Result
|
||||
# Error that occurred while running the example.
|
||||
# This describes the primary reason for the failure.
|
||||
getter error : Exception
|
||||
|
||||
# Creates a failure result.
|
||||
# The *elapsed* argument is the length of time it took to run the example.
|
||||
# The *error* is the exception raised that caused the failure.
|
||||
def initialize(elapsed, @error)
|
||||
super(elapsed)
|
||||
end
|
||||
|
||||
# Calls the `failure` method on *visitor*.
|
||||
def accept(visitor)
|
||||
visitor.failure
|
||||
end
|
||||
|
||||
# One-word description of the result.
|
||||
def to_s(io)
|
||||
io << "fail"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,42 +0,0 @@
|
|||
require "./finished_result"
|
||||
|
||||
module Spectator
|
||||
# Outcome that indicates running an example was a failure.
|
||||
class FailedResult < FinishedResult
|
||||
# Error that occurred while running the example.
|
||||
getter error : Exception
|
||||
|
||||
# Creates a failed result.
|
||||
# The *example* should refer to the example that was run
|
||||
# and that this result is for.
|
||||
# The *elapsed* argument is the length of time it took to run the example.
|
||||
# The *expectations* references the expectations that were checked in the example.
|
||||
# The *error* is the exception that was raised to cause the failure.
|
||||
def initialize(example, elapsed, expectations, @error)
|
||||
super(example, elapsed, expectations)
|
||||
end
|
||||
|
||||
# Calls the `failure` method on *interface*.
|
||||
def call(interface)
|
||||
interface.failure
|
||||
end
|
||||
|
||||
# Calls the `failure` method on *interface*
|
||||
# and passes the yielded value.
|
||||
def call(interface)
|
||||
value = yield self
|
||||
interface.failure(value)
|
||||
end
|
||||
|
||||
# One-word descriptor of the result.
|
||||
def to_s(io)
|
||||
io << "fail"
|
||||
end
|
||||
|
||||
# Adds all of the JSON fields for finished results and failed results.
|
||||
private def add_json_fields(json : ::JSON::Builder)
|
||||
super
|
||||
json.field("error", error.message)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,29 +0,0 @@
|
|||
require "./result"
|
||||
|
||||
module Spectator
|
||||
# Abstract class for all results by examples
|
||||
abstract class FinishedResult < Result
|
||||
# Length of time it took to run the example.
|
||||
getter elapsed : Time::Span
|
||||
|
||||
# The expectations that were run in the example.
|
||||
getter expectations : Expectations::ExampleExpectations
|
||||
|
||||
# Creates a successful result.
|
||||
# The *example* should refer to the example that was run
|
||||
# and that this result is for.
|
||||
# The *elapsed* argument is the length of time it took to run the example.
|
||||
# The *expectations* references the expectations that were checked in the example.
|
||||
def initialize(example, @elapsed, @expectations)
|
||||
super(example)
|
||||
end
|
||||
|
||||
# Adds the common JSON fields for all result types
|
||||
# and fields specific to finished results.
|
||||
private def add_json_fields(json : ::JSON::Builder)
|
||||
super
|
||||
json.field("time", elapsed.total_seconds)
|
||||
json.field("expectations", expectations)
|
||||
end
|
||||
end
|
||||
end
|
16
src/spectator/pass_result.cr
Normal file
16
src/spectator/pass_result.cr
Normal file
|
@ -0,0 +1,16 @@
|
|||
require "./result"
|
||||
|
||||
module Spectator
|
||||
# Outcome that indicates running an example was successful.
|
||||
class PassResult < Result
|
||||
# Calls the `pass` method on *visitor*.
|
||||
def accept(visitor)
|
||||
visitor.pass
|
||||
end
|
||||
|
||||
# One-word description of the result.
|
||||
def to_s(io)
|
||||
io << "pass"
|
||||
end
|
||||
end
|
||||
end
|
|
@ -5,19 +5,18 @@ module Spectator
|
|||
# A pending result means the example is not ready to run yet.
|
||||
# This can happen when the functionality to be tested is not implemented yet.
|
||||
class PendingResult < Result
|
||||
# Calls the `pending` method on *interface*.
|
||||
def call(interface)
|
||||
interface.pending
|
||||
# Creates the result.
|
||||
# *elapsed* is the length of time it took to run the example.
|
||||
def initialize(elapsed = Time::Span::ZERO)
|
||||
super
|
||||
end
|
||||
|
||||
# Calls the `pending` method on *interface*
|
||||
# and passes the yielded value.
|
||||
def call(interface)
|
||||
value = yield self
|
||||
interface.pending(value)
|
||||
# Calls the `pending` method on the *visitor*.
|
||||
def accept(visitor)
|
||||
visitor.pending
|
||||
end
|
||||
|
||||
# One-word descriptor of the result.
|
||||
# One-word description of the result.
|
||||
def to_s(io)
|
||||
io << "pending"
|
||||
end
|
||||
|
|
|
@ -2,39 +2,19 @@ module Spectator
|
|||
# Base class that represents the outcome of running an example.
|
||||
# Sub-classes contain additional information specific to the type of result.
|
||||
abstract class Result
|
||||
# Example that was run that this result is for.
|
||||
getter example : Example
|
||||
# Length of time it took to run the example.
|
||||
getter elapsed : Time::Span
|
||||
|
||||
# Constructs the base of the result.
|
||||
# The *example* should refer to the example that was run
|
||||
# and that this result is for.
|
||||
def initialize(@example)
|
||||
# The assertions checked in the example.
|
||||
# getter assertions : Enumerable(Assertion) # TODO: Implement Assertion type.
|
||||
|
||||
# Creates the result.
|
||||
# *elapsed* is the length of time it took to run the example.
|
||||
def initialize(@elapsed)
|
||||
end
|
||||
|
||||
# Calls the corresponding method for the type of result.
|
||||
# This is used to avoid placing if or case-statements everywhere based on type.
|
||||
# Each sub-class implements this method by calling the correct method on *interface*.
|
||||
abstract def call(interface)
|
||||
|
||||
# Calls the corresponding method for the type of result.
|
||||
# This is used to avoid placing if or case-statements everywhere based on type.
|
||||
# Each sub-class implements this method by calling the correct method on *interface*.
|
||||
# This variation takes a block, which is passed the result.
|
||||
# The value returned from the block will be returned by this method.
|
||||
abstract def call(interface, &block : Result -> _)
|
||||
|
||||
# Creates a JSON object from the result information.
|
||||
def to_json(json : ::JSON::Builder)
|
||||
json.object do
|
||||
add_json_fields(json)
|
||||
end
|
||||
end
|
||||
|
||||
# Adds the common fields for a result to a JSON builder.
|
||||
private def add_json_fields(json : ::JSON::Builder)
|
||||
json.field("name", example)
|
||||
json.field("location", example.source)
|
||||
json.field("result", to_s)
|
||||
end
|
||||
# This is the visitor design pattern.
|
||||
abstract def accept(visitor)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
require "./finished_result"
|
||||
|
||||
module Spectator
|
||||
# Outcome that indicates running an example was successful.
|
||||
class SuccessfulResult < FinishedResult
|
||||
# Calls the `success` method on *interface*.
|
||||
def call(interface)
|
||||
interface.success
|
||||
end
|
||||
|
||||
# Calls the `success` method on *interface*
|
||||
# and passes the yielded value.
|
||||
def call(interface)
|
||||
value = yield self
|
||||
interface.success(value)
|
||||
end
|
||||
|
||||
# One-word descriptor of the result.
|
||||
def to_s(io)
|
||||
io << "success"
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue