polytrix 0.1.0.pre → 0.1.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +7 -2
  4. data/.travis.yml +2 -1
  5. data/Gemfile +1 -0
  6. data/README.md +190 -98
  7. data/Rakefile +8 -6
  8. data/bin/polytrix +2 -1
  9. data/docs/samples/code2doc/java/HelloWorld.md +4 -0
  10. data/docs/samples/code2doc/java/Quine.md +2 -0
  11. data/docs/samples/code2doc/python/hello_world.md +2 -0
  12. data/docs/samples/code2doc/python/quine.md +2 -0
  13. data/docs/samples/code2doc/ruby/hello_world.md +4 -0
  14. data/features/bootstrapping.feature +36 -0
  15. data/features/cloning.feature +34 -0
  16. data/features/execution.feature +2 -16
  17. data/features/fixtures/configs/empty.yml +12 -1
  18. data/features/fixtures/configs/hello_world.yml +11 -1
  19. data/features/fixtures/spec/polytrix_spec.rb +1 -4
  20. data/features/solo.feature +12 -0
  21. data/features/states.feature +40 -0
  22. data/features/step_definitions/sdk_steps.rb +11 -1
  23. data/features/support/env.rb +2 -1
  24. data/lib/polytrix/challenge.rb +211 -13
  25. data/lib/polytrix/challenge_result.rb +9 -0
  26. data/lib/polytrix/challenge_runner.rb +4 -11
  27. data/lib/polytrix/challenges.rb +16 -0
  28. data/lib/polytrix/cli/report.rb +0 -4
  29. data/lib/polytrix/cli.rb +229 -137
  30. data/lib/polytrix/color.rb +40 -0
  31. data/lib/polytrix/command/action.rb +26 -0
  32. data/lib/polytrix/command/list.rb +53 -0
  33. data/lib/polytrix/command/rundoc.rb +27 -0
  34. data/lib/polytrix/command/test.rb +24 -0
  35. data/lib/polytrix/command.rb +209 -0
  36. data/lib/polytrix/configuration.rb +30 -40
  37. data/lib/polytrix/core/file_system_helper.rb +2 -5
  38. data/lib/polytrix/core/hashie.rb +14 -0
  39. data/lib/polytrix/core/implementor.rb +52 -12
  40. data/lib/polytrix/core/manifest_section.rb +4 -0
  41. data/lib/polytrix/core/string_helpers.rb +15 -0
  42. data/lib/polytrix/documentation/helpers/code_helper.rb +3 -1
  43. data/lib/polytrix/error.rb +209 -0
  44. data/lib/polytrix/logger.rb +365 -8
  45. data/lib/polytrix/logging.rb +34 -0
  46. data/lib/polytrix/manifest.rb +40 -26
  47. data/lib/polytrix/result.rb +1 -0
  48. data/lib/polytrix/rspec.rb +7 -5
  49. data/lib/polytrix/runners/buff_shellout_executor.rb +19 -0
  50. data/lib/polytrix/runners/executor.rb +32 -0
  51. data/lib/polytrix/runners/mixlib_shellout_executor.rb +83 -0
  52. data/lib/polytrix/state_file.rb +60 -0
  53. data/lib/polytrix/util.rb +155 -0
  54. data/lib/polytrix/validation.rb +1 -1
  55. data/lib/polytrix/validator.rb +9 -5
  56. data/lib/polytrix/version.rb +1 -1
  57. data/lib/polytrix.rb +55 -33
  58. data/polytrix.gemspec +4 -2
  59. data/polytrix.rb +0 -5
  60. data/{polytrix_tests.yml → polytrix.yml} +5 -0
  61. data/samples/default_bootstrap.rb +0 -7
  62. data/samples/polytrix.rb +0 -9
  63. data/samples/{polytrix_tests.yml → polytrix.yml} +11 -0
  64. data/samples/polytrix_cli.sh +1 -1
  65. data/spec/fabricators/implementor_fabricator.rb +20 -0
  66. data/spec/fabricators/manifest_fabricator.rb +4 -1
  67. data/spec/fixtures/{polytrix_tests.yml → polytrix.yml} +10 -0
  68. data/spec/polytrix/challenge_runner_spec.rb +3 -2
  69. data/spec/polytrix/challenge_spec.rb +5 -4
  70. data/spec/polytrix/cli_spec.rb +23 -26
  71. data/spec/polytrix/configuration_spec.rb +4 -43
  72. data/spec/polytrix/documentation/helpers/code_helper_spec.rb +1 -1
  73. data/spec/polytrix/documentation_generator_spec.rb +2 -0
  74. data/spec/polytrix/implementor_spec.rb +44 -2
  75. data/spec/polytrix/manifest_spec.rb +7 -4
  76. data/spec/polytrix_spec.rb +9 -11
  77. data/spec/thor_spy.rb +2 -0
  78. metadata +66 -16
  79. data/features/fixtures/spec/polytrix_merge.rb +0 -5
  80. data/features/reporting.feature +0 -140
  81. data/lib/polytrix/executor.rb +0 -89
  82. data/samples/sdks/custom/polytrix.yml +0 -2
data/lib/polytrix/cli.rb CHANGED
@@ -1,158 +1,250 @@
1
- require 'polytrix'
2
1
  require 'thor'
3
2
 
4
- module Polytrix
5
- module CLI
6
- autoload :Add, 'polytrix/cli/add'
7
- autoload :Report, 'polytrix/cli/report'
8
-
9
- class Base < Thor
10
- include Polytrix::Core::FileSystemHelper
11
-
12
- def self.config_options
13
- # I had trouble with class_option and subclasses...
14
- method_option :manifest, type: 'string', default: 'polytrix_tests.yml', desc: 'The Polytrix test manifest file'
15
- method_option :config, type: 'string', default: 'polytrix.rb', desc: 'The Polytrix config file'
16
- end
17
-
18
- def self.log_options
19
- method_option :quiet, type: :boolean, default: false, desc: 'Do not print log messages'
20
- end
21
-
22
- def self.doc_options
23
- method_option :target_dir, type: :string, default: 'docs'
24
- method_option :lang, enum: Polytrix::Documentation::CommentStyles::COMMENT_STYLES.keys, desc: 'Source language (auto-detected if not specified)'
25
- method_option :format, enum: %w(md rst), default: 'md'
26
- end
3
+ require 'polytrix'
4
+ require 'polytrix/command'
27
5
 
28
- def self.sdk_options
29
- method_option :sdk, type: 'string', desc: 'An implementor name or directory', default: '.'
6
+ module Polytrix
7
+ class CLI < Thor # rubocop:disable ClassLength
8
+ # Common module to load and invoke a CLI-implementation agnostic command.
9
+ module PerformCommand
10
+ # Perform a scenario subcommand.
11
+ #
12
+ # @param task [String] action to take, usually corresponding to the
13
+ # subcommand name
14
+ # @param command [String] command class to create and invoke]
15
+ # @param args [Array] remainder arguments from processed ARGV
16
+ # (default: `nil`)
17
+ # @param additional_options [Hash] additional configuration needed to
18
+ # set up the command class (default: `{}`)
19
+ def perform(task, command, args = nil, additional_options = {})
20
+ require "polytrix/command/#{command}"
21
+
22
+ command_options = {
23
+ action: task,
24
+ help: -> { help(task) },
25
+ test_dir: @test_dir,
26
+ shell: shell
27
+ }.merge(additional_options)
28
+
29
+ str_const = Thor::Util.camel_case(command)
30
+ klass = ::Polytrix::Command.const_get(str_const)
31
+ klass.new(args, options, command_options).call
32
+ rescue ArgumentError => e
33
+ abort e.message
30
34
  end
35
+ end
31
36
 
32
- protected
33
-
34
- def find_sdks(sdks)
35
- sdks.map do |sdk|
36
- implementor = Polytrix.implementors.find { |i| i.name == sdk }
37
- abort "SDK #{sdk} not found" if implementor.nil?
38
- implementor
39
- end
40
- end
37
+ include Logging
38
+ include PerformCommand
41
39
 
42
- def pick_implementor(sdk)
43
- Polytrix.implementors.find { |i| i.name == sdk } || Polytrix.configuration.implementor(sdk)
44
- end
40
+ # The maximum number of concurrent instances that can run--which is a bit
41
+ # high
42
+ MAX_CONCURRENCY = 9999
45
43
 
46
- def debug(msg)
47
- say("polytrix::debug: #{msg}", :cyan) if debugging?
48
- end
44
+ # Constructs a new instance.
45
+ def initialize(*args)
46
+ super
47
+ $stdout.sync = true
48
+ # Polytrix.logger = Polytrix.default_file_logger
49
+ end
49
50
 
50
- def debugging?
51
- !ENV['POLYTRIX_DEBUG'].nil?
52
- end
51
+ desc 'list [INSTANCE|REGEXP|all]', 'Lists one or more scenarios'
52
+ method_option :bare,
53
+ aliases: '-b',
54
+ type: :boolean,
55
+ desc: 'List the name of each scenario only, one per line'
56
+ method_option :log_level,
57
+ aliases: '-l',
58
+ desc: 'Set the log level (debug, info, warn, error, fatal)'
59
+ method_option :manifest,
60
+ aliases: '-m',
61
+ desc: 'The Polytrix test manifest file location',
62
+ default: 'polytrix.yml'
63
+ method_option :test_dir,
64
+ aliases: '-t',
65
+ desc: 'The Polytrix test directory',
66
+ default: 'tests/polytrix'
67
+ method_option :solo,
68
+ desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
69
+ # , default: 'polytrix.yml'
70
+ method_option :solo_glob,
71
+ desc: 'The globbing pattern to find code samples in solo mode'
72
+ def list(*args)
73
+ update_config!
74
+ perform('list', 'list', args, options)
75
+ end
53
76
 
54
- def setup
55
- manifest_file = File.expand_path options[:manifest]
56
- config_file = File.expand_path options[:config]
57
- if File.exists? manifest_file
58
- debug "Loading manifest file: #{manifest_file}"
59
- Polytrix.configuration.test_manifest = manifest_file if File.exists? manifest_file
60
- end
61
- if File.exists? config_file
62
- debug "Loading Polytrix config: #{config_file}"
63
- require_relative config_file
64
- end
77
+ {
78
+ clone: "Change scenario state to cloned. " \
79
+ "Clone the code sample from git",
80
+ bootstrap: "Change scenario state to bootstraped. " \
81
+ "Running bootstrap scripts for the implementor",
82
+ exec: "Change instance state to executed. " \
83
+ "Execute the code sample and capture the results.",
84
+ verify: "Change instance state to verified. " \
85
+ "Assert that the captured results match the expectations for the scenario.",
86
+ destroy: "Change scenario state to destroyed. " \
87
+ "Delete all information for one or more scenarios"
88
+ }.each do |action, short_desc|
89
+ desc(
90
+ "#{action} [INSTANCE|REGEXP|all]",
91
+ short_desc
92
+ )
93
+ long_desc <<-DESC
94
+ The scenario states are in order: cloned, bootstrapped, executed, verified.
95
+ Change one or more scenarios from the current state to the #{action} state. Actions for all
96
+ intermediate states will be executed.
97
+ DESC
98
+ method_option :concurrency,
99
+ aliases: '-c',
100
+ type: :numeric,
101
+ lazy_default: MAX_CONCURRENCY,
102
+ desc: <<-DESC.gsub(/^\s+/, '').gsub(/\n/, ' ')
103
+ Run a #{action} against all matching instances concurrently. Only N
104
+ instances will run at the same time if a number is given.
105
+ DESC
106
+ method_option :log_level,
107
+ aliases: '-l',
108
+ desc: 'Set the log level (debug, info, warn, error, fatal)'
109
+ method_option :manifest,
110
+ aliases: '-m',
111
+ desc: 'The Polytrix test manifest file location',
112
+ default: 'polytrix.yml'
113
+ method_option :test_dir,
114
+ aliases: '-t',
115
+ desc: 'The Polytrix test directory',
116
+ default: 'tests/polytrix'
117
+ method_option :solo,
118
+ desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
119
+ method_option :solo_glob,
120
+ desc: 'The globbing pattern to find code samples in solo mode'
121
+ define_method(action) do |*args|
122
+ update_config!
123
+ action_options = options.dup
124
+ action_options['on'] = :implementor if [:clone, :bootstrap].include? action
125
+ perform(action, 'action', args, action_options)
65
126
  end
66
127
  end
67
128
 
68
- class Main < Base
69
- include Polytrix::Documentation::Helpers::CodeHelper
70
-
71
- # register Add, :add, 'add', 'Add implementors or code samples'
72
- # register Report, :report, 'report', 'Generate test reports'
73
- desc 'add', 'Add implementors or code samples'
74
- subcommand 'add', Add
75
-
76
- desc 'report', 'Generate test reports'
77
- subcommand 'report', Report
78
-
79
- desc 'code2doc FILES', 'Converts annotated code to Markdown or reStructuredText'
80
- doc_options
81
- def code2doc(*files)
82
- if files.empty?
83
- help('code2doc')
84
- abort 'No FILES were specified, check usage above'
85
- end
86
-
87
- files.each do |file|
88
- target_file_name = File.basename(file, File.extname(file)) + ".#{options[:format]}"
89
- target_file = File.join(options[:target_dir], target_file_name)
90
- say_status 'polytrix:code2doc', "Converting #{file} to #{target_file}", !quiet?
91
- doc = Polytrix::DocumentationGenerator.new.code2doc(file, options[:lang])
92
- FileUtils.mkdir_p File.dirname(target_file)
93
- File.write(target_file, doc)
94
- end
95
- rescue Polytrix::Documentation::CommentStyles::UnknownStyleError => e
96
- abort "Unknown file extension: #{e.extension}, please use --lang to set the language manually"
97
- end
129
+ desc 'test [INSTANCE|REGEXP|all]',
130
+ 'Test (clone, bootstrap, exec, and verify) one or more scenarios'
131
+ long_desc <<-DESC
132
+ The scenario states are in order: cloned, bootstrapped, executed, verified.
133
+ Test changes the state of one or more scenarios executes
134
+ the actions for each state up to verify.
135
+ DESC
136
+ method_option :concurrency,
137
+ aliases: '-c',
138
+ type: :numeric,
139
+ lazy_default: MAX_CONCURRENCY,
140
+ desc: <<-DESC.gsub(/^\s+/, '').gsub(/\n/, ' ')
141
+ Run a test against all matching instances concurrently. Only N
142
+ instances will run at the same time if a number is given.
143
+ DESC
144
+ method_option :log_level,
145
+ aliases: '-l',
146
+ desc: 'Set the log level (debug, info, warn, error, fatal)'
147
+ method_option :manifest,
148
+ aliases: '-m',
149
+ desc: 'The Polytrix test manifest file location',
150
+ default: 'polytrix.yml'
151
+ method_option :test_dir,
152
+ aliases: '-t',
153
+ desc: 'The Polytrix test directory',
154
+ default: 'tests/polytrix'
155
+ method_option :solo,
156
+ desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
157
+ # , default: 'polytrix.yml'
158
+ method_option :solo_glob,
159
+ desc: 'The globbing pattern to find code samples in solo mode'
160
+ def test(*args)
161
+ update_config!
162
+ action_options = options.dup
163
+ perform('test', 'test', args, action_options)
164
+ end
98
165
 
99
- desc 'exec', 'Executes code sample(s), using the SDK settings if provided'
100
- method_option :code2doc, type: :boolean, desc: 'Convert successfully executed code samples to documentation using the code2doc command'
101
- doc_options
102
- sdk_options
103
- config_options
104
- def exec(*files)
105
- setup
106
- if files.empty?
107
- help('exec')
108
- abort 'No FILES were specified, check usage above'
109
- end
110
-
111
- exec_options = {
112
- # default_implementor: pick_implementor(options[:sdk])
113
- }
114
-
115
- files.each do | file |
116
- say_status 'polytrix:exec', "Running #{file}..."
117
- results = Polytrix.exec(file, exec_options)
118
- display_results results
119
- code2doc(file) if options[:code2doc]
120
- end
121
- end
166
+ desc 'code2doc [INSTANCE|REGEXP|all]',
167
+ 'Generates documenation from sample code for one or more scenarios'
168
+ long_desc <<-DESC
169
+ This task will convert annotated sample code to documentation. Markdown or
170
+ reStructureText are supported.
171
+ DESC
172
+ method_option :log_level,
173
+ aliases: '-l',
174
+ desc: 'Set the log level (debug, info, warn, error, fatal)'
175
+ method_option :manifest,
176
+ aliases: '-m',
177
+ desc: 'The Polytrix test manifest file location',
178
+ default: 'polytrix.yml'
179
+ method_option :solo,
180
+ desc: 'Enable solo mode - Polytrix will auto-configure a single implementor and its scenarios'
181
+ # , default: 'polytrix.yml'
182
+ method_option :solo_glob,
183
+ desc: 'The globbing pattern to find code samples in solo mode'
184
+ method_option :format,
185
+ aliases: '-f',
186
+ enum: %w(md rst),
187
+ default: 'md',
188
+ desc: 'Target documentation format'
189
+ method_option :target_dir,
190
+ aliases: '-d',
191
+ default: 'docs/',
192
+ desc: 'The target directory where documentation for generated documentation.'
193
+ def code2doc(*args)
194
+ update_config!
195
+ action_options = options.dup
196
+ perform('code2doc', 'action', args, action_options)
197
+ end
122
198
 
123
- desc 'bootstrap [SDKs]', 'Bootstraps the SDK by installing dependencies'
124
- config_options
125
- def bootstrap(*sdks)
126
- setup
127
- Polytrix.bootstrap(*sdks)
128
- rescue ArgumentError => e
129
- abort e.message
130
- end
199
+ desc 'version', "Print Polytrix's version information"
200
+ def version
201
+ puts "Polytrix version #{Polytrix::VERSION}"
202
+ end
203
+ map %w[-v --version] => :version
204
+
205
+ # register Polytrix::Generator::Init, "init",
206
+ # "init", "Adds some configuration to your cookbook so Polytrix can rock"
207
+ # long_desc <<-D, :for => "init"
208
+ # Init will add Test Polytrix support to an existing project for
209
+ # convergence integration testing. A default .polytrix.yml file (which is
210
+ # intended to be customized) is created in the project's root directory
211
+ # and one or more gems will be added to the project's Gemfile.
212
+ # D
213
+ # tasks["init"].options = Polytrix::Generator::Init.class_options
214
+
215
+ private
216
+
217
+ # Ensure the any failing commands exit non-zero.
218
+ #
219
+ # @return [true] you die always on failure
220
+ # @api private
221
+ def self.exit_on_failure?
222
+ true
223
+ end
131
224
 
132
- desc 'test [SDKs]', 'Runs and tests the code samples'
133
- method_option :rspec_options, format: 'string', desc: 'Extra options to pass to rspec'
134
- config_options
135
- def test(*sdks)
136
- setup
137
- implementors = find_sdks(sdks)
138
- Polytrix.configuration.rspec_options = options[:rspec_options]
139
- Polytrix.run_tests(implementors)
140
- end
225
+ # @return [Logger] the common logger
226
+ # @api private
227
+ def logger
228
+ Polytrix.logger
229
+ end
141
230
 
142
- protected
231
+ # Update and finalize options for logging, concurrency, and other concerns.
232
+ #
233
+ # @api private
234
+ def update_config!
235
+ end
143
236
 
144
- def quiet?
145
- options[:quiet] || false
146
- end
237
+ # If auto_init option is active, invoke the init generator.
238
+ #
239
+ # @api private
240
+ def ensure_initialized
241
+ end
147
242
 
148
- def display_results(challenge)
149
- short_name = challenge.name
150
- exit_code = challenge.result.execution_result.exitstatus
151
- color = exit_code == 0 ? :green : :red
152
- stderr = challenge.result.execution_result.stderr
153
- say_status "polytrix:exec[#{short_name}][stderr]", stderr, !quiet? unless stderr.empty?
154
- say_status "polytrix:exec[#{short_name}]", "Finished with exec code: #{challenge.result.execution_result.exitstatus}", color unless quiet?
155
- end
243
+ def duration(total)
244
+ total = 0 if total.nil?
245
+ minutes = (total / 60).to_i
246
+ seconds = (total - (minutes * 60))
247
+ format('(%dm%.2fs)', minutes, seconds)
156
248
  end
157
249
  end
158
250
  end
@@ -0,0 +1,40 @@
1
+ module Polytrix
2
+ module Color
3
+ ANSI = {
4
+ reset: 0, black: 30, red: 31, green: 32, yellow: 33,
5
+ blue: 34, magenta: 35, cyan: 36, white: 37,
6
+ bright_black: 90, bright_red: 91, bright_green: 92,
7
+ bright_yellow: 93, bright_blue: 94, bright_magenta: 95,
8
+ bright_cyan: 96, bright_white: 97
9
+ }.freeze
10
+
11
+ COLORS = %w[
12
+ cyan yellow green magenta blue bright_cyan bright_yellow
13
+ bright_green bright_magenta bright_blue
14
+ ].freeze
15
+
16
+ # Returns an ansi escaped string representing a color control sequence.
17
+ #
18
+ # @param name [Symbol] a valid color representation, taken from
19
+ # Polytrix::Color::ANSI
20
+ # @return [String] an ansi escaped string if the color is valid and an
21
+ # empty string otherwise
22
+ def self.escape(name)
23
+ return '' if name.nil?
24
+ return '' unless ANSI[name]
25
+ "\e[#{ANSI[name]}m"
26
+ end
27
+
28
+ # Returns a colorized ansi escaped string with the given color.
29
+ #
30
+ # @param str [String] a string to colorize
31
+ # @param name [Symbol] a valid color representation, taken from
32
+ # Polytrix::Color::ANSI
33
+ # @return [String] an ansi escaped string if the color is valid and an
34
+ # unescaped string otherwise
35
+ def self.colorize(str, name)
36
+ color = escape(name)
37
+ color.empty? ? str : "#{color}#{str}#{escape(:reset)}"
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ require 'benchmark'
2
+
3
+ module Polytrix
4
+ module Command
5
+ class Action < Polytrix::Command::Base
6
+ include RunAction
7
+
8
+ # Invoke the command.
9
+ def call
10
+ banner "Starting Polytrix (v#{Polytrix::VERSION})"
11
+ elapsed = Benchmark.measure do
12
+ setup
13
+ tests = parse_subcommand(args.first)
14
+ implementors = tests.map(&:implementor).uniq
15
+ # Logging.mdc['command'] = action
16
+ if [:clone, :bootstrap].include? action # actions on implementors
17
+ run_action(action, implementors)
18
+ else # actions on tests
19
+ run_action(action, tests)
20
+ end
21
+ end
22
+ banner "Polytrix is finished. #{Util.duration(elapsed.real)}"
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ module Polytrix
2
+ module Command
3
+ class List < Polytrix::Command::Base
4
+ def call
5
+ # Logging.mdc['command'] = 'list'
6
+
7
+ setup
8
+ tests = parse_subcommand(args.first)
9
+
10
+ table = [
11
+ [
12
+ colorize('Suite', :green), colorize('Scenario', :green),
13
+ colorize('Implementor', :green), colorize('Status', :green)
14
+ ]
15
+ ]
16
+ table += tests.map do | challenge |
17
+ [
18
+ color_pad(challenge.suite),
19
+ color_pad(challenge.name),
20
+ color_pad(challenge.implementor.name),
21
+ format_last_action(challenge)
22
+ ]
23
+ end
24
+ shell.print_table table
25
+ end
26
+
27
+ private
28
+
29
+ def print_table(*args)
30
+ shell.print_table(*args)
31
+ end
32
+
33
+ def colorize(string, *args)
34
+ shell.set_color(string, *args)
35
+ end
36
+
37
+ def color_pad(string)
38
+ string + colorize('', :white)
39
+ end
40
+
41
+ def format_last_action(challenge)
42
+ case challenge.last_action
43
+ when 'clone' then colorize('Cloned', :cyan)
44
+ when 'bootstrap' then colorize('Bootstrapped', :magenta)
45
+ when 'exec' then colorize('Executed', :blue)
46
+ when 'verify' then colorize("Verified (Level #{challenge.verification_level})", :yellow)
47
+ when nil then colorize('<Not Found>', :red)
48
+ else colorize("<Unknown (#{challenge.last_action})>", :white)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,27 @@
1
+ module Polytrix
2
+ module Command
3
+ class RunDoc < Thor::Group
4
+ class_option :format,
5
+ aliases: '-f',
6
+ enum: %w(markdown rst),
7
+ default: 'markdown',
8
+ desc: 'The documentation input format'
9
+
10
+ def rundoc
11
+ files = args
12
+ # Logging.mdc['command'] = 'rundoc'
13
+ if files.empty?
14
+ # help('code2doc')
15
+ abort 'No FILES were specified, check usage above'
16
+ end
17
+
18
+ files.each do |file|
19
+ target_file_name = File.basename(file, File.extname(file)) + ".#{options[:format]}"
20
+ target_file = File.join(options[:target_dir], target_file_name)
21
+ say_status 'polytrix:code2doc', "Converting #{file} to #{target_file}"
22
+ Polytrix::DocumentationExecutor.new.execute file
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,24 @@
1
+ require 'polytrix/command'
2
+
3
+ require 'benchmark'
4
+
5
+ module Polytrix
6
+ module Command
7
+ # Command to test one or more instances.
8
+ class Test < Polytrix::Command::Base
9
+ include RunAction
10
+
11
+ # Invoke the command.
12
+ def call
13
+ banner "Starting Polytrix (v#{Polytrix::VERSION})"
14
+ elapsed = Benchmark.measure do
15
+ setup
16
+ results = parse_subcommand(args.join('|'))
17
+
18
+ run_action(:test, results)
19
+ end
20
+ banner "Polytrix is finished. #{Util.duration(elapsed.real)}"
21
+ end
22
+ end
23
+ end
24
+ end