polytrix 0.1.2 → 0.1.3

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.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop-todo.yml +14 -5
  3. data/Gemfile +2 -1
  4. data/README.md +139 -177
  5. data/Rakefile +5 -12
  6. data/bin/polytrix +0 -1
  7. data/features/bootstrapping.feature +0 -3
  8. data/features/cloning.feature +0 -3
  9. data/features/show.feature +38 -0
  10. data/features/states.feature +12 -13
  11. data/features/step_definitions/sdk_steps.rb +0 -4
  12. data/lib/polytrix/challenge.rb +135 -53
  13. data/lib/polytrix/challenge_result.rb +0 -2
  14. data/lib/polytrix/challenge_runner.rb +28 -18
  15. data/lib/polytrix/cli.rb +53 -69
  16. data/lib/polytrix/color.rb +2 -2
  17. data/lib/polytrix/command/action.rb +4 -3
  18. data/lib/polytrix/command/list.rb +39 -28
  19. data/lib/polytrix/command/report.rb +9 -86
  20. data/lib/polytrix/command/reports/code2doc.rb +72 -0
  21. data/lib/polytrix/command/reports/dashboard.rb +125 -0
  22. data/lib/polytrix/command/show.rb +148 -0
  23. data/lib/polytrix/command.rb +37 -104
  24. data/lib/polytrix/configuration.rb +14 -18
  25. data/lib/polytrix/{core/hashie.rb → dash.rb} +4 -3
  26. data/lib/polytrix/documentation/code_segmenter.rb +8 -8
  27. data/lib/polytrix/documentation/comment_styles.rb +1 -1
  28. data/lib/polytrix/documentation/helpers/code_helper.rb +9 -0
  29. data/lib/polytrix/documentation_generator.rb +11 -14
  30. data/lib/polytrix/error.rb +104 -97
  31. data/lib/polytrix/executor.rb +33 -0
  32. data/lib/polytrix/{runners → executors}/buff_shellout_executor.rb +1 -1
  33. data/lib/polytrix/executors/linux_challenge_executor.rb +29 -0
  34. data/lib/polytrix/executors/mixlib_shellout_executor.rb +55 -0
  35. data/lib/polytrix/{runners/windows_challenge_runner.rb → executors/windows_challenge_executor.rb} +4 -11
  36. data/lib/polytrix/{core/implementor.rb → implementor.rb} +10 -6
  37. data/lib/polytrix/manifest.rb +2 -31
  38. data/lib/polytrix/{reports → reporters}/hash_reporter.rb +6 -2
  39. data/lib/polytrix/{reports → reporters}/json_reporter.rb +2 -2
  40. data/lib/polytrix/{reports → reporters}/markdown_reporter.rb +7 -2
  41. data/lib/polytrix/{reports → reporters}/yaml_reporter.rb +2 -2
  42. data/lib/polytrix/reporters.rb +27 -0
  43. data/lib/polytrix/result.rb +6 -5
  44. data/lib/polytrix/spies/file_system_spy.rb +15 -0
  45. data/lib/polytrix/spies.rb +61 -0
  46. data/lib/polytrix/state_file.rb +1 -20
  47. data/lib/polytrix/util.rb +157 -62
  48. data/lib/polytrix/validation.rb +41 -2
  49. data/lib/polytrix/validator.rb +9 -4
  50. data/lib/polytrix/version.rb +1 -1
  51. data/lib/polytrix.rb +110 -105
  52. data/polytrix.gemspec +7 -2
  53. data/polytrix.yml +16 -13
  54. data/resources/assets/pygments/autumn.css +58 -0
  55. data/resources/assets/pygments/borland.css +46 -0
  56. data/resources/assets/pygments/bw.css +34 -0
  57. data/resources/assets/pygments/colorful.css +61 -0
  58. data/resources/assets/pygments/default.css +62 -0
  59. data/resources/assets/pygments/emacs.css +61 -0
  60. data/resources/assets/pygments/friendly.css +61 -0
  61. data/resources/assets/pygments/fruity.css +69 -0
  62. data/resources/assets/pygments/github.css +61 -0
  63. data/resources/assets/pygments/manni.css +61 -0
  64. data/resources/assets/pygments/monokai.css +64 -0
  65. data/resources/assets/pygments/murphy.css +61 -0
  66. data/resources/assets/pygments/native.css +69 -0
  67. data/resources/assets/pygments/pastie.css +60 -0
  68. data/resources/assets/pygments/perldoc.css +58 -0
  69. data/resources/assets/pygments/tango.css +69 -0
  70. data/resources/assets/pygments/trac.css +59 -0
  71. data/resources/assets/pygments/vim.css +69 -0
  72. data/resources/assets/pygments/vs.css +33 -0
  73. data/resources/assets/pygments/zenburn.css +1 -0
  74. data/resources/assets/style.css +41 -0
  75. data/resources/templates/dashboard/files/dashboard.html.tt +82 -0
  76. data/resources/templates/dashboard/templates/_test_report.html.tt +87 -0
  77. data/samples/bootstrap.sh +2 -0
  78. data/samples/clone.sh +2 -0
  79. data/samples/code2doc.sh +4 -0
  80. data/samples/docs/samples/code2doc/java/katas-hello_world-java.md +17 -0
  81. data/samples/docs/samples/code2doc/java/katas-quine-java.md +35 -0
  82. data/samples/docs/samples/code2doc/python/katas-hello_world-python.md +5 -0
  83. data/samples/docs/samples/code2doc/python/katas-quine-python.md +6 -0
  84. data/samples/docs/samples/code2doc/ruby/katas-hello_world-ruby.md +11 -0
  85. data/samples/exec.sh +2 -0
  86. data/samples/polytrix.rb +2 -2
  87. data/samples/polytrix.yml +5 -2
  88. data/samples/show.sh +4 -0
  89. data/samples/test.sh +2 -0
  90. data/samples/tests/polytrix/validators.rb +2 -2
  91. data/samples/verify.sh +3 -0
  92. data/scripts/wrapper +4 -7
  93. data/spec/fabricators/challenge_fabricator.rb +2 -9
  94. data/spec/fabricators/implementor_fabricator.rb +0 -8
  95. data/spec/fabricators/manifest_fabricator.rb +2 -9
  96. data/spec/fabricators/validator_fabricator.rb +2 -4
  97. data/spec/polytrix/challenge_runner_spec.rb +20 -0
  98. data/spec/polytrix/documentation/helpers/code_helper_spec.rb +7 -7
  99. data/spec/polytrix/file_finder_spec.rb +5 -5
  100. data/spec/polytrix/manifest_spec.rb +0 -21
  101. data/spec/polytrix/result_spec.rb +14 -14
  102. data/spec/polytrix/validator_registry_spec.rb +4 -4
  103. data/spec/polytrix/validator_spec.rb +9 -9
  104. data/spec/polytrix_spec.rb +1 -25
  105. data/spec/spec_helper.rb +8 -1
  106. metadata +130 -38
  107. data/features/execution.feature +0 -53
  108. data/features/fixtures/spec/polytrix_spec.rb +0 -7
  109. data/lib/polytrix/cli/report.rb +0 -84
  110. data/lib/polytrix/command/rundoc.rb +0 -27
  111. data/lib/polytrix/core/file_system_helper.rb +0 -75
  112. data/lib/polytrix/core/manifest_section.rb +0 -4
  113. data/lib/polytrix/core/string_helpers.rb +0 -15
  114. data/lib/polytrix/documentation/view_helper.rb +0 -21
  115. data/lib/polytrix/rspec/documentation_formatter.rb +0 -66
  116. data/lib/polytrix/rspec/yaml_report.rb +0 -51
  117. data/lib/polytrix/rspec.rb +0 -56
  118. data/lib/polytrix/runners/executor.rb +0 -34
  119. data/lib/polytrix/runners/linux_challenge_runner.rb +0 -23
  120. data/lib/polytrix/runners/middleware/change_directory.rb +0 -20
  121. data/lib/polytrix/runners/middleware/feature_executor.rb +0 -24
  122. data/lib/polytrix/runners/middleware/setup_env_vars.rb +0 -42
  123. data/lib/polytrix/runners/mixlib_shellout_executor.rb +0 -83
  124. data/lib/polytrix/validations.rb +0 -23
  125. data/samples/scripts/wrapper +0 -7
  126. data/spec/polytrix/middleware/feature_executor_spec.rb +0 -48
  127. data/spec/polytrix/validations_spec.rb +0 -16
@@ -1,14 +1,11 @@
1
1
  require 'benchmark'
2
- require 'hashie/dash'
3
- require 'hashie/extensions/coercion'
4
- require 'hashie/extensions/indifferent_access'
5
2
  require 'polytrix/documentation/helpers/code_helper'
6
3
 
7
4
  module Polytrix
8
5
  class Challenge < Polytrix::Dash # rubocop:disable ClassLength
9
- include Polytrix::Core::FileSystemHelper
6
+ include Polytrix::Util::FileSystem
10
7
  include Polytrix::Logging
11
- include Polytrix::StringHelpers
8
+ include Polytrix::Util::String
12
9
  # View helpers
13
10
  include Polytrix::Documentation::Helpers::CodeHelper
14
11
 
@@ -17,28 +14,45 @@ module Polytrix
17
14
  coerce_key :implementor, Polytrix::Implementor
18
15
  property :suite, required: true
19
16
  property :vars, default: {}
17
+ # coerce_key :vars, Polytrix::Manifest::Environment
20
18
  property :source_file
21
19
  coerce_key :source_file, Pathname
22
20
  property :basedir
23
21
  coerce_key :basedir, Pathname
24
22
  property :challenge_runner, default: ChallengeRunner.create_runner
25
23
  property :result
26
- # coerce_key :results, Array[ChallengeResult]
27
- property :env_file
28
- # coerce_key :vars, Polytrix::Manifest::Environment
29
- property :plugin_data, default: {}
24
+ coerce_key :results, ChallengeResult
25
+ property :spy_data, default: {}
30
26
  property :verification_level, default: 0
31
27
 
28
+ KEYS_TO_PERSIST = [:result, :spy_data]
29
+
30
+ def initialize(hash)
31
+ super
32
+ refresh
33
+ end
34
+
32
35
  def state_file
33
36
  @state_file ||= StateFile.new(Dir.pwd, slug)
34
37
  end
35
38
 
39
+ def refresh
40
+ @state = state_file.read
41
+ KEYS_TO_PERSIST.each do |key|
42
+ public_send("#{key}=".to_sym, @state[key]) if @state[key]
43
+ end
44
+ end
45
+
46
+ def validators
47
+ Polytrix::ValidatorRegistry.validators_for self
48
+ end
49
+
36
50
  def logger
37
51
  implementor.logger
38
52
  end
39
53
 
40
54
  def slug
41
- slugify("#{suite}-#{name}-#{implementor.name}")
55
+ slugify(suite, name, implementor.name)
42
56
  end
43
57
 
44
58
  def absolute_source_file
@@ -47,6 +61,18 @@ module Polytrix
47
61
  File.expand_path source_file, basedir
48
62
  end
49
63
 
64
+ def detect
65
+ transition_to :detect
66
+ end
67
+
68
+ def detect_action
69
+ perform_action(:detect, 'Detecting code sample') do
70
+ fail FeatureNotImplementedError, "Implementor #{name} has not been cloned" unless implementor.cloned?
71
+ fail FeatureNotImplementedError, name if source_file.nil?
72
+ fail FeatureNotImplementedError, name unless File.exist?(absolute_source_file)
73
+ end
74
+ end
75
+
50
76
  def exec
51
77
  transition_to :exec
52
78
  end
@@ -55,7 +81,7 @@ module Polytrix
55
81
  perform_action(:exec, 'Executing') do
56
82
  fail FeatureNotImplementedError, "Implementor #{name} has not been cloned" unless implementor.cloned?
57
83
  fail FeatureNotImplementedError, name if source_file.nil?
58
- fail FeatureNotImplementedError, name unless File.exists?(absolute_source_file)
84
+ fail FeatureNotImplementedError, name unless File.exist?(absolute_source_file)
59
85
  self.result = challenge_runner.run_challenge self
60
86
  end
61
87
  end
@@ -68,7 +94,7 @@ module Polytrix
68
94
  transition_to :destroy
69
95
  end
70
96
 
71
- def test(destroy_mode = :passing)
97
+ def test(_destroy_mode = :passing)
72
98
  elapsed = Benchmark.measure do
73
99
  banner "Cleaning up any prior instances of #{slug}"
74
100
  destroy
@@ -78,47 +104,34 @@ module Polytrix
78
104
  end
79
105
  info "Finished testing #{slug} #{Util.duration(elapsed.real)}."
80
106
  self
81
- # ensure
107
+ # ensure
82
108
  # destroy if destroy_mode == :always
83
109
  end
84
110
 
85
- def code2doc
86
- if source_file.nil?
87
- warn "No code sample available for #{slug}, no documentation will be generated."
88
- return
89
- end
90
-
91
- display_file = relativize(absolute_source_file, Dir.pwd)
92
- banner "Generating documentation for #{slug} from #{display_file}"
93
- target_dir = Polytrix.configuration.documentation_dir
94
- format = Polytrix.configuration.documentation_format
95
- target_file_name = File.basename(source_file, File.extname(source_file)) + ".#{format}"
96
- target_file = File.join(target_dir, target_file_name)
97
- doc = Polytrix::DocumentationGenerator.new.code2doc(absolute_source_file)
98
- FileUtils.mkdir_p File.dirname(target_file)
99
- File.write(target_file, doc)
100
- info "Documentated saved to #{target_file}"
101
- rescue Polytrix::Documentation::CommentStyles::UnknownStyleError => e
102
- abort "Unknown file extension: #{e.extension}, please use --lang to set the language manually"
103
- end
104
-
105
111
  def destroy_action
106
112
  perform_action(:destroy, 'Destroying') do
107
113
  @state_file.destroy
108
114
  @state_file = nil
109
- @validations = nil
110
115
  @state = {}
116
+ refresh
111
117
  end
112
118
  end
113
119
 
114
120
  def verify_action
115
121
  perform_action(:verify, 'Verifying') do
116
- validators = Polytrix::ValidatorRegistry.validators_for self
117
122
  validators.each do |validator|
118
- validator.validate(self)
119
- validations << validator.description
123
+ validation = validator.validate(self)
124
+ status = case validation.result
125
+ when :passed
126
+ Polytrix::Color.colorize('✓ Passed', :green)
127
+ when :failed
128
+ Polytrix::Color.colorize('x Failed', :red)
129
+ Polytrix.handle_validation_failure(validation.error)
130
+ else
131
+ Polytrix::Color.colorize(validation.result, :yellow)
132
+ end
133
+ info format('%-50s %s', validator.description, status)
120
134
  end
121
- @state['validations'] = validations
122
135
  end
123
136
  end
124
137
 
@@ -133,55 +146,124 @@ module Polytrix
133
146
  end
134
147
 
135
148
  def action(what, &block)
136
- @state = state_file.read
149
+ @state ||= state_file.read
150
+ @state['last_attempted_action'] = what.to_s
137
151
  elapsed = Benchmark.measure do
138
152
  # synchronize_or_call(what, @state, &block)
139
153
  block.call(@state)
140
154
  end
141
- @state['last_action'] = what.to_s
155
+ @state['last_completed_action'] = what.to_s
142
156
  elapsed
143
157
  rescue Polytrix::FeatureNotImplementedError => e
144
158
  raise e
145
159
  rescue ActionFailed => e
146
160
  log_failure(what, e)
147
- fail(ChallengeFailure, failure_message(what) +
161
+ raise(ChallengeFailure, failure_message(what) +
148
162
  " Please see .polytrix/logs/#{name}.log for more details",
149
- e.backtrace)
163
+ e.backtrace)
150
164
  rescue Exception => e # rubocop:disable RescueException
151
165
  log_failure(what, e)
152
- fail ActionFailed,
153
- "Failed to complete ##{what} action: [#{e.message}]", e.backtrace
166
+ raise ActionFailed,
167
+ "Failed to complete ##{what} action: [#{e.message}]", e.backtrace
154
168
  ensure
169
+ KEYS_TO_PERSIST.each do |key|
170
+ @state[key] = public_send(key)
171
+ end
155
172
  state_file.write(@state) unless what == :destroy
156
173
  end
157
174
 
175
+ def failed?
176
+ last_attempted_action != last_completed_action
177
+ end
178
+
179
+ def skipped?
180
+ result.nil?
181
+ end
182
+
183
+ def sample?
184
+ !source_file.nil?
185
+ end
186
+
187
+ def status
188
+ status = last_attempted_action
189
+ failed? ? "#{status}_failed" : status
190
+ end
191
+
192
+ def status_description
193
+ case status
194
+ when 'clone' then 'Cloned'
195
+ when 'clone_failed' then 'Clone Failed'
196
+ when 'detect' then 'Sample Found'
197
+ when 'detect_failed', nil then '<Not Found>'
198
+ when 'bootstrap' then 'Bootstrapped'
199
+ when 'bootstrap_failed' then 'Bootstrap Failed'
200
+ when 'detect' then 'Detected'
201
+ when 'exec' then 'Executed'
202
+ when 'exec_failed' then 'Execution Failed'
203
+ when 'verify', 'verify_failed'
204
+ validator_count = validators.count
205
+ validation_count = validations.values.select { |v| v['result'] == :passed }.count
206
+ if validator_count == validation_count
207
+ "Fully Verified (#{validation_count} of #{validator_count})"
208
+ else
209
+ "Partially Verified (#{validation_count} of #{validator_count})"
210
+ end
211
+ # when 'verify_failed' then 'Verification Failed'
212
+ else "<Unknown (#{status})>"
213
+ end
214
+ end
215
+
216
+ def status_color
217
+ case status_description
218
+ when '<Not Found>' then :white
219
+ when 'Cloned' then :magenta
220
+ when 'Bootstrapped' then :magenta
221
+ when 'Sample Found' then :cyan
222
+ when 'Executed' then :blue
223
+ when /Verified/
224
+ if status_description =~ /Fully/
225
+ :green
226
+ else
227
+ :yellow
228
+ end
229
+ else :red
230
+ end
231
+ end
232
+
158
233
  # Returns the last successfully completed action state of the instance.
159
234
  #
160
235
  # @return [String] a named action which was last successfully completed
161
- def last_action
162
- state_file.read['last_action']
236
+ def last_attempted_action
237
+ state_file.read['last_attempted_action']
238
+ end
239
+
240
+ def last_completed_action
241
+ state_file.read['last_completed_action']
163
242
  end
164
243
 
165
244
  def validations
166
- @validations ||= (state_file.read['validations'] || [])
245
+ return nil if result.nil?
246
+ result.validations
167
247
  end
168
248
 
169
249
  def transition_to(desired)
170
250
  transition_result = nil
171
251
  begin
172
- FSM.actions(last_action, desired).each do |transition|
252
+ FSM.actions(last_completed_action, desired).each do |transition|
173
253
  transition_result = send("#{transition}_action")
174
254
  end
175
255
  rescue Polytrix::FeatureNotImplementedError
176
256
  warn("#{slug} is not implemented")
177
257
  rescue ActionFailed => e
178
- error("#{slug} failed: #{e}")
179
- fail(ChallengeFailure, e.message, e.backtrace)
258
+ # Need to use with_friendly_errors again somewhere, since errors don't bubble up
259
+ # without fast-fail?
260
+ Polytrix.handle_error(e)
261
+ raise(ChallengeFailure, e.message, e.backtrace)
180
262
  end
181
263
  transition_result
182
264
  end
183
265
 
184
- def log_failure(what, e)
266
+ def log_failure(what, _e)
185
267
  return if logger.logdev.nil?
186
268
 
187
269
  logger.logdev.error(failure_message(what))
@@ -195,7 +277,7 @@ module Polytrix
195
277
  # @return [String] a failure message
196
278
  # @api private
197
279
  def failure_message(what)
198
- "#{what.capitalize} failed on instance #{slug}."
280
+ "#{what.capitalize} failed for test #{slug}."
199
281
  end
200
282
 
201
283
  # The simplest finite state machine pseudo-implementation needed to manage
@@ -223,7 +305,7 @@ module Polytrix
223
305
  end
224
306
  end
225
307
 
226
- TRANSITIONS = [:destroy, :exec, :verify]
308
+ TRANSITIONS = [:destroy, :detect, :exec, :verify]
227
309
 
228
310
  # Determines the index of a state in the state lifecycle vector. Woah.
229
311
  #
@@ -1,6 +1,4 @@
1
1
  require 'hashie/dash'
2
- require 'hashie/extensions/coercion'
3
- require 'hashie/extensions/indifferent_access'
4
2
  require 'polytrix/documentation/helpers/code_helper'
5
3
 
6
4
  module Polytrix
@@ -2,44 +2,54 @@ require 'polytrix'
2
2
  require 'rbconfig'
3
3
 
4
4
  module Polytrix
5
- module Runners
6
- autoload :LinuxChallengeRunner, 'polytrix/runners/linux_challenge_runner'
7
- autoload :WindowsChallengeRunner, 'polytrix/runners/windows_challenge_runner'
5
+ module Executors
6
+ autoload :LinuxChallengeRunner, 'polytrix/executors/linux_challenge_executor'
7
+ autoload :WindowsChallengeRunner, 'polytrix/executors/windows_challenge_executor'
8
8
  end
9
9
 
10
10
  class ChallengeRunner < Thor::Shell::Color
11
- include Polytrix::Core::FileSystemHelper
12
- include Polytrix::Runners::Executor
13
-
14
- attr_accessor :env
11
+ include Polytrix::Util::FileSystem
12
+ include Executor
15
13
 
16
14
  def self.create_runner
17
15
  case RbConfig::CONFIG['host_os']
18
16
  when /mswin(\d+)|mingw/i
19
- Runners::WindowsChallengeRunner.new
17
+ # TODO: Display warning that Windows support is experimental
18
+ Executors::WindowsChallengeRunner.new
20
19
  else
21
- Runners::LinuxChallengeRunner.new
20
+ Executors::LinuxChallengeRunner.new
22
21
  end
23
22
  end
24
23
 
25
- def run_command(command)
24
+ def run_command(command, opts = { cwd: Dir.pwd })
26
25
  if Polytrix.configuration.dry_run
27
- puts "Would have run #{command}"
26
+ puts "Would have run #{command} with #{opts.inspect}"
28
27
  else
29
28
  say_status 'polytrix:execute', command
30
- execute command
29
+ execute(command, opts)
31
30
  end
32
31
  end
33
32
 
34
- def run_challenge(challenge)
35
- middleware.call(challenge)
36
- challenge.result
33
+ def run_challenge(challenge, spies = Polytrix::Spies)
34
+ source_file = challenge[:source_file].to_s
35
+ basedir = challenge[:basedir].to_s
36
+ command = challenge_command(source_file, basedir)
37
+ spies.observe(challenge) do
38
+ execution_result = run_command(command, cwd: basedir, env: environment_variables(challenge[:vars]))
39
+ challenge[:result] = Result.new(execution_result: execution_result, source_file: source_file)
40
+ end
41
+ challenge[:result]
37
42
  end
38
43
 
39
- private
44
+ protected
40
45
 
41
- def middleware
42
- Polytrix.configuration.middleware
46
+ def environment_variables(test_vars)
47
+ global_vars = begin
48
+ Polytrix.manifest[:global_env].dup
49
+ rescue
50
+ {}
51
+ end
52
+ global_vars.merge(test_vars.dup)
43
53
  end
44
54
  end
45
55
  end
data/lib/polytrix/cli.rb CHANGED
@@ -2,6 +2,7 @@ require 'thor'
2
2
 
3
3
  require 'polytrix'
4
4
  require 'polytrix/command'
5
+ require 'polytrix/command/report'
5
6
 
6
7
  module Polytrix
7
8
  class CLI < Thor # rubocop:disable ClassLength
@@ -29,8 +30,6 @@ module Polytrix
29
30
  str_const = Thor::Util.camel_case(command)
30
31
  klass = ::Polytrix::Command.const_get(str_const)
31
32
  klass.new(args, options, command_options).call
32
- rescue ArgumentError => e
33
- abort e.message
34
33
  end
35
34
  end
36
35
 
@@ -44,17 +43,30 @@ module Polytrix
44
43
  # Constructs a new instance.
45
44
  def initialize(*args)
46
45
  super
46
+ Polytrix.logger = Polytrix.default_file_logger
47
47
  $stdout.sync = true
48
48
  end
49
49
 
50
+ def self.filter_options
51
+ method_option :failed,
52
+ type: :boolean,
53
+ desc: 'Only list tests that failed / passed'
54
+ method_option :skipped,
55
+ type: :boolean,
56
+ desc: 'Only list tests that were skipped / executed'
57
+ method_option :samples,
58
+ type: :boolean,
59
+ desc: 'Only list tests that have sample code / do not have sample code'
60
+ end
61
+
50
62
  desc 'list [INSTANCE|REGEXP|all]', 'Lists one or more scenarios'
51
- method_option :bare,
52
- aliases: '-b',
53
- type: :boolean,
54
- desc: 'List the name of each scenario only, one per line'
55
63
  method_option :log_level,
56
64
  aliases: '-l',
57
65
  desc: 'Set the log level (debug, info, warn, error, fatal)'
66
+ method_option :format,
67
+ desc: 'List output format',
68
+ enum: %w(text markdown json yaml),
69
+ default: 'text'
58
70
  method_option :manifest,
59
71
  aliases: '-m',
60
72
  desc: 'The Polytrix test manifest file location',
@@ -65,22 +77,26 @@ module Polytrix
65
77
  default: 'tests/polytrix'
66
78
  method_option :solo,
67
79
  desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
68
- # , default: 'polytrix.yml'
80
+ # , default: 'polytrix.yml'
69
81
  method_option :solo_glob,
70
82
  desc: 'The globbing pattern to find code samples in solo mode'
83
+ method_option :source,
84
+ type: :boolean,
85
+ desc: 'Include source file in listing'
86
+ filter_options
71
87
  def list(*args)
72
88
  update_config!
73
89
  perform('list', 'list', args, options)
74
90
  end
75
91
 
76
- desc 'report [INSTANCE|REGEXP|all]', 'Summary report for one or more scenarios'
77
- method_option :bare,
78
- aliases: '-b',
79
- type: :boolean,
80
- desc: 'List the name of each scenario only, one per line'
92
+ desc 'show [INSTANCE|REGEXP|all]', 'Show detailed status for one or more scenarios'
81
93
  method_option :log_level,
82
94
  aliases: '-l',
83
95
  desc: 'Set the log level (debug, info, warn, error, fatal)'
96
+ method_option :format,
97
+ desc: 'List output format',
98
+ enum: %w(text markdown json yaml),
99
+ default: 'text'
84
100
  method_option :manifest,
85
101
  aliases: '-m',
86
102
  desc: 'The Polytrix test manifest file location',
@@ -91,25 +107,28 @@ module Polytrix
91
107
  default: 'tests/polytrix'
92
108
  method_option :solo,
93
109
  desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
94
- # , default: 'polytrix.yml'
110
+ # , default: 'polytrix.yml'
95
111
  method_option :solo_glob,
96
112
  desc: 'The globbing pattern to find code samples in solo mode'
97
- def report(*args)
113
+ filter_options
114
+ def show(*args)
98
115
  update_config!
99
- perform('report', 'report', args, options)
116
+ perform('show', 'show', args, options)
100
117
  end
101
118
 
102
119
  {
103
- clone: "Change scenario state to cloned. " \
104
- "Clone the code sample from git",
105
- bootstrap: "Change scenario state to bootstraped. " \
106
- "Running bootstrap scripts for the implementor",
107
- exec: "Change instance state to executed. " \
108
- "Execute the code sample and capture the results.",
109
- verify: "Change instance state to verified. " \
110
- "Assert that the captured results match the expectations for the scenario.",
111
- destroy: "Change scenario state to destroyed. " \
112
- "Delete all information for one or more scenarios"
120
+ clone: 'Change scenario state to cloned. ' \
121
+ 'Clone the code sample from git',
122
+ bootstrap: 'Change scenario state to bootstraped. ' \
123
+ 'Running bootstrap scripts for the implementor',
124
+ detect: 'Find sample code that matches a test scenario. ' \
125
+ 'Attempts to locate a code sample with a filename that the test scenario name.',
126
+ exec: 'Change instance state to executed. ' \
127
+ 'Execute the code sample and capture the results.',
128
+ verify: 'Change instance state to verified. ' \
129
+ 'Assert that the captured results match the expectations for the scenario.',
130
+ destroy: 'Change scenario state to destroyed. ' \
131
+ 'Delete all information for one or more scenarios'
113
132
  }.each do |action, short_desc|
114
133
  desc(
115
134
  "#{action} [INSTANCE|REGEXP|all]",
@@ -146,7 +165,6 @@ module Polytrix
146
165
  define_method(action) do |*args|
147
166
  update_config!
148
167
  action_options = options.dup
149
- action_options['on'] = :implementor if [:clone, :bootstrap].include? action
150
168
  perform(action, 'action', args, action_options)
151
169
  end
152
170
  end
@@ -179,7 +197,7 @@ module Polytrix
179
197
  default: 'tests/polytrix'
180
198
  method_option :solo,
181
199
  desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
182
- # , default: 'polytrix.yml'
200
+ # , default: 'polytrix.yml'
183
201
  method_option :solo_glob,
184
202
  desc: 'The globbing pattern to find code samples in solo mode'
185
203
  def test(*args)
@@ -188,54 +206,20 @@ module Polytrix
188
206
  perform('test', 'test', args, action_options)
189
207
  end
190
208
 
191
- desc 'code2doc [INSTANCE|REGEXP|all]',
192
- 'Generates documenation from sample code for one or more scenarios'
193
- long_desc <<-DESC
194
- This task will convert annotated sample code to documentation. Markdown or
195
- reStructureText are supported.
196
- DESC
197
- method_option :log_level,
198
- aliases: '-l',
199
- desc: 'Set the log level (debug, info, warn, error, fatal)'
200
- method_option :manifest,
201
- aliases: '-m',
202
- desc: 'The Polytrix test manifest file location',
203
- default: 'polytrix.yml'
204
- method_option :solo,
205
- desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
206
- # , default: 'polytrix.yml'
207
- method_option :solo_glob,
208
- desc: 'The globbing pattern to find code samples in solo mode'
209
- method_option :format,
210
- aliases: '-f',
211
- enum: %w(md rst),
212
- default: 'md',
213
- desc: 'Target documentation format'
214
- method_option :target_dir,
215
- aliases: '-d',
216
- default: 'docs/',
217
- desc: 'The target directory where documentation for generated documentation.'
218
- def code2doc(*args)
219
- update_config!
220
- action_options = options.dup
221
- perform('code2doc', 'action', args, action_options)
222
- end
223
-
224
209
  desc 'version', "Print Polytrix's version information"
225
210
  def version
226
211
  puts "Polytrix version #{Polytrix::VERSION}"
227
212
  end
228
- map %w[-v --version] => :version
213
+ map %w(-v --version) => :version
229
214
 
230
- # register Polytrix::CLI::Report, "init",
231
- # "init", "Adds some configuration to your cookbook so Polytrix can rock"
232
- # long_desc <<-D, :for => "init"
233
- # Init will add Test Polytrix support to an existing project for
234
- # convergence integration testing. A default .polytrix.yml file (which is
235
- # intended to be customized) is created in the project's root directory
236
- # and one or more gems will be added to the project's Gemfile.
215
+ desc 'report', 'Generate reports'
216
+ subcommand 'report', Polytrix::Command::Report
217
+ # register Polytrix::Command::Report, 'report',
218
+ # 'report', 'Generates a report'
219
+ # long_desc <<-D, for: 'report'
220
+ # Polytrix will generate an HTML report.
237
221
  # D
238
- # tasks["init"].options = Polytrix::CLI::Report.class_options
222
+ # tasks['report'].options = Polytrix::Command::Report.class_options
239
223
 
240
224
  private
241
225
 
@@ -8,10 +8,10 @@ module Polytrix
8
8
  bright_cyan: 96, bright_white: 97
9
9
  }.freeze
10
10
 
11
- COLORS = %w[
11
+ COLORS = %w(
12
12
  cyan yellow green magenta blue bright_cyan bright_yellow
13
13
  bright_green bright_magenta bright_blue
14
- ].freeze
14
+ ).freeze
15
15
 
16
16
  # Returns an ansi escaped string representing a color control sequence.
17
17
  #
@@ -5,15 +5,16 @@ module Polytrix
5
5
  class Action < Polytrix::Command::Base
6
6
  include RunAction
7
7
 
8
+ IMPLEMENTOR_ACTIONS = [:clone, :bootstrap] # These are run once per implementor, not per test
9
+
8
10
  # Invoke the command.
9
11
  def call
10
12
  banner "Starting Polytrix (v#{Polytrix::VERSION})"
11
13
  elapsed = Benchmark.measure do
12
14
  setup
13
- tests = parse_subcommand(args.first)
15
+ tests = parse_subcommand(args.pop)
14
16
  implementors = tests.map(&:implementor).uniq
15
- # Logging.mdc['command'] = action
16
- if [:clone, :bootstrap].include? action # actions on implementors
17
+ if IMPLEMENTOR_ACTIONS.include? action # actions on implementors
17
18
  run_action(action, implementors)
18
19
  else # actions on tests
19
20
  run_action(action, tests)