Remove reference to example from result

Pass examples instead of results into formatters.
This commit is contained in:
Michael Miller 2021-04-26 18:47:11 -06:00
parent f24d634ccb
commit 02b98ea61b
No known key found for this signature in database
GPG key ID: FB9F12F7C646A4AD
26 changed files with 144 additions and 126 deletions

View file

@ -16,11 +16,9 @@ module Spectator
# Indicates whether the example already ran. # Indicates whether the example already ran.
getter? finished : Bool = false getter? finished : Bool = false
# Retrieves the result of the last time the example ran. # Result of the last time the example ran.
def result : Result # Is pending if the example hasn't run.
# TODO: Set to pending immediately (requires circular dependency between Example <-> Result removed). getter result : Result = PendingResult.new
@result ||= PendingResult.new(self)
end
# Creates the example. # Creates the example.
# An instance to run the test code in is given by *context*. # An instance to run the test code in is given by *context*.
@ -62,7 +60,7 @@ module Spectator
if pending? if pending?
Log.debug { "Skipping example #{self} - marked pending" } Log.debug { "Skipping example #{self} - marked pending" }
return @result = PendingResult.new(self) return @result = PendingResult.new
end end
previous_example = @@current previous_example = @@current

View file

@ -11,8 +11,8 @@ module Spectator
# Creates a failure result. # Creates a failure result.
# The *elapsed* argument is the length of time it took to run the example. # The *elapsed* argument is the length of time it took to run the example.
# The *error* is the exception raised that caused the failure. # The *error* is the exception raised that caused the failure.
def initialize(example, elapsed, @error, expectations = [] of Expectation) def initialize(elapsed, @error, expectations = [] of Expectation)
super(example, elapsed, expectations) super(elapsed, expectations)
end end
# Calls the `failure` method on *visitor*. # Calls the `failure` method on *visitor*.

View file

@ -27,9 +27,9 @@ module Spectator::Formatting
end end
# Produces a single character output based on a result. # Produces a single character output based on a result.
def end_example(result) def end_example(example)
@previous_hierarchy.size.times { @io.print INDENT } @previous_hierarchy.size.times { @io.print INDENT }
@io.puts result.accept(Color) { result.example } @io.puts example.result.accept(Color) { example }
end end
# Produces a list of groups making up the hierarchy for an example. # Produces a list of groups making up the hierarchy for an example.

View file

@ -20,8 +20,8 @@ module Spectator::Formatting
end end
# Produces a single character output based on a result. # Produces a single character output based on a result.
def end_example(result) def end_example(example)
@io.print result.accept(Character) @io.print example.result.accept(Character)
end end
# Interface for `Result` to pick a character for output. # Interface for `Result` to pick a character for output.

View file

@ -7,7 +7,9 @@ module Spectator::Formatting
private getter result private getter result
# Creates the JUnit test case. # Creates the JUnit test case.
def initialize(@result : ErrorResult) def initialize(example : Example)
super
@result = example.result.as(ErrorResult)
end end
# Adds the exception to the XML block. # Adds the exception to the XML block.

View file

@ -15,8 +15,13 @@ module Spectator::Formatting
private struct FailureBlock private struct FailureBlock
# Creates the failure block. # Creates the failure block.
# The *index* uniquely identifies the failure in the output. # The *index* uniquely identifies the failure in the output.
# The *result* is the outcome of the failed example. # The *example* is the failed example.
def initialize(@index : Int32, @result : FailResult) def initialize(@index : Int32, @example : Example)
end
# Retrieves the failed result.
private def result
@example.result.as(FailResult)
end end
# Creates the block of text describing the failure. # Creates the block of text describing the failure.
@ -39,7 +44,7 @@ module Spectator::Formatting
# 1) Example name # 1) Example name
# ``` # ```
private def title(indent) private def title(indent)
indent.line(NumberedItem.new(@index, @result.example)) indent.line(NumberedItem.new(@index, @example))
end end
# Produces the main content of the failure block. # Produces the main content of the failure block.
@ -47,12 +52,12 @@ module Spectator::Formatting
# then an error stacktrace if an error occurred. # then an error stacktrace if an error occurred.
private def content(indent) private def content(indent)
unsatisfied_expectations(indent) unsatisfied_expectations(indent)
error_stacktrace(indent) if @result.is_a?(ErrorResult) error_stacktrace(indent) if result.is_a?(ErrorResult)
end end
# Produces a list of unsatisfied expectations and their values. # Produces a list of unsatisfied expectations and their values.
private def unsatisfied_expectations(indent) private def unsatisfied_expectations(indent)
@result.expectations.reject(&.satisfied?).each do |expectation| result.expectations.reject(&.satisfied?).each do |expectation|
indent.line(Color.failure(LabeledText.new("Failure", expectation.failure_message))) indent.line(Color.failure(LabeledText.new("Failure", expectation.failure_message)))
indent.line indent.line
indent.increase do indent.increase do
@ -76,7 +81,7 @@ module Spectator::Formatting
# Produces the stack trace for an errored result. # Produces the stack trace for an errored result.
private def error_stacktrace(indent) private def error_stacktrace(indent)
error = @result.error error = result.error
first_line = error.message.try(&.lines).try(&.first) first_line = error.message.try(&.lines).try(&.first)
indent.line(Color.error(LabeledText.new("Error", first_line))) indent.line(Color.error(LabeledText.new("Error", first_line)))
indent.line indent.line
@ -105,7 +110,7 @@ module Spectator::Formatting
# Produces the location line of the failure block. # Produces the location line of the failure block.
private def location(indent) private def location(indent)
indent.line(Comment.color(@result.example.location)) indent.line(Comment.color(@example.location))
end end
# Gets the number of characters a positive integer spans in base 10. # Gets the number of characters a positive integer spans in base 10.

View file

@ -12,8 +12,8 @@ module Spectator::Formatting
end end
# Colorizes the command instance based on the result. # Colorizes the command instance based on the result.
def self.color(result) def self.color(example)
result.accept(Color) { new(result.example) } example.result.accept(Color) { new(example) }
end end
end end
end end

View file

@ -7,7 +7,9 @@ module Spectator::Formatting
private getter result private getter result
# Creates the JUnit test case. # Creates the JUnit test case.
def initialize(@result : FailResult) def initialize(example : Example)
super
@result = example.result.as(FailResult)
end end
# Status string specific to the result type. # Status string specific to the result type.

View file

@ -21,7 +21,7 @@ module Spectator::Formatting
abstract def start_example(example : Example) abstract def start_example(example : Example)
# Called when a test finishes. # Called when a test finishes.
# The result of the test is provided. # The result of the test is available through *example*.
abstract def end_example(result : Result) abstract def end_example(example : Example)
end end
end end

View file

@ -36,8 +36,8 @@ module Spectator::Formatting
# Called when a test finishes. # Called when a test finishes.
# The result of the test is provided. # The result of the test is provided.
def end_example(result : Result) def end_example(example : Example)
result.to_json(@json) example.result.to_json(@json, example)
end end
# Adds the totals section of the document. # Adds the totals section of the document.
@ -84,11 +84,11 @@ module Spectator::Formatting
end end
# Adds a profile entry to the document. # Adds a profile entry to the document.
private def profile_entry(result) private def profile_entry(example)
@json.object do @json.object do
@json.field("example", result.example) @json.field("example", example)
@json.field("time", result.elapsed.total_seconds) @json.field("time", example.result.elapsed.total_seconds)
@json.field("location", result.example.location) @json.field("location", example.location)
end end
end end
end end

View file

@ -37,8 +37,8 @@ module Spectator::Formatting
end end
# Called when a test finishes. # Called when a test finishes.
# The result of the test is provided. # The result of the test is provided by *example*.
def end_example(result : Result) def end_example(example : Example)
end end
# Creates the "testsuites" block in the XML. # Creates the "testsuites" block in the XML.
@ -55,8 +55,8 @@ module Spectator::Formatting
# Adds all of the individual test suite blocks. # Adds all of the individual test suite blocks.
private def add_test_suites(report) private def add_test_suites(report)
report.group_by(&.example.location.path).each do |path, results| report.group_by(&.location.path).each do |path, examples|
JUnitTestSuite.new(path, results).to_xml(@xml) JUnitTestSuite.new(path, examples).to_xml(@xml)
end end
end end
end end

View file

@ -1,6 +1,10 @@
module Spectator::Formatting module Spectator::Formatting
# Base type for all JUnit test case results. # Base type for all JUnit test case results.
private abstract class JUnitTestCase private abstract class JUnitTestCase
# Creates the JUnit test case.
def initialize(@example : Example)
end
# Produces the test case XML element. # Produces the test case XML element.
def to_xml(xml : ::XML::Builder) def to_xml(xml : ::XML::Builder)
xml.element("testcase", **attributes) do xml.element("testcase", **attributes) do
@ -11,7 +15,7 @@ module Spectator::Formatting
# Attributes that go in the "testcase" XML element. # Attributes that go in the "testcase" XML element.
private def attributes private def attributes
{ {
name: result.example, name: example,
status: status, status: status,
classname: classname, classname: classname,
} }
@ -23,6 +27,9 @@ module Spectator::Formatting
# Status string specific to the result type. # Status string specific to the result type.
private abstract def status : String private abstract def status : String
# Example for this test case.
private getter example : Example
# Adds additional content to the "testcase" XML block. # Adds additional content to the "testcase" XML block.
# Override this to add more content. # Override this to add more content.
private def content(xml) private def content(xml)
@ -31,7 +38,7 @@ module Spectator::Formatting
# Java-ified class name created from the spec. # Java-ified class name created from the spec.
private def classname private def classname
path = result.example.location.path path = example.location.path
file = File.basename(path) file = File.basename(path)
ext = File.extname(file) ext = File.extname(file)
name = file[0...-(ext.size)] name = file[0...-(ext.size)]

View file

@ -3,9 +3,9 @@ module Spectator::Formatting
private struct JUnitTestSuite private struct JUnitTestSuite
# Creates the JUnit test suite. # Creates the JUnit test suite.
# The *path* should be the file that all results are from. # The *path* should be the file that all results are from.
# The *results* is a subset of all results that share the path. # The *examples* is a subset of all examples that share the path.
def initialize(@path : String, results : Array(Result)) def initialize(@path : String, examples : Array(Example))
@report = Report.new(results) @report = Report.new(examples)
end end
# Generates the XML for the test suite (and all nested test cases). # Generates the XML for the test suite (and all nested test cases).
@ -24,8 +24,8 @@ module Spectator::Formatting
# Adds the test case elements to the XML. # Adds the test case elements to the XML.
private def add_test_cases(xml) private def add_test_cases(xml)
@report.each do |result| @report.each do |example|
test_case = result.accept(JUnitTestCaseSelector) { |r| r } test_case = example.result.accept(JUnitTestCaseSelector) { example }
test_case.to_xml(xml) test_case.to_xml(xml)
end end
end end
@ -50,23 +50,23 @@ module Spectator::Formatting
extend self extend self
# Creates a successful JUnit test case. # Creates a successful JUnit test case.
def pass(result) def pass(example)
SuccessfulJUnitTestCase.new(result.as(PassResult)) SuccessfulJUnitTestCase.new(example)
end end
# Creates a failure JUnit test case. # Creates a failure JUnit test case.
def failure(result) def failure(example)
FailureJUnitTestCase.new(result.as(FailResult)) FailureJUnitTestCase.new(example)
end end
# Creates an error JUnit test case. # Creates an error JUnit test case.
def error(result) def error(example)
ErrorJUnitTestCase.new(result.as(ErrorResult)) ErrorJUnitTestCase.new(example)
end end
# Creates a skipped JUnit test case. # Creates a skipped JUnit test case.
def pending(result) def pending(example)
SkippedJUnitTestCase.new(result.as(PendingResult)) SkippedJUnitTestCase.new(example)
end end
end end
end end

View file

@ -11,17 +11,17 @@ module Spectator::Formatting
indent = Indent.new(io) indent = Indent.new(io)
indent.increase do indent.increase do
@profile.each do |result| @profile.each do |example|
entry(indent, result) entry(indent, example)
end end
end end
end end
# Adds a result entry to the output. # Adds a result entry to the output.
private def entry(indent, result) private def entry(indent, example)
indent.line(result.example) indent.line(example)
indent.increase do indent.increase do
indent.line(LocationTiming.new(result.elapsed, result.example.location)) indent.line(LocationTiming.new(example.result.elapsed, example.location))
end end
end end
end end

View file

@ -19,8 +19,8 @@ module Spectator::Formatting
end end
# Called when a test finishes. # Called when a test finishes.
# The result of the test is provided. # The result of the test is provided by *example*.
def end_example(result : Result) def end_example(example : Example)
# ... crickets ... # ... crickets ...
end end
end end

View file

@ -7,7 +7,9 @@ module Spectator::Formatting
private getter result private getter result
# Creates the JUnit test case. # Creates the JUnit test case.
def initialize(@result : PendingResult) def initialize(example : Example)
super
@result = example.result.as(PendingResult)
end end
# Status string specific to the result type. # Status string specific to the result type.

View file

@ -5,7 +5,9 @@ module Spectator::Formatting
private getter result private getter result
# Creates the JUnit test case. # Creates the JUnit test case.
def initialize(@result : PassResult) def initialize(example : Example)
super
@result = example.result.as(PassResult)
end end
# Status string specific to the result type. # Status string specific to the result type.

View file

@ -33,8 +33,8 @@ module Spectator::Formatting
private def failures(failures) private def failures(failures)
@io.puts "Failures:" @io.puts "Failures:"
@io.puts @io.puts
failures.each_with_index do |result, index| failures.each_with_index do |example, index|
@io.puts FailureBlock.new(index + 1, result) @io.puts FailureBlock.new(index + 1, example)
end end
end end
@ -68,10 +68,10 @@ module Spectator::Formatting
@io.puts @io.puts
@io.puts "Failed examples:" @io.puts "Failed examples:"
@io.puts @io.puts
failures.each do |result| failures.each do |example|
@io << FailureCommand.color(result) @io << FailureCommand.color(example)
@io << ' ' @io << ' '
@io.puts Comment.color(result.example) @io.puts Comment.color(example)
end end
end end
end end

View file

@ -27,9 +27,9 @@ module Spectator::Formatting
end end
# Called when a test finishes. # Called when a test finishes.
# The result of the test is provided. # The result of the test is provided by *example*.
def end_example(result : Result) def end_example(example : Example)
@io.puts TAPTestLine.new(@index, result) @io.puts TAPTestLine.new(@index, example)
@index += 1 @index += 1
end end
@ -39,19 +39,19 @@ module Spectator::Formatting
indent = Indent.new(@io) indent = Indent.new(@io)
indent.increase do indent.increase do
profile.each do |result| profile.each do |example|
profile_entry(indent, result) profile_entry(indent, example)
end end
end end
end end
# Adds a profile result entry to the output. # Adds a profile result entry to the output.
private def profile_entry(indent, result) private def profile_entry(indent, example)
@io << "# " @io << "# "
indent.line(result.example) indent.line(example)
indent.increase do indent.increase do
@io << "# " @io << "# "
indent.line(LocationTiming.new(result.elapsed, result.example.location)) indent.line(LocationTiming.new(example.result.elapsed, example.location))
end end
end end
end end

View file

@ -2,7 +2,7 @@ module Spectator::Formatting
# Produces a formatted TAP test line. # Produces a formatted TAP test line.
private struct TAPTestLine private struct TAPTestLine
# Creates the test line. # Creates the test line.
def initialize(@index : Int32, @result : Result) def initialize(@index : Int32, @example : Example)
end end
# Appends the line to the output. # Appends the line to the output.
@ -11,23 +11,23 @@ module Spectator::Formatting
io << ' ' io << ' '
io << @index io << @index
io << " - " io << " - "
io << example io << @example
io << " # skip" if pending? io << " # skip" if pending?
end end
# The text "ok" or "not ok" depending on the result. # The text "ok" or "not ok" depending on the result.
private def status private def status
@result.is_a?(FailResult) ? "not ok" : "ok" result.is_a?(FailResult) ? "not ok" : "ok"
end end
# The example that was tested. # The result of running the example.
private def example private def result
@result.example @example.result
end end
# Indicates whether this test was skipped. # Indicates whether this test was skipped.
private def pending? private def pending?
@result.is_a?(PendingResult) result.is_a?(PendingResult)
end end
end end
end end

View file

@ -94,14 +94,13 @@ module Spectator
# 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`.
private def translate(elapsed, error) : Result private def translate(elapsed, error) : Result
example = Example.current # TODO: Remove this.
case error case error
when nil when nil
PassResult.new(example, elapsed, @expectations) PassResult.new(elapsed, @expectations)
when ExpectationFailed when ExpectationFailed
FailResult.new(example, elapsed, error, @expectations) FailResult.new(elapsed, error, @expectations)
else else
ErrorResult.new(example, elapsed, error, @expectations) ErrorResult.new(elapsed, error, @expectations)
end end
end end

View file

@ -7,7 +7,7 @@ module Spectator
class PendingResult < Result class PendingResult < Result
# Creates the result. # Creates the result.
# *elapsed* is the length of time it took to run the example. # *elapsed* is the length of time it took to run the example.
def initialize(example, elapsed = Time::Span::ZERO, expectations = [] of Expectation) def initialize(elapsed = Time::Span::ZERO, expectations = [] of Expectation)
super super
end end

View file

@ -1,14 +1,14 @@
module Spectator module Spectator
# Information about the runtimes of examples. # Information about the runtimes of examples.
class Profile class Profile
include Indexable(Result) include Indexable(Example)
# Total length of time it took to run all examples in the test suite. # Total length of time it took to run all examples in the test suite.
getter total_time : Time::Span getter total_time : Time::Span
# Creates the profiling information. # Creates the profiling information.
# The *slowest* results must already be sorted, longest time first. # The *slowest* results must already be sorted, longest time first.
private def initialize(@slowest : Array(Result), @total_time) private def initialize(@slowest : Array(Example), @total_time)
end end
# Number of results in the profile. # Number of results in the profile.
@ -23,7 +23,7 @@ module Spectator
# Length of time it took to run the results in the profile. # Length of time it took to run the results in the profile.
def time def time
@slowest.sum(&.elapsed) @slowest.sum(&.result.elapsed)
end end
# Percentage (from 0 to 1) of time the results in this profile took compared to all examples. # Percentage (from 0 to 1) of time the results in this profile took compared to all examples.
@ -33,9 +33,9 @@ module Spectator
# Produces the profile from a report. # Produces the profile from a report.
def self.generate(report, size = 10) def self.generate(report, size = 10)
results = report.to_a examples = report.to_a
sorted_results = results.sort_by(&.elapsed) sorted_examples = examples.sort_by(&.result.elapsed)
slowest = sorted_results.last(size).reverse slowest = sorted_examples.last(size).reverse
self.new(slowest, report.example_runtime) self.new(slowest, report.example_runtime)
end end
end end

View file

@ -3,7 +3,7 @@ require "./result"
module Spectator module Spectator
# Outcome of all tests in a suite. # Outcome of all tests in a suite.
class Report class Report
include Enumerable(Result) include Enumerable(Example)
# Total length of time it took to execute the test suite. # Total length of time it took to execute the test suite.
# This includes examples, hooks, and framework processes. # This includes examples, hooks, and framework processes.
@ -29,14 +29,14 @@ module Spectator
getter! random_seed : UInt64? getter! random_seed : UInt64?
# Creates the report. # Creates the report.
# The *results* are from running the examples in the test suite. # The *examples* are all examples in the test suite.
# The *runtime* is the total time it took to execute the suite. # The *runtime* is the total time it took to execute the suite.
# The *remaining_count* is the number of tests skipped due to fail-fast. # The *remaining_count* is the number of tests skipped due to fail-fast.
# The *fail_blank* flag indicates whether it is a failure if there were no tests run. # The *fail_blank* flag indicates whether it is a failure if there were no tests run.
# The *random_seed* is the seed used for random number generation. # The *random_seed* is the seed used for random number generation.
def initialize(@results : Array(Result), @runtime, @remaining_count = 0, @fail_blank = false, @random_seed = nil) def initialize(@examples : Array(Example), @runtime, @remaining_count = 0, @fail_blank = false, @random_seed = nil)
@results.each do |result| @examples.each do |example|
case result case example.result
when PassResult when PassResult
@successful_count += 1 @successful_count += 1
when ErrorResult when ErrorResult
@ -55,23 +55,28 @@ module Spectator
# Creates the report. # Creates the report.
# This constructor is intended for reports of subsets of results. # This constructor is intended for reports of subsets of results.
# The *results* are from running the examples in the test suite. # The *examples* are all examples in the test suite.
# The runtime is calculated from the *results*. # The runtime is calculated from the *results*.
def initialize(results : Array(Result)) def initialize(examples : Array(Example))
runtime = results.sum(&.elapsed) runtime = examples.sum(&.result.elapsed)
initialize(results, runtime) initialize(examples, runtime)
end end
# Yields each result in turn. # Yields each example in turn.
def each def each
@results.each do |result| @examples.each do |example|
yield result yield example
end end
end end
# Retrieves results of all examples.
def results
@examples.each.map(&.result)
end
# Number of examples. # Number of examples.
def example_count def example_count
@results.size @examples.size
end end
# Number of examples run (not skipped or pending). # Number of examples run (not skipped or pending).
@ -90,21 +95,21 @@ module Spectator
remaining_count > 0 remaining_count > 0
end end
# Returns a set of results for all failed examples. # Returns a set of all failed examples.
def failures def failures
@results.each.compact_map(&.as?(FailResult)) @examples.select(&.result.is_a?(FailResult))
end end
# Returns a set of results for all errored examples. # Returns a set of all errored examples.
def errors def errors
@results.each.compact_map(&.as?(ErrorResult)) @examples.select(&.result.is_a?(ErrorResult))
end end
# Length of time it took to run just example code. # Length of time it took to run just example code.
# This does not include hooks, # This does not include hooks,
# but it does include pre- and post-conditions. # but it does include pre- and post-conditions.
def example_runtime def example_runtime
@results.sum(&.elapsed) results.sum(&.elapsed)
end end
# Length of time spent in framework processes and hooks. # Length of time spent in framework processes and hooks.

View file

@ -2,10 +2,6 @@ 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 generated the result.
# TODO: Remove this.
getter example : Example
# Length of time it took to run the example. # Length of time it took to run the example.
getter elapsed : Time::Span getter elapsed : Time::Span
@ -14,7 +10,7 @@ module Spectator
# Creates the result. # Creates the result.
# *elapsed* is the length of time it took to run the example. # *elapsed* is the length of time it took to run the example.
def initialize(@example, @elapsed, @expectations = [] of Expectation) def initialize(@elapsed, @expectations = [] of Expectation)
end end
# Calls the corresponding method for the type of result. # Calls the corresponding method for the type of result.
@ -22,14 +18,14 @@ module Spectator
abstract def accept(visitor) abstract def accept(visitor)
# Creates a JSON object from the result information. # Creates a JSON object from the result information.
def to_json(json : ::JSON::Builder) def to_json(json : ::JSON::Builder, example)
json.object do json.object do
add_json_fields(json) add_json_fields(json, example)
end end
end end
# Adds the common fields for a result to a JSON builder. # Adds the common fields for a result to a JSON builder.
private def add_json_fields(json : ::JSON::Builder) private def add_json_fields(json : ::JSON::Builder, example)
json.field("name", example) json.field("name", example)
json.field("location", example.location) json.field("location", example.location)
json.field("result", to_s) json.field("result", to_s)

View file

@ -16,25 +16,25 @@ module Spectator
@config.each_formatter(&.start_suite(@suite)) @config.each_formatter(&.start_suite(@suite))
# Run all examples and capture the results. # Run all examples and capture the results.
results = Array(Result).new(@suite.size) examples = Array(Example).new(@suite.size)
elapsed = Time.measure do elapsed = Time.measure do
collect_results(results) collect_results(examples)
end end
# Generate a report and pass it along to the formatter. # Generate a report and pass it along to the formatter.
remaining = @suite.size - results.size remaining = @suite.size - examples.size
seed = (@config.random_seed if @config.randomize?) seed = (@config.random_seed if @config.randomize?)
report = Report.new(results, elapsed, remaining, @config.fail_blank?, seed) report = Report.new(examples, elapsed, remaining, @config.fail_blank?, seed)
@config.each_formatter(&.end_suite(report, profile(report))) @config.each_formatter(&.end_suite(report, profile(report)))
!report.failed? !report.failed?
end end
# Runs all examples and adds results to a list. # Runs all examples and adds them to a list.
private def collect_results(results) private def collect_results(examples)
example_order.each do |example| example_order.each do |example|
result = run_example(example).as(Result) result = run_example(example)
results << result examples << example
if @config.fail_fast? && result.is_a?(FailResult) if @config.fail_fast? && result.is_a?(FailResult)
example.group.call_once_after_all example.group.call_once_after_all
break break
@ -60,14 +60,14 @@ module Spectator
else else
example.run example.run
end end
@config.each_formatter(&.end_example(result)) @config.each_formatter(&.end_example(example))
result result
end end
# Creates a fake result for an example. # Creates a fake result for an example.
private def dry_run_result(example) private def dry_run_result(example)
expectations = [] of Expectation expectations = [] of Expectation
PassResult.new(example, Time::Span.zero, expectations) PassResult.new(Time::Span.zero, expectations)
end end
# Generates and returns a profile if one should be displayed. # Generates and returns a profile if one should be displayed.