Cleanup harness some

This commit is contained in:
Michael Miller 2021-05-06 22:10:40 -06:00
parent 02b98ea61b
commit ff5d855389
No known key found for this signature in database
GPG key ID: F9A0C5C65B162436

View file

@ -6,7 +6,6 @@ require "./result"
module Spectator module Spectator
# Helper class that acts as a gateway between test code and the framework. # Helper class that acts as a gateway between test code and the framework.
# This is essentially an "example runner."
# #
# Test code should be wrapped with a call to `.run`. # Test code should be wrapped with a call to `.run`.
# This class will catch all errors raised by the test code. # This class will catch all errors raised by the test code.
@ -44,12 +43,23 @@ module Spectator
# It will be reset after the test regardless of the outcome. # It will be reset after the test regardless of the outcome.
# The result of running the test code will be returned. # The result of running the test code will be returned.
def self.run : Result def self.run : Result
harness = new with_harness do |harness|
harness.run { yield }
end
end
# Instanciates a new harness and yields it.
# The `.current` harness is set to the new harness for the duration of the block.
# `.current` is reset to the previous value (probably nil) afterwards, even if the block raises.
# The result of the block is returned.
private def self.with_harness
previous = @@current previous = @@current
@@current = harness begin
result = harness.run { yield } harness = new
@@current = previous yield harness
result ensure
@@current = previous
end
end end
@deferred = Deque(->).new @deferred = Deque(->).new
@ -59,14 +69,17 @@ module Spectator
# The test code should be called from within the block given to this method. # The test code should be called from within the block given to this method.
def run : Result def run : Result
elapsed, error = capture { yield } elapsed, error = capture { yield }
elapsed2, error2 = run_deferred elapsed2, error2 = capture { run_deferred }
translate(elapsed + elapsed2, error || error2) translate(elapsed + elapsed2, error || error2)
end end
def report(expectation : Expectation) : Nil def report(expectation : Expectation) : Nil
Log.debug { "Reporting expectation #{expectation}" } Log.debug { "Reporting expectation #{expectation}" }
@expectations << expectation @expectations << expectation
# TODO: Move this out of harness, maybe to `Example`.
Example.current.name = expectation.description unless Example.current.name? Example.current.name = expectation.description unless Example.current.name?
raise ExpectationFailed.new(expectation) if expectation.failed? raise ExpectationFailed.new(expectation) if expectation.failed?
end end
@ -78,18 +91,25 @@ module Spectator
# Yields to run the test code and returns information about the outcome. # Yields to run the test code and returns information about the outcome.
# Returns a tuple with the elapsed time and an error if one occurred (otherwise nil). # Returns a tuple with the elapsed time and an error if one occurred (otherwise nil).
private def capture private def capture : Tuple(Time, Exception?)
error = nil.as(Exception?) error = nil
elapsed = Time.measure do elapsed = Time.measure do
begin error = catch_error { yield }
yield
rescue e
error = e
end
end end
{elapsed, error} {elapsed, error}
end end
# Yields to run a block of code and captures exceptions.
# If the block of code raises an error, the error is caught and returned.
# If the block doesn't raise an error, then nil is returned.
private def catch : Exception?
yield
rescue e
e
else
nil
end
# Translates the outcome of running a test to a result. # Translates the outcome of running a test to a result.
# Takes the *elapsed* time and a possible *error* from the test. # Takes the *elapsed* time and a possible *error* from the test.
# Returns a type of `Result`. # Returns a type of `Result`.
@ -105,16 +125,11 @@ module Spectator
end end
# Runs all deferred blocks. # Runs all deferred blocks.
# This method executes code from tests and may raise an error.
# It should be wrapped in a call to `#capture`.
private def run_deferred private def run_deferred
Log.debug { "Running deferred operations" } Log.debug { "Running deferred operations" }
error = nil.as(Exception?) @deferred.each(&.call)
elapsed = Time.measure do
@deferred.each(&.call)
rescue ex
error = ex
end
@deferred.clear
{elapsed, error}
end end
end end
end end