diff --git a/src/spectator/runnable_example.cr b/src/spectator/runnable_example.cr index 2ad4a8e..16009ed 100644 --- a/src/spectator/runnable_example.cr +++ b/src/spectator/runnable_example.cr @@ -6,15 +6,10 @@ module Spectator # the example code, and capturing a result. # Sub-classes need to implement the `#run_instance` method. abstract class RunnableExample < Example - # Runs the example, hooks, and captures the result. + # Runs the example, hooks, and captures the result + # and translates to a usable result. def run_inner : Result - result = ResultCapture.new - begin - run_before_hooks - wrapped_capture_result(result).call - ensure - run_after_hooks - end + result = capture_result expectations = Internals::Harness.current.expectation_results translate_result(result, expectations) end @@ -26,29 +21,49 @@ module Spectator private def run_before_hooks group.run_before_all_hooks group.run_before_each_hooks + rescue ex + # If an error occurs in the before hooks, skip running the example. + raise Exception.new("Error encountered while running before hooks", ex) end # Runs the hooks that should be performed after the test code finishes. - private def run_after_hooks + private def run_after_hooks(result) group.run_after_each_hooks group.run_after_all_hooks rescue ex - # TODO: Pass along error to result. + # Store the error from the hooks + # if the example didn't encounter an error. + result.error = ex unless result.error + end + + # Runs all hooks and the example code. + # A captured result is returned. + private def capture_result : ResultCapture + ResultCapture.new.tap do |result| + # Get the proc that will call around-each hooks and the example. + wrapper = wrapped_run_example(result) + begin + run_before_hooks + wrapper.call + ensure + run_after_hooks(result) + end + end end # Creates a proc that runs the test code # and captures the result. - private def wrapped_capture_result(result) + private def wrapped_run_example(result) : -> # Wrap the method that runs and captures # the test code with the around-each hooks. group.wrap_around_each_hooks do # Pass along the result capture utility. - capture_result(result) + run_example(result) end end # Runs the test code and captures the result. - private def capture_result(result) + private def run_example(result) # Capture how long it takes to run the test code. result.elapsed = Time.measure do begin @@ -60,12 +75,16 @@ module Spectator end end + # Creates a result instance from captured result information. private def translate_result(result, expectations) case (error = result.error) + # If no errors occurred, then the example ran successfully. when Nil SuccessfulResult.new(self, result.elapsed, expectations) + # If a required expectation fails, then a `ExpectationRailed` exception will be raised. when ExpectationFailed FailedResult.new(self, result.elapsed, expectations, error) + # Any other exception that is raised is unexpected and is an errored result. else ErroredResult.new(self, result.elapsed, expectations, error) end