tldr 0.10.1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/README.md +207 -248
- data/exe/tldr +2 -0
- data/exe/tldt +2 -0
- data/lib/tldr/argv_parser.rb +73 -25
- data/lib/tldr/argv_reconstructor.rb +107 -0
- data/lib/tldr/assertions.rb +2 -3
- data/lib/tldr/autorun.rb +2 -0
- data/lib/tldr/minitest_compatibility.rb +35 -0
- data/lib/tldr/reporters/default.rb +11 -11
- data/lib/tldr/reporters/icon_provider.rb +9 -0
- data/lib/tldr/runner.rb +27 -8
- data/lib/tldr/value/config.rb +55 -133
- data/lib/tldr/version.rb +1 -1
- data/lib/tldr/yaml_parser.rb +29 -0
- data/lib/tldr.rb +3 -0
- data/script/test +3 -3
- metadata +25 -4
- data/lib/tldr/assertions/minitest_compatibility.rb +0 -55
data/lib/tldr/argv_parser.rb
CHANGED
@@ -5,21 +5,41 @@ class TLDR
|
|
5
5
|
PATTERN_FRIENDLY_SPLITTER = /,(?=(?:[^\/]*\/[^\/]*\/)*[^\/]*$)/
|
6
6
|
|
7
7
|
def parse args, options = {cli_defaults: true}
|
8
|
+
og_args = args.dup
|
8
9
|
OptionParser.new do |opts|
|
9
10
|
opts.banner = "Usage: tldr [options] some_tests/**/*.rb some/path.rb:13 ..."
|
10
11
|
|
11
|
-
opts.on
|
12
|
-
options[:
|
12
|
+
opts.on "-t", "--[no-]timeout [TIMEOUT]", "Timeout (in seconds) before timer aborts the run (Default: #{Config::DEFAULT_TIMEOUT})" do |timeout|
|
13
|
+
options[:timeout] = if timeout == false
|
14
|
+
# --no-timeout
|
15
|
+
-1
|
16
|
+
elsif timeout.nil?
|
17
|
+
# --timeout
|
18
|
+
Config::DEFAULT_TIMEOUT
|
19
|
+
else
|
20
|
+
# --timeout 42.3
|
21
|
+
handle_unparsable_optional_value(og_args, "timeout", timeout) do
|
22
|
+
Float(timeout)
|
23
|
+
end
|
24
|
+
end
|
13
25
|
end
|
14
26
|
|
15
|
-
opts.on
|
16
|
-
options[:
|
27
|
+
opts.on CONFLAGS[:watch], "Run your tests continuously on file save (requires 'fswatch' to be installed)" do
|
28
|
+
options[:watch] = true
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.on CONFLAGS[:fail_fast], "Stop running tests as soon as one fails" do |fail_fast|
|
32
|
+
options[:fail_fast] = fail_fast
|
17
33
|
end
|
18
34
|
|
19
35
|
opts.on CONFLAGS[:parallel], "Parallelize tests (Default: true)" do |parallel|
|
20
36
|
options[:parallel] = parallel
|
21
37
|
end
|
22
38
|
|
39
|
+
opts.on "-s", "#{CONFLAGS[:seed]} SEED", Integer, "Random seed for test order (setting --seed disables parallelization by default)" do |seed|
|
40
|
+
options[:seed] = seed
|
41
|
+
end
|
42
|
+
|
23
43
|
opts.on "-n", "#{CONFLAGS[:names]} PATTERN", "One or more names or /patterns/ of tests to run (like: foo_test, /test_foo.*/, Foo#foo_test)" do |name|
|
24
44
|
options[:names] ||= []
|
25
45
|
options[:names] += name.split(PATTERN_FRIENDLY_SPLITTER)
|
@@ -58,54 +78,82 @@ class TLDR
|
|
58
78
|
options[:load_paths] += load_path
|
59
79
|
end
|
60
80
|
|
61
|
-
opts.on "-r", "#{CONFLAGS[:reporter]} REPORTER", String, "Set a custom reporter class (Default: \"TLDR::Reporters::Default\")" do |reporter|
|
62
|
-
options[:reporter] = Kernel.const_get(reporter)
|
63
|
-
end
|
64
|
-
|
65
81
|
opts.on "#{CONFLAGS[:base_path]} PATH", String, "Change the working directory for all relative paths (Default: current working directory)" do |path|
|
66
82
|
options[:base_path] = path
|
67
83
|
end
|
68
84
|
|
69
|
-
opts.on CONFLAGS[:
|
70
|
-
options[:
|
71
|
-
end
|
72
|
-
|
73
|
-
opts.on CONFLAGS[:no_emoji], "Disable emoji in the output" do
|
74
|
-
options[:no_emoji] = true
|
85
|
+
opts.on "-c", "#{CONFLAGS[:config_path]} PATH", String, "The YAML configuration file to load (Default: '.tldr.yml')" do |config_path|
|
86
|
+
options[:config_path] = config_path
|
75
87
|
end
|
76
88
|
|
77
|
-
opts.on "-
|
78
|
-
options[:
|
89
|
+
opts.on "-r", "#{CONFLAGS[:reporter]} REPORTER", String, "Set a custom reporter class (Default: \"TLDR::Reporters::Default\")" do |reporter|
|
90
|
+
options[:reporter] = reporter
|
79
91
|
end
|
80
92
|
|
81
|
-
opts.on CONFLAGS[:
|
82
|
-
options[:
|
93
|
+
opts.on CONFLAGS[:emoji], "Enable emoji output for the default reporter (Default: false)" do |emoji|
|
94
|
+
options[:emoji] = emoji
|
83
95
|
end
|
84
96
|
|
85
97
|
opts.on CONFLAGS[:warnings], "Print Ruby warnings (Default: true)" do |warnings|
|
86
98
|
options[:warnings] = warnings
|
87
99
|
end
|
88
100
|
|
89
|
-
opts.on CONFLAGS[:
|
90
|
-
options[:
|
101
|
+
opts.on "-v", CONFLAGS[:verbose], "Print stack traces for errors" do |verbose|
|
102
|
+
options[:verbose] = verbose
|
91
103
|
end
|
92
104
|
|
93
|
-
opts.on CONFLAGS[:yes_i_know], "Suppress TLDR report when suite runs
|
105
|
+
opts.on CONFLAGS[:yes_i_know], "Suppress TLDR report when suite runs beyond any configured --timeout" do
|
94
106
|
options[:yes_i_know] = true
|
95
107
|
end
|
96
108
|
|
97
|
-
opts.on CONFLAGS[:
|
98
|
-
options[:
|
109
|
+
opts.on CONFLAGS[:print_interrupted_test_backtraces], "Print stack traces of tests interrupted after a timeout" do |print_interrupted_test_backtraces|
|
110
|
+
options[:print_interrupted_test_backtraces] = print_interrupted_test_backtraces
|
99
111
|
end
|
100
112
|
|
101
|
-
|
102
|
-
|
113
|
+
unless ARGV.include?("--help") || ARGV.include?("--h")
|
114
|
+
opts.on CONFLAGS[:i_am_being_watched], "[INTERNAL] Signals to tldr it is being invoked under --watch mode" do
|
115
|
+
options[:i_am_being_watched] = true
|
116
|
+
end
|
117
|
+
|
118
|
+
opts.on "--comment COMMENT", String, "[INTERNAL] No-op; used for multi-line execution instructions" do
|
119
|
+
# See "--comment" in lib/tldr/reporters/default.rb for an example of how this is used internally
|
120
|
+
end
|
103
121
|
end
|
104
122
|
end.parse!(args)
|
105
123
|
|
106
124
|
options[:paths] = args if args.any?
|
125
|
+
options[:config_path] = case options[:config_path]
|
126
|
+
when nil then Config::DEFAULT_YAML_PATH
|
127
|
+
when false then nil
|
128
|
+
else options[:config_path]
|
129
|
+
end
|
107
130
|
|
108
131
|
Config.new(**options)
|
109
132
|
end
|
133
|
+
|
134
|
+
private
|
135
|
+
|
136
|
+
def handle_unparsable_optional_value(og_args, option_name, value, &blk)
|
137
|
+
yield
|
138
|
+
rescue ArgumentError
|
139
|
+
args = og_args.dup
|
140
|
+
if (option_index = args.index("--#{option_name}"))
|
141
|
+
args.insert(option_index + 1, "--")
|
142
|
+
warn <<~MSG
|
143
|
+
TLDR exited in error!
|
144
|
+
|
145
|
+
We couldn't parse #{value.inspect} as a valid #{option_name} value
|
146
|
+
|
147
|
+
Did you mean to set --#{option_name} as the last option and without an explicit value?
|
148
|
+
|
149
|
+
If so, you need to append ' -- ' before any paths, like:
|
150
|
+
|
151
|
+
tldr #{args.join(" ")}
|
152
|
+
MSG
|
153
|
+
exit 1
|
154
|
+
else
|
155
|
+
raise
|
156
|
+
end
|
157
|
+
end
|
110
158
|
end
|
111
159
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
class TLDR
|
2
|
+
class ArgvReconstructor
|
3
|
+
def reconstruct config, exclude:, ensure_args:, exclude_dotfile_matches:
|
4
|
+
argv = to_cli_argv(
|
5
|
+
config,
|
6
|
+
CONFLAGS.keys - exclude - [
|
7
|
+
(:seed unless config.seed_set_intentionally),
|
8
|
+
:watch,
|
9
|
+
:i_am_being_watched
|
10
|
+
],
|
11
|
+
exclude_dotfile_matches:
|
12
|
+
)
|
13
|
+
|
14
|
+
ensure_args.each do |arg|
|
15
|
+
argv << arg unless argv.include?(arg)
|
16
|
+
end
|
17
|
+
|
18
|
+
argv.join(" ")
|
19
|
+
end
|
20
|
+
|
21
|
+
def reconstruct_single_path_args config, path, exclude_dotfile_matches:
|
22
|
+
argv = to_cli_argv(config, CONFLAGS.keys - [
|
23
|
+
:seed, :parallel, :names, :fail_fast, :paths, :prepend_paths,
|
24
|
+
:no_prepend, :exclude_paths, :watch, :i_am_being_watched
|
25
|
+
], exclude_dotfile_matches:)
|
26
|
+
|
27
|
+
(argv + [stringify(:paths, path)]).join(" ")
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def to_cli_argv config, options = CONFLAGS.keys, exclude_dotfile_matches:
|
33
|
+
defaults = Config.build_defaults(cli_defaults: true)
|
34
|
+
defaults = defaults.merge(config.dotfile_args(config.config_path)) if exclude_dotfile_matches
|
35
|
+
options.map { |key|
|
36
|
+
flag = CONFLAGS[key]
|
37
|
+
|
38
|
+
# Special cases
|
39
|
+
if key == :prepend_paths
|
40
|
+
if config.prepend_paths.map { |s| stringify(key, s) }.sort == config.paths.map { |s| stringify(:paths, s) }.sort
|
41
|
+
# Don't print prepended tests if they're the same as the test paths
|
42
|
+
next
|
43
|
+
elsif config.no_prepend
|
44
|
+
# Don't print prepended tests if they're disabled
|
45
|
+
next
|
46
|
+
end
|
47
|
+
elsif key == :helper_paths && config.no_helper
|
48
|
+
# Don't print the helper if it's disabled
|
49
|
+
next
|
50
|
+
elsif key == :parallel
|
51
|
+
val = if !config.seed_set_intentionally && !config.parallel
|
52
|
+
"--no-parallel"
|
53
|
+
elsif !config.seed.nil? && config.seed_set_intentionally && config.parallel
|
54
|
+
"--parallel"
|
55
|
+
end
|
56
|
+
next val
|
57
|
+
elsif key == :timeout
|
58
|
+
if config[:timeout] < 0
|
59
|
+
next
|
60
|
+
elsif config[:timeout] == Config::DEFAULT_TIMEOUT
|
61
|
+
next "--timeout"
|
62
|
+
elsif config[:timeout] != Config::DEFAULT_TIMEOUT
|
63
|
+
next "--timeout #{config[:timeout]}"
|
64
|
+
else
|
65
|
+
next
|
66
|
+
end
|
67
|
+
elsif key == :config_path
|
68
|
+
case config[:config_path]
|
69
|
+
when nil then next "--no-config"
|
70
|
+
when Config::DEFAULT_YAML_PATH then next
|
71
|
+
else next "--config #{config[:config_path]}"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if defaults[key] == config[key] && (key != :seed || !config.seed_set_intentionally)
|
76
|
+
next
|
77
|
+
elsif CONFLAGS[key]&.start_with?("--[no-]")
|
78
|
+
case config[key]
|
79
|
+
when false then CONFLAGS[key].gsub(/[\[\]]/, "")
|
80
|
+
when nil || true then CONFLAGS[key].gsub("[no-]", "")
|
81
|
+
else "#{CONFLAGS[key].gsub("[no-]", "")} #{stringify(key, config[key])}"
|
82
|
+
end
|
83
|
+
elsif config[key].is_a?(Array)
|
84
|
+
config[key].map { |value| [flag, stringify(key, value)] }
|
85
|
+
elsif config[key].is_a?(TrueClass) || config[key].is_a?(FalseClass)
|
86
|
+
flag if config[key]
|
87
|
+
elsif config[key].is_a?(Class)
|
88
|
+
[flag, config[key].name]
|
89
|
+
elsif !config[key].nil?
|
90
|
+
[flag, stringify(key, config[key])]
|
91
|
+
end
|
92
|
+
}.flatten.compact
|
93
|
+
end
|
94
|
+
|
95
|
+
def stringify key, val
|
96
|
+
if PATH_FLAGS.include?(key) && val.start_with?(Dir.pwd)
|
97
|
+
val = val[Dir.pwd.length + 1..]
|
98
|
+
end
|
99
|
+
|
100
|
+
if val.nil? || val.is_a?(Integer)
|
101
|
+
val
|
102
|
+
else
|
103
|
+
"\"#{val}\""
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
data/lib/tldr/assertions.rb
CHANGED
@@ -9,7 +9,6 @@
|
|
9
9
|
|
10
10
|
require "pp"
|
11
11
|
require "super_diff"
|
12
|
-
require_relative "assertions/minitest_compatibility"
|
13
12
|
|
14
13
|
class TLDR
|
15
14
|
module Assertions
|
@@ -109,7 +108,7 @@ class TLDR
|
|
109
108
|
refute_in_delta expected, actual, expected * epsilon, msg
|
110
109
|
end
|
111
110
|
|
112
|
-
def
|
111
|
+
def assert_includes actual, expected, message = nil
|
113
112
|
message = Assertions.msg(message) {
|
114
113
|
"Expected #{Assertions.h(actual)} to include #{Assertions.h(expected)}"
|
115
114
|
}
|
@@ -117,7 +116,7 @@ class TLDR
|
|
117
116
|
assert actual.include?(expected), message
|
118
117
|
end
|
119
118
|
|
120
|
-
def
|
119
|
+
def refute_includes actual, expected, message = nil
|
121
120
|
message = Assertions.msg(message) {
|
122
121
|
"Expected #{Assertions.h(actual)} to not include #{Assertions.h(expected)}"
|
123
122
|
}
|
data/lib/tldr/autorun.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# These methods are provided to support drop-in compatibility with Minitest. You
|
2
|
+
# can use them by mixing them into your test or into the `TLDR` base class
|
3
|
+
# itself:
|
4
|
+
#
|
5
|
+
# class YourTest < TLDR
|
6
|
+
# include TLDR::MinitestCompatibility
|
7
|
+
#
|
8
|
+
# def test_something
|
9
|
+
# # …
|
10
|
+
# end
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# The implementation of these methods is extremely similar or identical to those
|
14
|
+
# found in minitest itself, which is Copyright © Ryan Davis, seattle.rb and
|
15
|
+
# distributed under the MIT License
|
16
|
+
class TLDR
|
17
|
+
module MinitestCompatibility
|
18
|
+
def capture_io &blk
|
19
|
+
Assertions.capture_io(&blk)
|
20
|
+
end
|
21
|
+
|
22
|
+
def mu_pp obj
|
23
|
+
s = obj.inspect.encode(Encoding.default_external)
|
24
|
+
|
25
|
+
if String === obj && (obj.encoding != Encoding.default_external ||
|
26
|
+
!obj.valid_encoding?)
|
27
|
+
enc = "# encoding: #{obj.encoding}"
|
28
|
+
val = "# valid: #{obj.valid_encoding?}"
|
29
|
+
"#{enc}\n#{val}\n#{s}"
|
30
|
+
else
|
31
|
+
s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -3,7 +3,7 @@ class TLDR
|
|
3
3
|
class Default < Base
|
4
4
|
def initialize config, out = $stdout, err = $stderr
|
5
5
|
super
|
6
|
-
@icons = @config.
|
6
|
+
@icons = @config.emoji ? IconProvider::Emoji.new : IconProvider::Base.new
|
7
7
|
end
|
8
8
|
|
9
9
|
def before_suite tests
|
@@ -11,9 +11,9 @@ class TLDR
|
|
11
11
|
@suite_start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
|
12
12
|
@out.print <<~MSG
|
13
13
|
Command: #{tldr_command} #{@config.to_full_args}
|
14
|
-
#{@icons.seed}
|
14
|
+
#{@icons.rpad(:seed)}#{CONFLAGS[:seed]} #{@config.seed}
|
15
15
|
|
16
|
-
#{@icons.run}
|
16
|
+
#{@icons.rpad(:run)}Running:
|
17
17
|
|
18
18
|
MSG
|
19
19
|
end
|
@@ -39,22 +39,22 @@ class TLDR
|
|
39
39
|
@err.print "\n\n"
|
40
40
|
|
41
41
|
if @config.yes_i_know
|
42
|
-
@err.print "
|
42
|
+
@err.print "#{@icons.rpad(:alarm)}TLDR after completing #{test_results.size} of #{planned_tests.size} tests! Print full summary by omitting --yes-i-know"
|
43
43
|
else
|
44
44
|
wrap_in_horizontal_rule do
|
45
45
|
@err.print [
|
46
46
|
"too long; didn't run!",
|
47
|
-
"#{@icons.run}
|
47
|
+
"#{@icons.rpad(:run)}Completed #{test_results.size} of #{planned_tests.size} tests (#{((test_results.size.to_f / planned_tests.size) * 100).round}%) before running out of time.",
|
48
48
|
(<<~WIP.chomp if wip_tests.any?),
|
49
|
-
#{@icons.wip}
|
49
|
+
#{@icons.rpad(:wip)}#{plural(wip_tests.size, "test was", "tests were")} cancelled in progress:
|
50
50
|
#{wip_tests.map { |wip_test| " #{time_diff(wip_test.start_time, stop_time)}ms - #{describe(wip_test.test)}#{print_wip_backtrace(wip_test, indent: " ") if @config.print_interrupted_test_backtraces}" }.join("\n")}
|
51
51
|
WIP
|
52
52
|
(<<~SLOW.chomp if test_results.any?),
|
53
|
-
#{@icons.slow}
|
53
|
+
#{@icons.rpad(:slow)}Your #{[10, test_results.size].min} slowest completed tests:
|
54
54
|
#{test_results.sort_by(&:runtime).last(10).reverse.map { |result| " #{result.runtime}ms - #{describe(result.test)}" }.join("\n")}
|
55
55
|
SLOW
|
56
56
|
describe_tests_that_didnt_finish(planned_tests, test_results),
|
57
|
-
"
|
57
|
+
"#{@icons.rpad(:not_run)}Suppress this summary with --yes-i-know"
|
58
58
|
].compact.join("\n\n")
|
59
59
|
end
|
60
60
|
end
|
@@ -69,8 +69,8 @@ class TLDR
|
|
69
69
|
wrap_in_horizontal_rule do
|
70
70
|
@err.print [
|
71
71
|
"Failing fast after #{describe(last_result.test, last_result.relevant_location)} #{last_result.error? ? "errored" : "failed"}.",
|
72
|
-
("#{@icons.wip}
|
73
|
-
("#{@icons.not_run} #{plural(unrun_tests.size, "test was", "tests were")} not run at all." if unrun_tests.any?),
|
72
|
+
("#{@icons.rpad(:wip)}#{plural(wip_tests.size, "test was", "tests were")} cancelled in progress." if wip_tests.any?),
|
73
|
+
("#{@icons.rpad(:not_run)} #{plural(unrun_tests.size, "test was", "tests were")} not run at all." if unrun_tests.any?),
|
74
74
|
describe_tests_that_didnt_finish(planned_tests, test_results)
|
75
75
|
].compact.join("\n\n")
|
76
76
|
end
|
@@ -165,7 +165,7 @@ class TLDR
|
|
165
165
|
("--comment \"Also include #{plural(failed.size, "test")} that failed:\"" if failed_locators.any?)
|
166
166
|
].compact + failed_locators
|
167
167
|
<<~MSG
|
168
|
-
#{@icons.rock_on}
|
168
|
+
#{@icons.rpad(:rock_on)}Run the #{plural(unrun.size, "test")} that didn't finish:
|
169
169
|
#{tldr_command} #{@config.to_full_args(exclude: [:paths], exclude_dotfile_matches: true)} #{suggested_locators.join(" \\\n ")}
|
170
170
|
MSG
|
171
171
|
end
|
data/lib/tldr/runner.rb
CHANGED
@@ -9,23 +9,42 @@ class TLDR
|
|
9
9
|
@run_aborted = Concurrent::AtomicBoolean.new(false)
|
10
10
|
end
|
11
11
|
|
12
|
+
def instantiate_reporter config
|
13
|
+
begin
|
14
|
+
reporter_class = Kernel.const_get(config.reporter)
|
15
|
+
rescue NameError
|
16
|
+
raise Error, "Unknown reporter '#{config.reporter}' (are you sure it was loaded by your test or helper?)"
|
17
|
+
end
|
18
|
+
if reporter_class.is_a?(Class)
|
19
|
+
if reporter_class.instance_method(:initialize).parameters.any? { |type, _| [:req, :opt, :rest].include?(type) }
|
20
|
+
reporter_class.new(config)
|
21
|
+
else
|
22
|
+
reporter_class.new
|
23
|
+
end
|
24
|
+
else
|
25
|
+
raise Error, "Reporter '#{config.reporter}' expected to be a class, but was a #{reporter_class.class}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
12
29
|
def run config, plan
|
13
30
|
@wip.clear
|
14
31
|
@results.clear
|
15
|
-
reporter =
|
16
|
-
reporter.before_suite(plan.tests)
|
32
|
+
reporter = instantiate_reporter(config)
|
33
|
+
reporter.before_suite(plan.tests) if reporter.respond_to?(:before_suite)
|
17
34
|
|
18
35
|
time_bomb = Thread.new {
|
36
|
+
next if config.timeout < 0
|
37
|
+
|
19
38
|
explode = proc do
|
20
|
-
next if ENV["CI"] && !$stderr.tty?
|
21
39
|
next if @run_aborted.true?
|
22
40
|
@run_aborted.make_true
|
23
41
|
@wip.each(&:capture_backtrace_at_exit)
|
24
|
-
reporter.after_tldr(plan.tests, @wip.dup, @results.dup)
|
42
|
+
reporter.after_tldr(plan.tests, @wip.dup, @results.dup) if reporter.respond_to?(:after_tldr)
|
25
43
|
exit!(3)
|
26
44
|
end
|
27
45
|
|
28
|
-
sleep(
|
46
|
+
sleep(config.timeout)
|
47
|
+
|
29
48
|
# Don't hard-kill the runner if user is debugging, it'll
|
30
49
|
# screw up their terminal slash be a bad time
|
31
50
|
if IRB.CurrentContext
|
@@ -42,7 +61,7 @@ class TLDR
|
|
42
61
|
end
|
43
62
|
|
44
63
|
unless @run_aborted.true?
|
45
|
-
reporter.after_suite(results)
|
64
|
+
reporter.after_suite(results) if reporter.respond_to?(:after_suite)
|
46
65
|
exit(exit_code(results))
|
47
66
|
end
|
48
67
|
end
|
@@ -74,7 +93,7 @@ class TLDR
|
|
74
93
|
next if @run_aborted.true?
|
75
94
|
@results << result
|
76
95
|
@wip.delete(wip_test)
|
77
|
-
reporter.after_test(result)
|
96
|
+
reporter.after_test(result) if reporter.respond_to?(:after_test)
|
78
97
|
fail_fast(reporter, plan, result) if result.failing? && config.fail_fast
|
79
98
|
end
|
80
99
|
end
|
@@ -83,7 +102,7 @@ class TLDR
|
|
83
102
|
unless @run_aborted.true?
|
84
103
|
@run_aborted.make_true
|
85
104
|
abort = proc do
|
86
|
-
reporter.after_fail_fast(plan.tests, @wip.dup, @results.dup, fast_failed_result)
|
105
|
+
reporter.after_fail_fast(plan.tests, @wip.dup, @results.dup, fast_failed_result) if reporter.respond_to?(:after_fail_fast)
|
87
106
|
exit!(exit_code([fast_failed_result]))
|
88
107
|
end
|
89
108
|
|