sleeping_king_studios-tasks 0.1.0.rc.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 +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,29 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/apps/ci/rubocop_task.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/apps/ci'
|
4
|
+
require 'sleeping_king_studios/tasks/apps/ci/steps_task'
|
5
|
+
|
6
|
+
module SleepingKingStudios::Tasks::Apps::Ci
|
7
|
+
# Defines a Thor task for running the RuboCop linter for each application.
|
8
|
+
class RuboCopTask < SleepingKingStudios::Tasks::Task
|
9
|
+
def self.description
|
10
|
+
'Runs the RuboCop linter for each application.'
|
11
|
+
end # class method description
|
12
|
+
|
13
|
+
def self.task_name
|
14
|
+
'rubocop'
|
15
|
+
end # class method task_name
|
16
|
+
|
17
|
+
option :quiet,
|
18
|
+
:aliases => '-q',
|
19
|
+
:type => :boolean,
|
20
|
+
:default => false,
|
21
|
+
:desc => 'Do not write lint results to STDOUT.'
|
22
|
+
|
23
|
+
def call *applications
|
24
|
+
SleepingKingStudios::Tasks::Apps::Ci::StepsTask.
|
25
|
+
new(options.merge('only' => %w(rubocop))).
|
26
|
+
call(*applications)
|
27
|
+
end # method call
|
28
|
+
end # class
|
29
|
+
end # module
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/apps/ci/rubocop_wrapper.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/apps/ci'
|
4
|
+
require 'sleeping_king_studios/tasks/apps/ci/step_wrapper'
|
5
|
+
require 'sleeping_king_studios/tasks/ci/rubocop_results'
|
6
|
+
|
7
|
+
module SleepingKingStudios::Tasks::Apps::Ci
|
8
|
+
# Wrapper class for calling a RuboCop Ci task for a specific application.
|
9
|
+
class RuboCopWrapper < SleepingKingStudios::Tasks::Apps::Ci::StepWrapper
|
10
|
+
def call application
|
11
|
+
super
|
12
|
+
|
13
|
+
run_step(*source_files)
|
14
|
+
end # method call
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def source_files
|
19
|
+
config =
|
20
|
+
SleepingKingStudios::Tasks::Apps.configuration[current_application]
|
21
|
+
|
22
|
+
config.source_files + config.spec_files
|
23
|
+
end # method source_files
|
24
|
+
|
25
|
+
def step_key
|
26
|
+
:rubocop
|
27
|
+
end # method step_key
|
28
|
+
end # module
|
29
|
+
end # module
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/apps/ci/simplecov_task.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/apps/ci'
|
4
|
+
require 'sleeping_king_studios/tasks/ci/simplecov_results'
|
5
|
+
require 'sleeping_king_studios/tasks/task'
|
6
|
+
|
7
|
+
module SleepingKingStudios::Tasks::Apps::Ci
|
8
|
+
# Defines a Thor task for aggregating SimpleCov coverage results across
|
9
|
+
# applications.
|
10
|
+
class SimpleCovTask < SleepingKingStudios::Tasks::Task
|
11
|
+
RESULTS_STRUCT =
|
12
|
+
Struct.new(
|
13
|
+
:covered_lines,
|
14
|
+
:covered_percent,
|
15
|
+
:missed_lines,
|
16
|
+
:total_lines
|
17
|
+
) # end struct
|
18
|
+
|
19
|
+
def self.configure_simplecov!
|
20
|
+
require 'simplecov'
|
21
|
+
require 'simplecov-json'
|
22
|
+
|
23
|
+
::SimpleCov.configure do
|
24
|
+
command_name "#{command_name}:#{ENV['APP_NAME']}" if ENV['APP_NAME']
|
25
|
+
|
26
|
+
self.formatter =
|
27
|
+
::SimpleCov::Formatter::MultiFormatter.new(
|
28
|
+
[formatter, ::SimpleCov::Formatter::JSONFormatter]
|
29
|
+
) # end formatter
|
30
|
+
end # configure
|
31
|
+
end # class method configure_simplecov!
|
32
|
+
|
33
|
+
def self.description
|
34
|
+
'Aggregates the SimpleCov results for all applications.'
|
35
|
+
end # class method description
|
36
|
+
|
37
|
+
def self.task_name
|
38
|
+
'simplecov'
|
39
|
+
end # class method task_name
|
40
|
+
|
41
|
+
def call _application = nil
|
42
|
+
results = load_report :report => File.join('coverage', 'coverage.json')
|
43
|
+
results = convert_results_to_object(results)
|
44
|
+
|
45
|
+
SleepingKingStudios::Tasks::Ci::SimpleCovResults.new(results)
|
46
|
+
end # method call
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def load_report report:
|
51
|
+
raw = File.read report
|
52
|
+
json = JSON.parse raw
|
53
|
+
|
54
|
+
json['metrics']
|
55
|
+
rescue
|
56
|
+
{}
|
57
|
+
end # method load_report
|
58
|
+
|
59
|
+
def convert_results_to_object hsh
|
60
|
+
RESULTS_STRUCT.new(
|
61
|
+
hsh.fetch('covered_lines', 0),
|
62
|
+
hsh.fetch('covered_percent', 0.0),
|
63
|
+
hsh.fetch('total_lines', 0) - hsh.fetch('covered_lines', 0),
|
64
|
+
hsh.fetch('total_lines', 0)
|
65
|
+
) # end object
|
66
|
+
end # method convert_results_to_object
|
67
|
+
end # module
|
68
|
+
end # module
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/apps/ci/step_wrapper.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/apps/applications_task'
|
4
|
+
require 'sleeping_king_studios/tasks/apps/ci'
|
5
|
+
|
6
|
+
module SleepingKingStudios::Tasks::Apps::Ci
|
7
|
+
# Wrapper class for calling a configured task for a specific application.
|
8
|
+
class StepWrapper < SleepingKingStudios::Tasks::Task
|
9
|
+
include SleepingKingStudios::Tasks::Apps::ApplicationsTask
|
10
|
+
|
11
|
+
def call application, *_rest
|
12
|
+
@current_application = application
|
13
|
+
@step_config = nil
|
14
|
+
end # method call
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :current_application
|
19
|
+
|
20
|
+
def build_step
|
21
|
+
require step_config.fetch(:require) if step_config.key?(:require)
|
22
|
+
|
23
|
+
step_class = Object.const_get(step_config.fetch :class)
|
24
|
+
|
25
|
+
step_class.new(step_options)
|
26
|
+
end # method
|
27
|
+
|
28
|
+
def run_step *args
|
29
|
+
return if skip_step?
|
30
|
+
|
31
|
+
build_step.call(*args)
|
32
|
+
end # method run_step
|
33
|
+
|
34
|
+
def skip_step?
|
35
|
+
step_config == false
|
36
|
+
end # method skip_step?
|
37
|
+
|
38
|
+
def step_config
|
39
|
+
config = SleepingKingStudios::Tasks.configuration
|
40
|
+
steps = config.ci.steps_with_options
|
41
|
+
|
42
|
+
steps.fetch(step_key, false)
|
43
|
+
end # method step_config
|
44
|
+
|
45
|
+
def step_options
|
46
|
+
options
|
47
|
+
end # method step_options
|
48
|
+
end # class
|
49
|
+
end # module
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/apps/ci/steps_runner.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/apps/applications_task'
|
4
|
+
require 'sleeping_king_studios/tasks/ci/steps_runner'
|
5
|
+
|
6
|
+
module SleepingKingStudios::Tasks::Apps::Ci
|
7
|
+
# Abstract base class for running a sequence of tasks for a specific
|
8
|
+
# application from a configured list.
|
9
|
+
class StepsRunner < SleepingKingStudios::Tasks::Ci::StepsRunner
|
10
|
+
include SleepingKingStudios::Tasks::Apps::ApplicationsTask
|
11
|
+
|
12
|
+
def call application
|
13
|
+
@current_application = application
|
14
|
+
|
15
|
+
super application
|
16
|
+
end # method call
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :current_application
|
21
|
+
|
22
|
+
def ci_steps
|
23
|
+
SleepingKingStudios::Tasks::Apps.configuration[current_application].
|
24
|
+
ci.steps_with_options
|
25
|
+
end # method ci_steps
|
26
|
+
|
27
|
+
def skip_step? _name, config
|
28
|
+
return true if config == false
|
29
|
+
|
30
|
+
if options.fetch('global', false)
|
31
|
+
!config.fetch(:global, false)
|
32
|
+
else
|
33
|
+
config.fetch(:global, false)
|
34
|
+
end # if-else
|
35
|
+
end # method skip_step?
|
36
|
+
end # class
|
37
|
+
end # module
|
@@ -0,0 +1,92 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/apps/ci/steps_task.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/apps/applications_task'
|
4
|
+
require 'sleeping_king_studios/tasks/apps/ci'
|
5
|
+
require 'sleeping_king_studios/tasks/apps/ci/results_reporter'
|
6
|
+
require 'sleeping_king_studios/tasks/apps/ci/steps_runner'
|
7
|
+
|
8
|
+
module SleepingKingStudios::Tasks::Apps::Ci
|
9
|
+
# Thor task for running each step in the CI suite for each application and
|
10
|
+
# generating a report.
|
11
|
+
class StepsTask < SleepingKingStudios::Tasks::Task
|
12
|
+
include SleepingKingStudios::Tasks::Apps::ApplicationsTask
|
13
|
+
|
14
|
+
def self.description
|
15
|
+
'Runs the configured steps for each application.'
|
16
|
+
end # class method description
|
17
|
+
|
18
|
+
option :except,
|
19
|
+
:type => :array,
|
20
|
+
:default => [],
|
21
|
+
:desc => 'Exclude steps from the CI process.'
|
22
|
+
option :only,
|
23
|
+
:type => :array,
|
24
|
+
:default => [],
|
25
|
+
:desc => 'Run only the specified steps from the CI process.'
|
26
|
+
option :quiet,
|
27
|
+
:aliases => '-q',
|
28
|
+
:type => :boolean,
|
29
|
+
:default => false,
|
30
|
+
:desc => 'Do not write intermediate results to STDOUT.'
|
31
|
+
|
32
|
+
def call *applications
|
33
|
+
filtered = filter_applications :only => applications
|
34
|
+
results = run_steps(filtered)
|
35
|
+
globals = run_global_steps
|
36
|
+
|
37
|
+
aggregate_results(results) if filtered.count > 1
|
38
|
+
|
39
|
+
(results['Totals'] ||= {}).update(globals)
|
40
|
+
|
41
|
+
say "\n" unless quiet?
|
42
|
+
|
43
|
+
reporter = ResultsReporter.new(self)
|
44
|
+
reporter.call(results)
|
45
|
+
|
46
|
+
results
|
47
|
+
end # method call
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def aggregate_results results
|
52
|
+
totals = Hash.new { |hsh, key| hsh[key] = 0 }
|
53
|
+
|
54
|
+
results.each do |_, app_results|
|
55
|
+
app_results.each do |step, step_results|
|
56
|
+
next if step_results.nil?
|
57
|
+
|
58
|
+
next totals[step] = step_results unless totals.key?(step)
|
59
|
+
|
60
|
+
totals[step] = totals[step].merge(step_results)
|
61
|
+
end # each
|
62
|
+
end # each
|
63
|
+
|
64
|
+
results['Totals'] = totals
|
65
|
+
end # method aggregate_results
|
66
|
+
|
67
|
+
def run_global_steps
|
68
|
+
opts = options.merge 'global' => true
|
69
|
+
runner = SleepingKingStudios::Tasks::Apps::Ci::StepsRunner.new(opts)
|
70
|
+
|
71
|
+
runner.call(nil)
|
72
|
+
end # method run_global_steps
|
73
|
+
|
74
|
+
def run_steps applications
|
75
|
+
results = Hash.new { |hsh, key| hsh[key] = {} }
|
76
|
+
|
77
|
+
applications.each do |name, _|
|
78
|
+
results[name] = run_steps_for_application(name)
|
79
|
+
end # each
|
80
|
+
|
81
|
+
results
|
82
|
+
end # method run_steps
|
83
|
+
|
84
|
+
def run_steps_for_application name
|
85
|
+
steps_runner.call(name)
|
86
|
+
end # method run_steps_for_application
|
87
|
+
|
88
|
+
def steps_runner
|
89
|
+
SleepingKingStudios::Tasks::Apps::Ci::StepsRunner.new(options)
|
90
|
+
end # method steps_runner
|
91
|
+
end # class
|
92
|
+
end # module
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/cucumber_parser.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
|
5
|
+
module SleepingKingStudios::Tasks::Ci
|
6
|
+
# Parses the output from cucumber --format=json into a summary report.
|
7
|
+
module CucumberParser
|
8
|
+
class << self
|
9
|
+
def parse results
|
10
|
+
@report = build_report
|
11
|
+
|
12
|
+
results.each { |feature| parse_feature(feature) }
|
13
|
+
|
14
|
+
report['duration'] = report['duration'] / (1.0 * 10**9)
|
15
|
+
|
16
|
+
report
|
17
|
+
end # class method parse
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
attr_reader :report
|
22
|
+
|
23
|
+
def build_report
|
24
|
+
{
|
25
|
+
'scenario_count' => 0,
|
26
|
+
'failing_scenarios' => [],
|
27
|
+
'pending_scenarios' => [],
|
28
|
+
'step_count' => 0,
|
29
|
+
'failing_step_count' => 0,
|
30
|
+
'pending_step_count' => 0,
|
31
|
+
'duration' => 0
|
32
|
+
} # end report
|
33
|
+
end # method build report
|
34
|
+
|
35
|
+
def parse_feature feature
|
36
|
+
feature['elements'].each do |scenario|
|
37
|
+
parse_scenario(scenario, feature)
|
38
|
+
end # each
|
39
|
+
end # method parse_feature
|
40
|
+
|
41
|
+
# rubocop:disable Metrics/MethodLength
|
42
|
+
def parse_scenario scenario, feature
|
43
|
+
failing = false
|
44
|
+
pending = false
|
45
|
+
|
46
|
+
scenario['steps'].each do |step|
|
47
|
+
status = parse_step(step)
|
48
|
+
|
49
|
+
failing ||= status == 'failed'
|
50
|
+
pending ||= status == 'pending' || status == 'skipped'
|
51
|
+
end # each
|
52
|
+
|
53
|
+
report_scenario(
|
54
|
+
scenario,
|
55
|
+
feature,
|
56
|
+
:failing => failing,
|
57
|
+
:pending => pending
|
58
|
+
) # end report scenario
|
59
|
+
end # method parse_scenario
|
60
|
+
# rubocop:enable Metrics/MethodLength
|
61
|
+
|
62
|
+
def parse_step step
|
63
|
+
report['step_count'] += 1
|
64
|
+
report['duration'] += step_duration(step)
|
65
|
+
|
66
|
+
status = step_status(step) || 'failed'
|
67
|
+
|
68
|
+
if status == 'failed'
|
69
|
+
report['failing_step_count'] += 1
|
70
|
+
elsif status == 'pending' || status == 'skipped'
|
71
|
+
report['pending_step_count'] += 1
|
72
|
+
end # if
|
73
|
+
|
74
|
+
status
|
75
|
+
end # method parse_step
|
76
|
+
|
77
|
+
# rubocop:disable Metrics/MethodLength
|
78
|
+
def report_scenario scenario, feature, failing:, pending:
|
79
|
+
report['scenario_count'] += 1
|
80
|
+
|
81
|
+
return unless failing || pending
|
82
|
+
|
83
|
+
hsh =
|
84
|
+
{
|
85
|
+
'location' => "#{feature['uri']}:#{scenario['line']}",
|
86
|
+
'description' => "#{scenario['keyword']}: #{scenario['name']}"
|
87
|
+
}
|
88
|
+
|
89
|
+
if failing
|
90
|
+
report['failing_scenarios'] << hsh
|
91
|
+
else
|
92
|
+
report['pending_scenarios'] << hsh
|
93
|
+
end # if-else
|
94
|
+
end # method report_scenario
|
95
|
+
# rubocop:enable Metrics/MethodLength
|
96
|
+
|
97
|
+
def step_duration hsh
|
98
|
+
return 0 if hsh.nil? || hsh.empty?
|
99
|
+
|
100
|
+
result = hsh['result']
|
101
|
+
|
102
|
+
return 0 if result.nil? || result.empty?
|
103
|
+
|
104
|
+
result['duration'] || 0
|
105
|
+
end # method step_duration
|
106
|
+
|
107
|
+
def step_status hsh
|
108
|
+
return nil if hsh.nil? || hsh.empty?
|
109
|
+
|
110
|
+
result = hsh['result']
|
111
|
+
|
112
|
+
return nil if result.nil? || result.empty?
|
113
|
+
|
114
|
+
result['status']
|
115
|
+
end # method step_status
|
116
|
+
end # class
|
117
|
+
end # module
|
118
|
+
end # module
|
@@ -0,0 +1,191 @@
|
|
1
|
+
# lib/sleeping_king_studios/tasks/ci/cucumber_results.rb
|
2
|
+
|
3
|
+
require 'sleeping_king_studios/tasks/ci'
|
4
|
+
|
5
|
+
module SleepingKingStudios::Tasks::Ci
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
7
|
+
|
8
|
+
# Encapsulates the results of a Cucumber call.
|
9
|
+
class CucumberResults
|
10
|
+
# @param results [Hash] The raw results of the RSpec call.
|
11
|
+
def initialize results
|
12
|
+
@results = results
|
13
|
+
end # constructor
|
14
|
+
|
15
|
+
# @param other [RSpecResults] The other results object to compare.
|
16
|
+
#
|
17
|
+
# @return [Boolean] True if the results are equal, otherwise false.
|
18
|
+
def == other
|
19
|
+
if other.is_a?(Hash)
|
20
|
+
empty? ? other.empty? : to_h == other
|
21
|
+
elsif other.is_a?(CucumberResults)
|
22
|
+
to_h == other.to_h
|
23
|
+
else
|
24
|
+
false
|
25
|
+
end # if-elsif-else
|
26
|
+
end # method ==
|
27
|
+
|
28
|
+
# @return [Float] The duration value.
|
29
|
+
def duration
|
30
|
+
@results.fetch('duration', 0.0)
|
31
|
+
end # method duration
|
32
|
+
|
33
|
+
# @return [Boolean] True if there are no scenarios, otherwise false.
|
34
|
+
def empty?
|
35
|
+
scenario_count.zero?
|
36
|
+
end # method empty?
|
37
|
+
|
38
|
+
# @return [Boolean] True if there are any failing scenarios, otherwise
|
39
|
+
# false.
|
40
|
+
def failing?
|
41
|
+
!failing_scenario_count.zero?
|
42
|
+
end # method failing?
|
43
|
+
|
44
|
+
# @return [Integer] The list of failing scenarios.
|
45
|
+
def failing_scenarios
|
46
|
+
@results.fetch('failing_scenarios', [])
|
47
|
+
end # method failing_scenarios
|
48
|
+
|
49
|
+
# @return [Integer] The number of failing scenarios.
|
50
|
+
def failing_scenario_count
|
51
|
+
failing_scenarios.count
|
52
|
+
end # method failing_scenario_count
|
53
|
+
|
54
|
+
# @return [Integer] The number of failing steps.
|
55
|
+
def failing_step_count
|
56
|
+
@results.fetch('failing_step_count', 0)
|
57
|
+
end # method failing_step_count
|
58
|
+
|
59
|
+
# Adds the given result values and returns a new results object with the
|
60
|
+
# sums.
|
61
|
+
#
|
62
|
+
# @param other [RSpecResults] The results to add.
|
63
|
+
#
|
64
|
+
# @return [RSpecResults] The total results.
|
65
|
+
def merge other
|
66
|
+
merged = {}
|
67
|
+
|
68
|
+
keys.each do |key|
|
69
|
+
merged[key] = public_send(key) + other.public_send(key)
|
70
|
+
end # each
|
71
|
+
|
72
|
+
self.class.new(merged)
|
73
|
+
end # method merge
|
74
|
+
|
75
|
+
# @return [Boolean] True if there are any pending scenarios, otherwise
|
76
|
+
# false.
|
77
|
+
def pending?
|
78
|
+
!pending_scenario_count.zero?
|
79
|
+
end # method pending?
|
80
|
+
|
81
|
+
# @return [Integer] The number of pending scenarios.
|
82
|
+
def pending_scenario_count
|
83
|
+
pending_scenarios.count
|
84
|
+
end # method pending_scenario_count
|
85
|
+
|
86
|
+
# @return [Integer] The list of pending scenarios.
|
87
|
+
def pending_scenarios
|
88
|
+
@results.fetch('pending_scenarios', [])
|
89
|
+
end # method pending_scenarios
|
90
|
+
|
91
|
+
# @return [Integer] The number of pending steps.
|
92
|
+
def pending_step_count
|
93
|
+
@results.fetch('pending_step_count', 0)
|
94
|
+
end # method pending_step_count
|
95
|
+
|
96
|
+
# @return [Integer] The total number of scenarios.
|
97
|
+
def scenario_count
|
98
|
+
@results.fetch('scenario_count', 0)
|
99
|
+
end # method scenario_count
|
100
|
+
|
101
|
+
# @return [String] A brief summary of the scenario results.
|
102
|
+
def scenarios_summary
|
103
|
+
build_summary(
|
104
|
+
'scenario',
|
105
|
+
scenario_count,
|
106
|
+
failing_scenario_count,
|
107
|
+
pending_scenario_count
|
108
|
+
) # end build_summary
|
109
|
+
end # method scenarios_summary
|
110
|
+
|
111
|
+
# @return [Integer] The total number of steps.
|
112
|
+
def step_count
|
113
|
+
@results.fetch('step_count', 0)
|
114
|
+
end # method step_count
|
115
|
+
|
116
|
+
# @return [String] A brief summary of the scenario results.
|
117
|
+
def steps_summary
|
118
|
+
build_summary(
|
119
|
+
'step',
|
120
|
+
step_count,
|
121
|
+
failing_step_count,
|
122
|
+
pending_step_count
|
123
|
+
) # end build_summary
|
124
|
+
end # method steps_summary
|
125
|
+
|
126
|
+
# @return [String] A brief summary of the results.
|
127
|
+
def summary
|
128
|
+
str = scenarios_summary
|
129
|
+
|
130
|
+
str << ', '
|
131
|
+
|
132
|
+
str << steps_summary
|
133
|
+
|
134
|
+
str << " in #{duration.round(2)} seconds"
|
135
|
+
end # method summary
|
136
|
+
alias_method :to_s, :summary
|
137
|
+
|
138
|
+
# @return [Hash] The hash representation of the results.
|
139
|
+
def to_h
|
140
|
+
hsh = {}
|
141
|
+
|
142
|
+
keys.each { |key| hsh[key] = public_send(key) }
|
143
|
+
|
144
|
+
hsh
|
145
|
+
end # method to_h
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
def build_summary name, count, failing_count, pending_count
|
150
|
+
str = pluralize(count, name)
|
151
|
+
|
152
|
+
return str if failing_count.zero? && pending_count.zero?
|
153
|
+
|
154
|
+
str << build_summary_details(failing_count, pending_count)
|
155
|
+
end # method build_summary
|
156
|
+
|
157
|
+
def build_summary_details failing_count, pending_count
|
158
|
+
str = ' ('
|
159
|
+
|
160
|
+
str << pluralize(failing_count, 'failure') unless failing_count.zero?
|
161
|
+
|
162
|
+
str << ', ' if !failing_count.zero? && !pending_count.zero?
|
163
|
+
|
164
|
+
str << "#{pending_count} pending" unless pending_count.zero?
|
165
|
+
|
166
|
+
str << ')'
|
167
|
+
end # method build_summary_details
|
168
|
+
|
169
|
+
def keys
|
170
|
+
%w(
|
171
|
+
duration
|
172
|
+
step_count
|
173
|
+
pending_step_count
|
174
|
+
failing_step_count
|
175
|
+
scenario_count
|
176
|
+
pending_scenarios
|
177
|
+
failing_scenarios
|
178
|
+
) # end keys
|
179
|
+
end # method keys
|
180
|
+
|
181
|
+
def pluralize count, singular, plural = nil
|
182
|
+
"#{count} #{tools.integer.pluralize count, singular, plural}"
|
183
|
+
end # method pluralize
|
184
|
+
|
185
|
+
def tools
|
186
|
+
SleepingKingStudios::Tools::Toolbelt.instance
|
187
|
+
end # method tools
|
188
|
+
end # class
|
189
|
+
|
190
|
+
# rubocop:enable Metrics/ClassLength
|
191
|
+
end # module
|