shard-spectator/src/spectator/runner.cr

99 lines
2.8 KiB
Crystal

require "./example"
require "./formatting/formatter"
require "./profile"
require "./report"
require "./run_flags"
require "./runner_events"
module Spectator
# Logic for executing examples and collecting results.
struct Runner
include RunnerEvents
# Formatter to send events to.
private getter formatter : Formatting::Formatter
# Creates the runner.
# The collection of *examples* should be pre-filtered and shuffled.
# This runner will run each example in the order provided.
# The *formatter* will be called for various events.
def initialize(@examples : Array(Example), @formatter : Formatting::Formatter,
@run_flags = RunFlags::None, @random_seed : UInt64? = nil)
end
# Runs the spec.
# This will run the provided examples
# and invoke the reporters to communicate results.
# True will be returned if the spec ran successfully,
# or false if there was at least one failure.
def run : Bool
start
elapsed = Time.measure { run_examples }
stop
report = Report.generate(@examples, elapsed, @random_seed)
profile = Profile.generate(@examples) if @run_flags.profile? && report.counts.run > 0
summarize(report, profile)
report.counts.fail.zero?
ensure
close
end
# Attempts to run all examples.
# Returns a list of examples that ran.
private def run_examples
@examples.each do |example|
result = run_example(example)
# Bail out if the example failed
# and configured to stop after the first failure.
break fail_fast if fail_fast? && result.fail?
end
end
# Runs a single example and returns the result.
# The formatter is given the example and result information.
private def run_example(example)
example_started(example)
result = if dry_run?
# TODO: Pending examples return a pending result instead of pass in RSpec dry-run.
dry_run_result
else
example.run
end
example_finished(example)
result
end
# Creates a fake result.
private def dry_run_result
expectations = [] of Expectation
PassResult.new(Time::Span.zero, expectations)
end
# Generates and returns a profile if one should be displayed.
private def profile(report)
Profile.generate(report) if @config.profile?
end
# Indicates whether examples should be simulated, but not run.
private def dry_run?
@run_flags.dry_run?
end
# Indicates whether test execution should stop after the first failure.
private def fail_fast?
@run_flags.fail_fast?
end
private def fail_fast : Nil
end
# Number of examples configured to run.
private def example_count
@examples.size
end
end
end