polytrix 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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)