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_context_delegate"
|
||||||
require "./example_group"
|
require "./example_group"
|
||||||
require "./example_node"
|
require "./example_node"
|
||||||
|
require "./pass_result"
|
||||||
|
require "./pending_result"
|
||||||
require "./result"
|
require "./result"
|
||||||
require "./source"
|
require "./source"
|
||||||
|
|
||||||
|
@ -11,8 +13,7 @@ module Spectator
|
||||||
getter? finished : Bool = false
|
getter? finished : Bool = false
|
||||||
|
|
||||||
# Retrieves the result of the last time the example ran.
|
# Retrieves the result of the last time the example ran.
|
||||||
# TODO: Make result not nil and default to pending.
|
getter result : Result = PendingResult.new
|
||||||
getter! result : Result
|
|
||||||
|
|
||||||
# Creates the example.
|
# Creates the example.
|
||||||
# The *delegate* contains the test context and method that runs the test case.
|
# 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`.
|
# The result will also be stored in `#result`.
|
||||||
def run : Result
|
def run : Result
|
||||||
Log.debug { "Running example #{self}" }
|
Log.debug { "Running example #{self}" }
|
||||||
@delegate.call(self)
|
elapsed = Time.measure do
|
||||||
raise NotImplementedError.new("#run")
|
@delegate.call(self)
|
||||||
|
end
|
||||||
|
@finished = true
|
||||||
|
@result = PassResult.new(elapsed)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Exposes information about the example useful for debugging.
|
# Exposes information about the example useful for debugging.
|
||||||
|
@ -47,7 +51,7 @@ module Spectator
|
||||||
io << s
|
io << s
|
||||||
end
|
end
|
||||||
|
|
||||||
# TODO: Add result.
|
io << result
|
||||||
end
|
end
|
||||||
end
|
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.
|
# 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.
|
# This can happen when the functionality to be tested is not implemented yet.
|
||||||
class PendingResult < Result
|
class PendingResult < Result
|
||||||
# Calls the `pending` method on *interface*.
|
# Creates the result.
|
||||||
def call(interface)
|
# *elapsed* is the length of time it took to run the example.
|
||||||
interface.pending
|
def initialize(elapsed = Time::Span::ZERO)
|
||||||
|
super
|
||||||
end
|
end
|
||||||
|
|
||||||
# Calls the `pending` method on *interface*
|
# Calls the `pending` method on the *visitor*.
|
||||||
# and passes the yielded value.
|
def accept(visitor)
|
||||||
def call(interface)
|
visitor.pending
|
||||||
value = yield self
|
|
||||||
interface.pending(value)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# One-word descriptor of the result.
|
# One-word description of the result.
|
||||||
def to_s(io)
|
def to_s(io)
|
||||||
io << "pending"
|
io << "pending"
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,39 +2,19 @@ module Spectator
|
||||||
# Base class that represents the outcome of running an example.
|
# Base class that represents the outcome of running an example.
|
||||||
# Sub-classes contain additional information specific to the type of result.
|
# Sub-classes contain additional information specific to the type of result.
|
||||||
abstract class Result
|
abstract class Result
|
||||||
# Example that was run that this result is for.
|
# Length of time it took to run the example.
|
||||||
getter example : Example
|
getter elapsed : Time::Span
|
||||||
|
|
||||||
# Constructs the base of the result.
|
# The assertions checked in the example.
|
||||||
# The *example* should refer to the example that was run
|
# getter assertions : Enumerable(Assertion) # TODO: Implement Assertion type.
|
||||||
# and that this result is for.
|
|
||||||
def initialize(@example)
|
# Creates the result.
|
||||||
|
# *elapsed* is the length of time it took to run the example.
|
||||||
|
def initialize(@elapsed)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Calls the corresponding method for the type of result.
|
# Calls the corresponding method for the type of result.
|
||||||
# This is used to avoid placing if or case-statements everywhere based on type.
|
# This is the visitor design pattern.
|
||||||
# Each sub-class implements this method by calling the correct method on *interface*.
|
abstract def accept(visitor)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
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