sleeping_king_studios-tasks 0.1.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +26 -0
- data/DEVELOPMENT.md +50 -0
- data/LICENSE +22 -0
- data/README.md +405 -0
- data/lib/sleeping_king_studios/tasks.rb +27 -0
- data/lib/sleeping_king_studios/tasks/apps.rb +49 -0
- data/lib/sleeping_king_studios/tasks/apps/app_configuration.rb +68 -0
- data/lib/sleeping_king_studios/tasks/apps/applications_task.rb +28 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle.rb +8 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/install_runner.rb +21 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/install_task.rb +39 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/update_runner.rb +21 -0
- data/lib/sleeping_king_studios/tasks/apps/bundle/update_task.rb +39 -0
- data/lib/sleeping_king_studios/tasks/apps/ci.rb +8 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/results_reporter.rb +69 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rspec_task.rb +29 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rspec_wrapper.rb +42 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_task.rb +29 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/rubocop_wrapper.rb +29 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/simplecov_task.rb +68 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/step_wrapper.rb +49 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/steps_runner.rb +37 -0
- data/lib/sleeping_king_studios/tasks/apps/ci/steps_task.rb +92 -0
- data/lib/sleeping_king_studios/tasks/ci.rb +8 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_parser.rb +118 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_results.rb +191 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_runner.rb +53 -0
- data/lib/sleeping_king_studios/tasks/ci/cucumber_task.rb +47 -0
- data/lib/sleeping_king_studios/tasks/ci/results_helpers.rb +44 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_each_results.rb +118 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_each_task.rb +156 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_results.rb +126 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_runner.rb +62 -0
- data/lib/sleeping_king_studios/tasks/ci/rspec_task.rb +71 -0
- data/lib/sleeping_king_studios/tasks/ci/rubocop_results.rb +80 -0
- data/lib/sleeping_king_studios/tasks/ci/rubocop_runner.rb +46 -0
- data/lib/sleeping_king_studios/tasks/ci/rubocop_task.rb +44 -0
- data/lib/sleeping_king_studios/tasks/ci/simplecov_results.rb +62 -0
- data/lib/sleeping_king_studios/tasks/ci/simplecov_task.rb +25 -0
- data/lib/sleeping_king_studios/tasks/ci/steps_runner.rb +69 -0
- data/lib/sleeping_king_studios/tasks/ci/steps_task.rb +93 -0
- data/lib/sleeping_king_studios/tasks/configuration.rb +114 -0
- data/lib/sleeping_king_studios/tasks/file.rb +8 -0
- data/lib/sleeping_king_studios/tasks/file/new_task.rb +238 -0
- data/lib/sleeping_king_studios/tasks/process_runner.rb +70 -0
- data/lib/sleeping_king_studios/tasks/task.rb +95 -0
- data/lib/sleeping_king_studios/tasks/task_group.rb +37 -0
- data/lib/sleeping_king_studios/tasks/version.rb +58 -0
- metadata +271 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/cucumber_runner.rb
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require 'sleeping_king_studios/tasks/ci'
|
6
|
+
require 'sleeping_king_studios/tasks/ci/cucumber_parser'
|
7
|
+
require 'sleeping_king_studios/tasks/process_runner'
|
8
|
+
|
9
|
+
module SleepingKingStudios::Tasks::Ci
|
10
|
+
# Service object to run Cucumber as an external process with the specified
|
11
|
+
# parameters.
|
12
|
+
class CucumberRunner < SleepingKingStudios::Tasks::ProcessRunner
|
13
|
+
def call env: {}, files: [], options: [], report: true
|
14
|
+
report = 'tmp/ci/cucumber.json' if report && !report.is_a?(String)
|
15
|
+
command =
|
16
|
+
build_command(
|
17
|
+
:env => env,
|
18
|
+
:files => files,
|
19
|
+
:options => options,
|
20
|
+
:report => report
|
21
|
+
) # end build_command
|
22
|
+
|
23
|
+
stream_process(command)
|
24
|
+
|
25
|
+
report ? load_report(:report => report) : {}
|
26
|
+
end # method call
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def base_command
|
31
|
+
'bundle exec cucumber'
|
32
|
+
end # method base_command
|
33
|
+
|
34
|
+
def build_options files:, options:, report:, **_kwargs
|
35
|
+
options += ['--format=json', "--out=#{report}"] if report
|
36
|
+
|
37
|
+
super :files => files, :options => options
|
38
|
+
end # method build_options
|
39
|
+
|
40
|
+
def load_report report:
|
41
|
+
raw = File.read report
|
42
|
+
|
43
|
+
return {} if raw.empty?
|
44
|
+
|
45
|
+
json = JSON.parse raw
|
46
|
+
parser = SleepingKingStudios::Tasks::Ci::CucumberParser
|
47
|
+
|
48
|
+
parser.parse(json)
|
49
|
+
rescue
|
50
|
+
{}
|
51
|
+
end # method load_report
|
52
|
+
end # class
|
53
|
+
end # module
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/cucumber_task.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
require 'sleeping_king_studios/tasks/ci/cucumber_results'
|
5
|
+
require 'sleeping_king_studios/tasks/ci/cucumber_runner'
|
6
|
+
|
7
|
+
module SleepingKingStudios::Tasks::Ci
|
8
|
+
# Defines a Thor task for running the full RSpec test suite.
|
9
|
+
class CucumberTask < SleepingKingStudios::Tasks::Task
|
10
|
+
def self.description
|
11
|
+
'Runs the Cucumber feature suite.'
|
12
|
+
end # class method description
|
13
|
+
|
14
|
+
option :quiet,
|
15
|
+
:aliases => '-q',
|
16
|
+
:type => :boolean,
|
17
|
+
:default => false,
|
18
|
+
:desc => 'Do not write spec results to STDOUT.'
|
19
|
+
option :raw,
|
20
|
+
:aliases => '-r',
|
21
|
+
:type => :boolean,
|
22
|
+
:default => false,
|
23
|
+
:desc => 'Return a Hash instead of a results object.'
|
24
|
+
|
25
|
+
def call *files
|
26
|
+
files += default_files unless files.empty?
|
27
|
+
|
28
|
+
results = cucumber_runner.call(:files => files)
|
29
|
+
|
30
|
+
raw? ? results : CucumberResults.new(results)
|
31
|
+
end # method call
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def cucumber_runner
|
36
|
+
opts = %w(--color)
|
37
|
+
opts << '--format=pretty' unless quiet?
|
38
|
+
|
39
|
+
CucumberRunner.new(:options => opts)
|
40
|
+
end # method cucumber_runner
|
41
|
+
|
42
|
+
def default_files
|
43
|
+
SleepingKingStudios::Tasks.configuration.ci.cucumber.
|
44
|
+
fetch('default_files', [])
|
45
|
+
end # method default_files
|
46
|
+
end # class
|
47
|
+
end # module
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/results_helpers.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
|
5
|
+
module SleepingKingStudios::Tasks::Ci
|
6
|
+
# Helper methods for reporting CI results.
|
7
|
+
module ResultsHelpers
|
8
|
+
private
|
9
|
+
|
10
|
+
# Returns a terminal color corresponding to the state of the results object.
|
11
|
+
#
|
12
|
+
# @param results [Object] The results object.
|
13
|
+
#
|
14
|
+
# @return [Symbol] The terminal color.
|
15
|
+
def results_color results
|
16
|
+
if results.failing?
|
17
|
+
:red
|
18
|
+
elsif results.respond_to?(:errored?) && results.errored?
|
19
|
+
:red
|
20
|
+
elsif results.pending? || results.empty?
|
21
|
+
:yellow
|
22
|
+
else
|
23
|
+
:green
|
24
|
+
end # if-elsif-else
|
25
|
+
end # method set_results_color
|
26
|
+
|
27
|
+
# Returns a state string for the results object.
|
28
|
+
#
|
29
|
+
# @param results [Object] The results object.
|
30
|
+
#
|
31
|
+
# @return [String] The results state.
|
32
|
+
def results_state results
|
33
|
+
if results.respond_to?(:errored?) && results.errored?
|
34
|
+
'Errored'
|
35
|
+
elsif results.failing?
|
36
|
+
'Failing'
|
37
|
+
elsif results.pending? || results.empty?
|
38
|
+
'Pending'
|
39
|
+
else
|
40
|
+
'Passing'
|
41
|
+
end # if-elsif-else
|
42
|
+
end # method results_state
|
43
|
+
end # module
|
44
|
+
end # module
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/rspec_each_results.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
|
5
|
+
module SleepingKingStudios::Tasks::Ci
|
6
|
+
# Encapsulates the results of an RSpecEach call.
|
7
|
+
class RSpecEachResults
|
8
|
+
# @param results [Hash] The raw results of the RSpecEach call.
|
9
|
+
def initialize results
|
10
|
+
@results = results
|
11
|
+
end # constructor
|
12
|
+
|
13
|
+
# @param other [RSpecEachResults] The other results object to compare.
|
14
|
+
#
|
15
|
+
# @return [Boolean] True if the results are equal, otherwise false.
|
16
|
+
def == other
|
17
|
+
if other.is_a?(Hash)
|
18
|
+
empty? ? other.empty? : to_h == other
|
19
|
+
elsif other.is_a?(RSpecEachResults)
|
20
|
+
to_h == other.to_h
|
21
|
+
else
|
22
|
+
false
|
23
|
+
end # if-elsif-else
|
24
|
+
end # method ==
|
25
|
+
|
26
|
+
# @return [Float] The duration value.
|
27
|
+
def duration
|
28
|
+
@results.fetch('duration', 0.0)
|
29
|
+
end # method duration
|
30
|
+
|
31
|
+
# @return [Boolean] True if there are no files, otherwise false.
|
32
|
+
def empty?
|
33
|
+
file_count.zero?
|
34
|
+
end # method empty?
|
35
|
+
|
36
|
+
# @return [Boolean] True if there are any errored files, otherwise false.
|
37
|
+
def errored?
|
38
|
+
!errored_count.zero?
|
39
|
+
end # method errored?
|
40
|
+
|
41
|
+
# @return [Integer] The number of errored files.
|
42
|
+
def errored_count
|
43
|
+
errored_files.count
|
44
|
+
end # method errored_count
|
45
|
+
|
46
|
+
# @return [Array] The list of errored file names.
|
47
|
+
def errored_files
|
48
|
+
@results.fetch('errored_files', [])
|
49
|
+
end # method errored_files
|
50
|
+
|
51
|
+
# @return [Boolean] True if there are any failing files, otherwise false.
|
52
|
+
def failing?
|
53
|
+
!failure_count.zero?
|
54
|
+
end # method failing?
|
55
|
+
|
56
|
+
# @return [Array] The list of failing file names.
|
57
|
+
def failing_files
|
58
|
+
@results.fetch('failing_files', [])
|
59
|
+
end # method failing_files
|
60
|
+
|
61
|
+
# @return [Integer] The number of failing files.
|
62
|
+
def failure_count
|
63
|
+
failing_files.count
|
64
|
+
end # method failing_files
|
65
|
+
|
66
|
+
# @return [Integer] The total file count.
|
67
|
+
def file_count
|
68
|
+
@results.fetch('file_count', 0)
|
69
|
+
end # method file_count
|
70
|
+
|
71
|
+
# @return [Boolean] True if there are any pending files, otherwise false.
|
72
|
+
def pending?
|
73
|
+
!pending_count.zero?
|
74
|
+
end # method pending?
|
75
|
+
|
76
|
+
# @return [Integer] The number of pending files.
|
77
|
+
def pending_count
|
78
|
+
pending_files.count
|
79
|
+
end # method pending_count
|
80
|
+
|
81
|
+
# @return [Array] The list of pending file names.
|
82
|
+
def pending_files
|
83
|
+
@results.fetch('pending_files', [])
|
84
|
+
end # method pending_files
|
85
|
+
|
86
|
+
def pluralize count, singular, plural = nil
|
87
|
+
"#{count} #{tools.integer.pluralize count, singular, plural}"
|
88
|
+
end # method pluralize
|
89
|
+
|
90
|
+
# @return [Hash] The hash representation of the results.
|
91
|
+
def to_h
|
92
|
+
{
|
93
|
+
'failing_files' => failing_files,
|
94
|
+
'pending_files' => pending_files,
|
95
|
+
'errored_files' => errored_files,
|
96
|
+
'file_count' => file_count,
|
97
|
+
'duration' => duration
|
98
|
+
} # end hash
|
99
|
+
end # method to_h
|
100
|
+
|
101
|
+
# @return [String] The string representation of the results.
|
102
|
+
def to_s
|
103
|
+
str = "#{file_count} files"
|
104
|
+
|
105
|
+
str << ', ' << pluralize(failure_count, 'failure')
|
106
|
+
|
107
|
+
str << ", #{pending_count} pending" if pending?
|
108
|
+
|
109
|
+
str << ", #{errored_count} errored" if errored?
|
110
|
+
|
111
|
+
str << " in #{duration.round(2)} seconds"
|
112
|
+
end # method to_s
|
113
|
+
|
114
|
+
def tools
|
115
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
116
|
+
end # method tools
|
117
|
+
end # class
|
118
|
+
end # module
|
@@ -0,0 +1,156 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/rspec_each_task.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
require 'sleeping_king_studios/tasks/ci/results_helpers'
|
5
|
+
require 'sleeping_king_studios/tasks/ci/rspec_each_results'
|
6
|
+
require 'sleeping_king_studios/tasks/ci/rspec_results'
|
7
|
+
require 'sleeping_king_studios/tasks/ci/rspec_runner'
|
8
|
+
|
9
|
+
module SleepingKingStudios::Tasks::Ci
|
10
|
+
# rubocop:disable Metrics/ClassLength
|
11
|
+
|
12
|
+
# Defines a Thor task for running the full RSpec test suite.
|
13
|
+
class RSpecEachTask < SleepingKingStudios::Tasks::Task
|
14
|
+
include SleepingKingStudios::Tasks::Ci::ResultsHelpers
|
15
|
+
|
16
|
+
def self.description
|
17
|
+
'Runs each spec file as an individual RSpec process.'
|
18
|
+
end # class method description
|
19
|
+
|
20
|
+
def self.task_name
|
21
|
+
'rspec_each'
|
22
|
+
end # class method task_name
|
23
|
+
|
24
|
+
option :quiet,
|
25
|
+
:aliases => '-q',
|
26
|
+
:type => :boolean,
|
27
|
+
:default => false,
|
28
|
+
:desc => 'Do not write spec results to STDOUT.'
|
29
|
+
option :raw,
|
30
|
+
:aliases => '-r',
|
31
|
+
:type => :boolean,
|
32
|
+
:default => false,
|
33
|
+
:desc => 'Return a Hash instead of a results object.'
|
34
|
+
|
35
|
+
def call *groups
|
36
|
+
mute! if quiet?
|
37
|
+
|
38
|
+
files = files_list(groups)
|
39
|
+
|
40
|
+
say "Running #{files.count} spec files..."
|
41
|
+
say "\n"
|
42
|
+
|
43
|
+
results = run_files(files)
|
44
|
+
|
45
|
+
report_pending results
|
46
|
+
report_failing results
|
47
|
+
report_errored results
|
48
|
+
report_totals results
|
49
|
+
|
50
|
+
raw? ? results.to_h : results
|
51
|
+
end # method call
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def aggregate_results file, results, totals
|
56
|
+
if results.errored?
|
57
|
+
totals['errored_files'] << file
|
58
|
+
elsif results.failing?
|
59
|
+
totals['failing_files'] << file
|
60
|
+
elsif results.pending?
|
61
|
+
totals['pending_files'] << file
|
62
|
+
end # if-else
|
63
|
+
|
64
|
+
totals['file_count'] += 1
|
65
|
+
end # method aggregate_results
|
66
|
+
|
67
|
+
def build_totals
|
68
|
+
{
|
69
|
+
'pending_files' => [],
|
70
|
+
'failing_files' => [],
|
71
|
+
'errored_files' => [],
|
72
|
+
'file_count' => 0
|
73
|
+
} # end results
|
74
|
+
end # method build_totals
|
75
|
+
|
76
|
+
def files_list groups
|
77
|
+
groups = %w(spec) if groups.empty?
|
78
|
+
|
79
|
+
groups.map do |group_or_file|
|
80
|
+
if File.extname(group_or_file).empty?
|
81
|
+
Dir[File.join group_or_file, pattern]
|
82
|
+
else
|
83
|
+
[group_or_file]
|
84
|
+
end # if-else
|
85
|
+
end. # map
|
86
|
+
flatten.
|
87
|
+
uniq
|
88
|
+
end # method files_list
|
89
|
+
|
90
|
+
def pattern
|
91
|
+
'**{,/*/**}/*_spec.rb'
|
92
|
+
end # method pattern
|
93
|
+
|
94
|
+
def report_errored results
|
95
|
+
return unless results.errored?
|
96
|
+
|
97
|
+
say "\nErrored:\n\n"
|
98
|
+
|
99
|
+
results.errored_files.each { |file| say " #{file}", :red }
|
100
|
+
end # report_pending
|
101
|
+
|
102
|
+
def report_failing results
|
103
|
+
return unless results.failing?
|
104
|
+
|
105
|
+
say "\nFailures:\n\n"
|
106
|
+
|
107
|
+
results.failing_files.each { |file| say " #{file}", :red }
|
108
|
+
end # report_pending
|
109
|
+
|
110
|
+
def report_pending results
|
111
|
+
return unless results.pending?
|
112
|
+
|
113
|
+
say "\nPending:\n\n"
|
114
|
+
|
115
|
+
results.pending_files.each { |file| say " #{file}", :yellow }
|
116
|
+
end # report_pending
|
117
|
+
|
118
|
+
def report_totals results
|
119
|
+
say "\nFinished in #{results.duration.round(2)} seconds"
|
120
|
+
|
121
|
+
if results.failing? || results.errored?
|
122
|
+
say results.to_s, :red
|
123
|
+
elsif results.pending? || results.empty?
|
124
|
+
say results.to_s, :yellow
|
125
|
+
else
|
126
|
+
say results.to_s, :green
|
127
|
+
end # if-elsif-else
|
128
|
+
end # method report_totals
|
129
|
+
|
130
|
+
def rspec_runner
|
131
|
+
RSpecRunner.new(:env => { :coverage => false })
|
132
|
+
end # method rspec_runner
|
133
|
+
|
134
|
+
def run_file file
|
135
|
+
results = rspec_runner.call(:files => [file])
|
136
|
+
results = RSpecResults.new(results)
|
137
|
+
|
138
|
+
say "#{set_color results_state(results), results_color(results)} #{file}"
|
139
|
+
|
140
|
+
results
|
141
|
+
end # method run_file
|
142
|
+
|
143
|
+
def run_files files
|
144
|
+
start = Time.now
|
145
|
+
totals = build_totals
|
146
|
+
|
147
|
+
files.each { |file| aggregate_results(file, run_file(file), totals) }
|
148
|
+
|
149
|
+
totals['duration'] = Time.now - start
|
150
|
+
|
151
|
+
RSpecEachResults.new(totals)
|
152
|
+
end # method run_files
|
153
|
+
end # class
|
154
|
+
|
155
|
+
# rubocop:enable Metrics/ClassLength
|
156
|
+
end # module
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/rspec_results.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
|
5
|
+
module SleepingKingStudios::Tasks::Ci
|
6
|
+
# Encapsulates the results of an RSpec call.
|
7
|
+
class RSpecResults
|
8
|
+
# @param results [Hash] The raw results of the RSpec call.
|
9
|
+
def initialize results
|
10
|
+
@results = results
|
11
|
+
end # constructor
|
12
|
+
|
13
|
+
# @param other [RSpecResults] The other results object to compare.
|
14
|
+
#
|
15
|
+
# @return [Boolean] True if the results are equal, otherwise false.
|
16
|
+
def == other
|
17
|
+
if other.is_a?(Hash)
|
18
|
+
empty? ? other.empty? : to_h == other
|
19
|
+
elsif other.is_a?(RSpecResults)
|
20
|
+
to_h == other.to_h
|
21
|
+
else
|
22
|
+
false
|
23
|
+
end # if-elsif-else
|
24
|
+
end # method ==
|
25
|
+
|
26
|
+
# @return [Float] The duration value.
|
27
|
+
def duration
|
28
|
+
@results.fetch('duration', 0.0)
|
29
|
+
end # method duration
|
30
|
+
|
31
|
+
# @return [Boolean] True if there are no examples, otherwise false.
|
32
|
+
def empty?
|
33
|
+
example_count.zero?
|
34
|
+
end # method empty?
|
35
|
+
|
36
|
+
# @return [Boolean] True if there are no results or if errors occurred
|
37
|
+
# outside of examples, otherwise false.
|
38
|
+
def errored?
|
39
|
+
@results.empty? || !error_count.zero?
|
40
|
+
end # method errored?
|
41
|
+
|
42
|
+
# @return [Integer] The number of errors that occurred outside of examples.
|
43
|
+
def error_count
|
44
|
+
@results.fetch('error_count', 0)
|
45
|
+
end # method error_count
|
46
|
+
|
47
|
+
# @return [Integer] The total number of examples.
|
48
|
+
def example_count
|
49
|
+
@results.fetch('example_count', 0)
|
50
|
+
end # method example_count
|
51
|
+
|
52
|
+
# @return [Boolean] True if there are any failing examples, otherwise false.
|
53
|
+
def failing?
|
54
|
+
!failure_count.zero?
|
55
|
+
end # method failing?
|
56
|
+
|
57
|
+
# @return [Integer] The number of failing examples.
|
58
|
+
def failure_count
|
59
|
+
@results.fetch('failure_count', 0)
|
60
|
+
end # method failure_count
|
61
|
+
|
62
|
+
# Adds the given result values and returns a new results object with the
|
63
|
+
# sums.
|
64
|
+
#
|
65
|
+
# @param other [RSpecResults] The results to add.
|
66
|
+
#
|
67
|
+
# @return [RSpecResults] The total results.
|
68
|
+
def merge other
|
69
|
+
self.class.new(
|
70
|
+
'duration' => duration + other.duration,
|
71
|
+
'example_count' => example_count + other.example_count,
|
72
|
+
'failure_count' => failure_count + other.failure_count,
|
73
|
+
'pending_count' => pending_count + other.pending_count
|
74
|
+
) # end new
|
75
|
+
end # method merge
|
76
|
+
|
77
|
+
# @return [Boolean] True if there are any pending examples, otherwise false.
|
78
|
+
def pending?
|
79
|
+
!pending_count.zero?
|
80
|
+
end # method pending?
|
81
|
+
|
82
|
+
# @return [Intger] The number of pending examples.
|
83
|
+
def pending_count
|
84
|
+
@results.fetch('pending_count', 0)
|
85
|
+
end # method pending_count
|
86
|
+
|
87
|
+
def pluralize count, singular, plural = nil
|
88
|
+
"#{count} #{tools.integer.pluralize count, singular, plural}"
|
89
|
+
end # method pluralize
|
90
|
+
|
91
|
+
# @return [Hash] The hash representation of the results.
|
92
|
+
def to_h
|
93
|
+
{
|
94
|
+
'duration' => duration,
|
95
|
+
'example_count' => example_count,
|
96
|
+
'failure_count' => failure_count,
|
97
|
+
'pending_count' => pending_count,
|
98
|
+
'error_count' => error_count
|
99
|
+
} # end hash
|
100
|
+
end # method to_h
|
101
|
+
|
102
|
+
# rubocop:disable Metrics/AbcSize
|
103
|
+
|
104
|
+
# @return [String] The string representation of the results.
|
105
|
+
def to_s
|
106
|
+
str = pluralize(example_count, 'example')
|
107
|
+
|
108
|
+
str << ', ' << pluralize(failure_count, 'failure')
|
109
|
+
|
110
|
+
str << ', ' << pending_count.to_s << ' pending' if pending?
|
111
|
+
|
112
|
+
if error_count.zero?
|
113
|
+
str << " in #{duration.round(2)} seconds"
|
114
|
+
else
|
115
|
+
str << ', ' << pluralize(error_count, 'error') <<
|
116
|
+
' occurred outside of examples'
|
117
|
+
end # if-else
|
118
|
+
end # method to_s
|
119
|
+
|
120
|
+
# rubocop:enable Metrics/AbcSize
|
121
|
+
|
122
|
+
def tools
|
123
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
124
|
+
end # method tools
|
125
|
+
end # class
|
126
|
+
end # module
|