mutant 0.6.7 → 0.7.1
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 +10 -0
- data/README.md +1 -1
- data/config/flay.yml +1 -1
- data/config/reek.yml +11 -40
- data/config/rubocop.yml +1 -1
- data/lib/mutant.rb +10 -2
- data/lib/mutant/actor.rb +64 -0
- data/lib/mutant/actor/actor.rb +50 -0
- data/lib/mutant/actor/env.rb +35 -0
- data/lib/mutant/actor/mailbox.rb +53 -0
- data/lib/mutant/actor/receiver.rb +48 -0
- data/lib/mutant/actor/sender.rb +27 -0
- data/lib/mutant/ast/types.rb +1 -1
- data/lib/mutant/cli.rb +2 -0
- data/lib/mutant/config.rb +2 -1
- data/lib/mutant/env.rb +6 -2
- data/lib/mutant/expression/methods.rb +1 -1
- data/lib/mutant/integration.rb +11 -1
- data/lib/mutant/isolation.rb +1 -2
- data/lib/mutant/meta/example.rb +1 -1
- data/lib/mutant/mutation.rb +47 -21
- data/lib/mutant/mutator/node.rb +1 -1
- data/lib/mutant/mutator/node/literal/symbol.rb +1 -1
- data/lib/mutant/mutator/node/send.rb +4 -3
- data/lib/mutant/reporter/cli.rb +2 -0
- data/lib/mutant/reporter/cli/format.rb +23 -36
- data/lib/mutant/reporter/cli/printer.rb +66 -27
- data/lib/mutant/result.rb +45 -58
- data/lib/mutant/runner.rb +47 -154
- data/lib/mutant/runner/master.rb +174 -0
- data/lib/mutant/runner/scheduler.rb +141 -0
- data/lib/mutant/runner/worker.rb +93 -0
- data/lib/mutant/subject/method/instance.rb +1 -15
- data/lib/mutant/test.rb +2 -15
- data/lib/mutant/version.rb +1 -1
- data/meta/send.rb +16 -0
- data/mutant-rspec.gemspec +1 -1
- data/mutant.gemspec +1 -1
- data/spec/integration/mutant/rspec_spec.rb +0 -6
- data/spec/spec_helper.rb +9 -1
- data/spec/support/fake_actor.rb +93 -0
- data/spec/support/shared_context.rb +135 -0
- data/spec/unit/mutant/actor/actor_spec.rb +35 -0
- data/spec/unit/mutant/actor/binding_spec.rb +32 -0
- data/spec/unit/mutant/actor/env_spec.rb +49 -0
- data/spec/unit/mutant/actor/message_spec.rb +23 -0
- data/spec/unit/mutant/actor/receiver_spec.rb +60 -0
- data/spec/unit/mutant/actor/sender_spec.rb +22 -0
- data/spec/unit/mutant/cli_spec.rb +17 -4
- data/spec/unit/mutant/env_spec.rb +2 -2
- data/spec/unit/mutant/mailbox_spec.rb +33 -0
- data/spec/unit/mutant/mutation_spec.rb +52 -18
- data/spec/unit/mutant/mutator/registry_spec.rb +4 -4
- data/spec/unit/mutant/reporter/cli_spec.rb +131 -249
- data/spec/unit/mutant/result/env_spec.rb +55 -0
- data/spec/unit/mutant/result/subject_spec.rb +43 -0
- data/spec/unit/mutant/runner/master_spec.rb +199 -0
- data/spec/unit/mutant/runner/scheduler_spec.rb +161 -0
- data/spec/unit/mutant/runner/worker_spec.rb +73 -0
- data/spec/unit/mutant/runner_spec.rb +60 -118
- data/spec/unit/mutant/subject/method/instance_spec.rb +18 -31
- data/spec/unit/mutant/warning_filter_spec.rb +1 -1
- metadata +39 -14
- data/lib/mutant/runner/collector.rb +0 -133
- data/lib/mutant/warning_expectation.rb +0 -47
- data/spec/unit/mutant/runner/collector_spec.rb +0 -198
- data/spec/unit/mutant/test_spec.rb +0 -23
- data/spec/unit/mutant/warning_expectation_spec.rb +0 -80
- data/test_app/Gemfile.rspec2 +0 -6
@@ -0,0 +1,27 @@
|
|
1
|
+
module Mutant
|
2
|
+
module Actor
|
3
|
+
|
4
|
+
# Sender for messages to acting thread
|
5
|
+
class Sender
|
6
|
+
include Concord.new(:thread, :mutex, :mailbox)
|
7
|
+
|
8
|
+
# Send a message to actor
|
9
|
+
#
|
10
|
+
# @param [Object] message
|
11
|
+
#
|
12
|
+
# @return [self]
|
13
|
+
#
|
14
|
+
# @api private
|
15
|
+
#
|
16
|
+
def call(message)
|
17
|
+
mutex.synchronize do
|
18
|
+
mailbox << message
|
19
|
+
thread.run
|
20
|
+
end
|
21
|
+
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
end # Sender
|
26
|
+
end # Actor
|
27
|
+
end # Mutant
|
data/lib/mutant/ast/types.rb
CHANGED
@@ -18,7 +18,7 @@ module Mutant
|
|
18
18
|
INDEX_OPERATORS = symbolset.(%w[[] []=])
|
19
19
|
UNARY_METHOD_OPERATORS = symbolset.(%w[~@ +@ -@ !])
|
20
20
|
|
21
|
-
# Operators ruby
|
21
|
+
# Operators ruby implements as methods
|
22
22
|
METHOD_OPERATORS = symbolset.(%w[
|
23
23
|
<=> === []= [] <= >= == !~ != =~ <<
|
24
24
|
>> ** * % / | ^ & < > + - ~@ +@ -@ !
|
data/lib/mutant/cli.rb
CHANGED
@@ -128,6 +128,8 @@ module Mutant
|
|
128
128
|
def setup_integration(name)
|
129
129
|
require "mutant/integration/#{name}"
|
130
130
|
update(integration: Integration.lookup(name))
|
131
|
+
rescue LoadError
|
132
|
+
fail Error, "Could not load integration #{name.inspect} (you may want to try installing the gem mutant-#{name})"
|
131
133
|
end
|
132
134
|
|
133
135
|
# Add options
|
data/lib/mutant/config.rb
CHANGED
data/lib/mutant/env.rb
CHANGED
@@ -3,6 +3,10 @@ module Mutant
|
|
3
3
|
class Env
|
4
4
|
include Adamantium::Flat, Concord::Public.new(:config, :cache)
|
5
5
|
|
6
|
+
SEMANTICS_MESSAGE =
|
7
|
+
"Fix your lib to follow normal ruby semantics!\n" \
|
8
|
+
'{Module,Class}#name should return resolvable constant name as String or nil'.freeze
|
9
|
+
|
6
10
|
# Return new env
|
7
11
|
#
|
8
12
|
# @param [Config] config
|
@@ -86,7 +90,7 @@ module Mutant
|
|
86
90
|
def scope_name(scope)
|
87
91
|
scope.name
|
88
92
|
rescue => exception
|
89
|
-
warn("#{scope.class}#name from: #{scope.inspect} raised an error: #{exception.inspect}
|
93
|
+
warn("#{scope.class}#name from: #{scope.inspect} raised an error: #{exception.inspect}. #{SEMANTICS_MESSAGE}")
|
90
94
|
nil
|
91
95
|
end
|
92
96
|
|
@@ -106,7 +110,7 @@ module Mutant
|
|
106
110
|
name = scope_name(scope) or return
|
107
111
|
|
108
112
|
unless name.is_a?(String)
|
109
|
-
warn("#{scope.class}#name from: #{scope.inspect} returned #{name.inspect}
|
113
|
+
warn("#{scope.class}#name from: #{scope.inspect} returned #{name.inspect}. #{SEMANTICS_MESSAGE}")
|
110
114
|
return
|
111
115
|
end
|
112
116
|
|
data/lib/mutant/integration.rb
CHANGED
@@ -16,7 +16,7 @@ module Mutant
|
|
16
16
|
# @api private
|
17
17
|
#
|
18
18
|
def self.lookup(name)
|
19
|
-
REGISTRY.fetch(name).
|
19
|
+
REGISTRY.fetch(name).new
|
20
20
|
end
|
21
21
|
|
22
22
|
# Register integration
|
@@ -44,6 +44,16 @@ module Mutant
|
|
44
44
|
self
|
45
45
|
end
|
46
46
|
|
47
|
+
# Return test result for tests
|
48
|
+
#
|
49
|
+
# @param [Enumerable<Test>] tests
|
50
|
+
#
|
51
|
+
# @return [Result::Test]
|
52
|
+
#
|
53
|
+
# @api private
|
54
|
+
#
|
55
|
+
abstract_method :call
|
56
|
+
|
47
57
|
# Return all available tests by integration
|
48
58
|
#
|
49
59
|
# @return [Enumerable<Test>]
|
data/lib/mutant/isolation.rb
CHANGED
data/lib/mutant/meta/example.rb
CHANGED
data/lib/mutant/mutation.rb
CHANGED
@@ -7,21 +7,30 @@ module Mutant
|
|
7
7
|
CODE_DELIMITER = "\0".freeze
|
8
8
|
CODE_RANGE = (0..4).freeze
|
9
9
|
|
10
|
-
#
|
10
|
+
# Kill mutation under isolation with integration
|
11
11
|
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# is a detail of method mutations.
|
12
|
+
# @param [Isolation] isolation
|
13
|
+
# @param [Integration] integration
|
15
14
|
#
|
16
|
-
# @return [
|
15
|
+
# @return [Result::Test]
|
17
16
|
#
|
18
17
|
# @api private
|
19
18
|
#
|
20
|
-
def
|
21
|
-
|
22
|
-
subject.
|
23
|
-
|
24
|
-
|
19
|
+
def kill(isolation, integration)
|
20
|
+
start = Time.now
|
21
|
+
tests = subject.tests
|
22
|
+
|
23
|
+
isolation.call do
|
24
|
+
insert
|
25
|
+
integration.call(tests)
|
26
|
+
end.update(tests: tests)
|
27
|
+
rescue Isolation::Error => error
|
28
|
+
Result::Test.new(
|
29
|
+
tests: tests,
|
30
|
+
output: error.message,
|
31
|
+
runtime: Time.now - start,
|
32
|
+
passed: false
|
33
|
+
)
|
25
34
|
end
|
26
35
|
|
27
36
|
# Return identification
|
@@ -67,20 +76,37 @@ module Mutant
|
|
67
76
|
subject.source
|
68
77
|
end
|
69
78
|
|
70
|
-
# Test if mutation is killed by test
|
79
|
+
# Test if mutation is killed by test reports
|
71
80
|
#
|
72
|
-
# @param [Report::Test]
|
81
|
+
# @param [Array<Report::Test>] test_reports
|
73
82
|
#
|
74
83
|
# @return [Boolean]
|
75
84
|
#
|
76
85
|
# @api private
|
77
86
|
#
|
78
|
-
def
|
79
|
-
self
|
87
|
+
def self.success?(test_result)
|
88
|
+
self::TEST_PASS_SUCCESS.equal?(test_result.passed)
|
80
89
|
end
|
81
90
|
|
82
91
|
private
|
83
92
|
|
93
|
+
# Insert mutated node
|
94
|
+
#
|
95
|
+
# FIXME: Cache subject visibility in a better way! Ideally dont mutate it
|
96
|
+
# implicitly. Also subject.public? should NOT be a public interface it
|
97
|
+
# is a detail of method mutations.
|
98
|
+
#
|
99
|
+
# @return [self]
|
100
|
+
#
|
101
|
+
# @api private
|
102
|
+
#
|
103
|
+
def insert
|
104
|
+
subject.public?
|
105
|
+
subject.prepare
|
106
|
+
Loader::Eval.call(root, subject)
|
107
|
+
self
|
108
|
+
end
|
109
|
+
|
84
110
|
# Return sha1 sum of source and subject identification
|
85
111
|
#
|
86
112
|
# @return [String]
|
@@ -105,24 +131,24 @@ module Mutant
|
|
105
131
|
# Evil mutation that should case mutations to fail tests
|
106
132
|
class Evil < self
|
107
133
|
|
108
|
-
|
109
|
-
|
134
|
+
SYMBOL = 'evil'.freeze
|
135
|
+
TEST_PASS_SUCCESS = false
|
110
136
|
|
111
137
|
end # Evil
|
112
138
|
|
113
139
|
# Neutral mutation that should not cause mutations to fail tests
|
114
140
|
class Neutral < self
|
115
141
|
|
116
|
-
SYMBOL
|
117
|
-
|
142
|
+
SYMBOL = 'neutral'.freeze
|
143
|
+
TEST_PASS_SUCCESS = true
|
118
144
|
|
119
145
|
end # Neutral
|
120
146
|
|
121
147
|
# Noop mutation, special case of neutral
|
122
|
-
class Noop <
|
148
|
+
class Noop < Neutral
|
123
149
|
|
124
|
-
SYMBOL
|
125
|
-
|
150
|
+
SYMBOL = 'noop'.freeze
|
151
|
+
TEST_PASS_SUCCESS = true
|
126
152
|
|
127
153
|
end # Noop
|
128
154
|
|
data/lib/mutant/mutator/node.rb
CHANGED
@@ -17,7 +17,8 @@ module Mutant
|
|
17
17
|
reverse_each: [:each],
|
18
18
|
reverse_merge: [:merge],
|
19
19
|
map: [:each],
|
20
|
-
send: [:public_send],
|
20
|
+
send: [:public_send, :__send__],
|
21
|
+
__send__: [:public_send],
|
21
22
|
gsub: [:sub],
|
22
23
|
eql?: [:equal?],
|
23
24
|
to_s: [:to_str],
|
@@ -26,8 +27,8 @@ module Mutant
|
|
26
27
|
:== => [:eql?, :equal?],
|
27
28
|
:>= => [:>, :==, :eql?, :equal?],
|
28
29
|
:<= => [:<, :==, :eql?, :equal?],
|
29
|
-
:> => [:==, :eql?, :equal?],
|
30
|
-
:< => [:==, :eql?, :equal?]
|
30
|
+
:> => [:==, :>=, :eql?, :equal?],
|
31
|
+
:< => [:==, :<=, :eql?, :equal?]
|
31
32
|
)
|
32
33
|
|
33
34
|
private
|
data/lib/mutant/reporter/cli.rb
CHANGED
@@ -17,7 +17,7 @@ module Mutant
|
|
17
17
|
|
18
18
|
# Return progress representation
|
19
19
|
#
|
20
|
-
# @param [Runner::
|
20
|
+
# @param [Runner::Status] status
|
21
21
|
#
|
22
22
|
# @return [String]
|
23
23
|
#
|
@@ -67,6 +67,18 @@ module Mutant
|
|
67
67
|
# Format for progressive non rewindable output
|
68
68
|
class Progressive < self
|
69
69
|
|
70
|
+
# Initialize object
|
71
|
+
#
|
72
|
+
# @return [undefined]
|
73
|
+
#
|
74
|
+
# @api private
|
75
|
+
#
|
76
|
+
def initialize(*)
|
77
|
+
@seen = Set.new
|
78
|
+
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
70
82
|
# Return start representation
|
71
83
|
#
|
72
84
|
# @return [String]
|
@@ -83,10 +95,13 @@ module Mutant
|
|
83
95
|
#
|
84
96
|
# @api private
|
85
97
|
#
|
86
|
-
def progress(
|
87
|
-
|
88
|
-
|
89
|
-
|
98
|
+
def progress(status)
|
99
|
+
current = status.env_result.subject_results.flat_map(&:mutation_results)
|
100
|
+
new = current.reject(&@seen.method(:include?))
|
101
|
+
@seen = current.to_set
|
102
|
+
new.map do |mutation_result|
|
103
|
+
format(Printer::MutationProgressResult, mutation_result)
|
104
|
+
end.join(EMPTY_STRING)
|
90
105
|
end
|
91
106
|
|
92
107
|
private
|
@@ -109,20 +124,6 @@ module Mutant
|
|
109
124
|
|
110
125
|
BUFFER_FLAGS = 'a+'.freeze
|
111
126
|
|
112
|
-
# Rate per second progress report fires
|
113
|
-
OUTPUT_RATE = 1.0 / 20
|
114
|
-
|
115
|
-
# Initialize object
|
116
|
-
#
|
117
|
-
# @return [undefined]
|
118
|
-
#
|
119
|
-
# @api private
|
120
|
-
#
|
121
|
-
def initialize(*)
|
122
|
-
super
|
123
|
-
@last_frame = nil
|
124
|
-
end
|
125
|
-
|
126
127
|
# Format start
|
127
128
|
#
|
128
129
|
# @param [Env] env
|
@@ -137,16 +138,14 @@ module Mutant
|
|
137
138
|
|
138
139
|
# Format progress
|
139
140
|
#
|
140
|
-
# @param [Runner::
|
141
|
+
# @param [Runner::Status] status
|
141
142
|
#
|
142
143
|
# @return [String]
|
143
144
|
#
|
144
145
|
# @api private
|
145
146
|
#
|
146
|
-
def progress(
|
147
|
-
|
148
|
-
format(Printer::Collector, collector)
|
149
|
-
end.to_s
|
147
|
+
def progress(status)
|
148
|
+
format(Printer::Status, status)
|
150
149
|
end
|
151
150
|
|
152
151
|
private
|
@@ -166,18 +165,6 @@ module Mutant
|
|
166
165
|
buffer << tput.restore
|
167
166
|
end
|
168
167
|
|
169
|
-
# Call block throttled
|
170
|
-
#
|
171
|
-
# @return [self]
|
172
|
-
#
|
173
|
-
# @api private
|
174
|
-
#
|
175
|
-
def throttle
|
176
|
-
now = Time.now
|
177
|
-
return if @last_frame && (now - @last_frame) < OUTPUT_RATE
|
178
|
-
yield.tap { @last_frame = now }
|
179
|
-
end
|
180
|
-
|
181
168
|
end # Framed
|
182
169
|
end # Format
|
183
170
|
end # CLI
|
@@ -5,6 +5,8 @@ module Mutant
|
|
5
5
|
class Printer
|
6
6
|
include AbstractType, Delegator, Adamantium::Flat, Concord.new(:output, :object)
|
7
7
|
|
8
|
+
delegate(:success?)
|
9
|
+
|
8
10
|
NL = "\n".freeze
|
9
11
|
|
10
12
|
# Run printer on object to output
|
@@ -98,16 +100,6 @@ module Mutant
|
|
98
100
|
output.puts(string)
|
99
101
|
end
|
100
102
|
|
101
|
-
# Test if runner was successful
|
102
|
-
#
|
103
|
-
# @return [Boolean]
|
104
|
-
#
|
105
|
-
# @api private
|
106
|
-
#
|
107
|
-
def success?
|
108
|
-
object.success?
|
109
|
-
end
|
110
|
-
|
111
103
|
# Colorize message
|
112
104
|
#
|
113
105
|
# @param [Color] color
|
@@ -142,8 +134,10 @@ module Mutant
|
|
142
134
|
#
|
143
135
|
alias_method :color?, :tty?
|
144
136
|
|
145
|
-
# Printer for
|
146
|
-
class
|
137
|
+
# Printer for runner status
|
138
|
+
class Status < self
|
139
|
+
|
140
|
+
delegate(:active_jobs, :env_result)
|
147
141
|
|
148
142
|
# Print progress for collector
|
149
143
|
#
|
@@ -152,14 +146,44 @@ module Mutant
|
|
152
146
|
# @api private
|
153
147
|
#
|
154
148
|
def run
|
155
|
-
visit(EnvProgress, object.
|
156
|
-
active_subject_results = object.active_subject_results
|
149
|
+
visit(EnvProgress, object.env_result)
|
157
150
|
info('Active subjects: %d', active_subject_results.length)
|
158
151
|
visit_collection(SubjectProgress, active_subject_results)
|
152
|
+
job_status
|
159
153
|
self
|
160
154
|
end
|
161
155
|
|
162
|
-
|
156
|
+
private
|
157
|
+
|
158
|
+
# Print worker status
|
159
|
+
#
|
160
|
+
# @return [undefined]
|
161
|
+
#
|
162
|
+
# @api private
|
163
|
+
#
|
164
|
+
def job_status
|
165
|
+
return if active_jobs.empty?
|
166
|
+
info('Active Jobs:')
|
167
|
+
object.active_jobs.sort_by(&:index).each do |job|
|
168
|
+
info('%d: %s', job.index, job.mutation.identification)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Return active subject results
|
173
|
+
#
|
174
|
+
# @return [Array<Result::Subject>]
|
175
|
+
#
|
176
|
+
# @api private
|
177
|
+
#
|
178
|
+
def active_subject_results
|
179
|
+
active_subjects = active_jobs.map(&:mutation).flat_map(&:subject).to_set
|
180
|
+
|
181
|
+
env_result.subject_results.select do |subject_result|
|
182
|
+
active_subjects.include?(subject_result.subject)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
end # Status
|
163
187
|
|
164
188
|
# Progress printer for configuration
|
165
189
|
class Config < self
|
@@ -406,9 +430,9 @@ module Mutant
|
|
406
430
|
# Reporter for mutation results
|
407
431
|
class MutationResult < self
|
408
432
|
|
409
|
-
delegate :mutation, :
|
433
|
+
delegate :mutation, :test_result
|
410
434
|
|
411
|
-
DIFF_ERROR_MESSAGE = 'BUG: Mutation NOT resulted in exactly one diff. Please report a reproduction!'.freeze
|
435
|
+
DIFF_ERROR_MESSAGE = 'BUG: Mutation NOT resulted in exactly one diff hunk. Please report a reproduction!'.freeze
|
412
436
|
|
413
437
|
MAP = {
|
414
438
|
Mutant::Mutation::Evil => :evil_details,
|
@@ -424,13 +448,13 @@ module Mutant
|
|
424
448
|
"%s\n" \
|
425
449
|
"Unparsed Source:\n" \
|
426
450
|
"%s\n" \
|
427
|
-
"Test
|
451
|
+
"Test Result:\n".freeze
|
428
452
|
|
429
453
|
NOOP_MESSAGE =
|
430
454
|
"---- Noop failure -----\n" \
|
431
455
|
"No code was inserted. And the test did NOT PASS.\n" \
|
432
456
|
"This is typically a problem of your specs not passing unmutated.\n" \
|
433
|
-
"Test
|
457
|
+
"Test Result:\n".freeze
|
434
458
|
|
435
459
|
FOOTER = '-----------------------'.freeze
|
436
460
|
|
@@ -479,8 +503,8 @@ module Mutant
|
|
479
503
|
# @api private
|
480
504
|
#
|
481
505
|
def noop_details
|
482
|
-
info(NOOP_MESSAGE
|
483
|
-
|
506
|
+
info(NOOP_MESSAGE)
|
507
|
+
visit_test_result
|
484
508
|
end
|
485
509
|
|
486
510
|
# Neutral details
|
@@ -490,8 +514,8 @@ module Mutant
|
|
490
514
|
# @api private
|
491
515
|
#
|
492
516
|
def neutral_details
|
493
|
-
info(NEUTRAL_MESSAGE, mutation.subject.node.inspect, mutation.source
|
494
|
-
|
517
|
+
info(NEUTRAL_MESSAGE, mutation.subject.node.inspect, mutation.source)
|
518
|
+
visit_test_result
|
495
519
|
end
|
496
520
|
|
497
521
|
# Visit failed test results
|
@@ -500,8 +524,8 @@ module Mutant
|
|
500
524
|
#
|
501
525
|
# @api private
|
502
526
|
#
|
503
|
-
def
|
504
|
-
|
527
|
+
def visit_test_result
|
528
|
+
visit(TestResult, test_result)
|
505
529
|
end
|
506
530
|
|
507
531
|
end # MutationResult
|
@@ -509,7 +533,7 @@ module Mutant
|
|
509
533
|
# Test result reporter
|
510
534
|
class TestResult < self
|
511
535
|
|
512
|
-
delegate :
|
536
|
+
delegate :tests, :runtime
|
513
537
|
|
514
538
|
# Run test result reporter
|
515
539
|
#
|
@@ -518,11 +542,26 @@ module Mutant
|
|
518
542
|
# @api private
|
519
543
|
#
|
520
544
|
def run
|
521
|
-
status('- %
|
545
|
+
status('- %d @ runtime: %s', tests.length, runtime)
|
546
|
+
tests.each do |test|
|
547
|
+
puts(" - #{test.identification}")
|
548
|
+
end
|
522
549
|
puts('Test Output:')
|
523
550
|
puts(object.output)
|
524
551
|
end
|
525
552
|
|
553
|
+
# Test if test result is successful
|
554
|
+
#
|
555
|
+
# Only used to determine color.
|
556
|
+
#
|
557
|
+
# @return [false]
|
558
|
+
#
|
559
|
+
# @api private
|
560
|
+
#
|
561
|
+
def success?
|
562
|
+
false
|
563
|
+
end
|
564
|
+
|
526
565
|
end # TestResult
|
527
566
|
end # Printer
|
528
567
|
end # CLI
|