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
@@ -0,0 +1,60 @@
1
+ require 'hashie'
2
+
3
+ module Polytrix
4
+ class StateFileLoadError < StandardError; end
5
+ class StateFile
6
+ def initialize(polytrix_root, name)
7
+ @file_name = File.expand_path(
8
+ File.join(polytrix_root, '.polytrix', "#{name}.yml")
9
+ )
10
+ end
11
+
12
+ def read
13
+ if File.exist?(file_name)
14
+ Hashie::Mash.load(file_name).dup
15
+ else
16
+ Hashie::Mash.new
17
+ end
18
+ end
19
+
20
+ def write(state)
21
+ dir = File.dirname(file_name)
22
+ serialized_string = serialize_hash(Util.stringified_hash(state))
23
+
24
+ FileUtils.mkdir_p(dir) unless File.directory?(dir)
25
+ File.open(file_name, 'wb') { |f| f.write(serialized_string) }
26
+ end
27
+
28
+ def destroy
29
+ FileUtils.rm_f(file_name) if File.exist?(file_name)
30
+ end
31
+
32
+ def diagnose
33
+ raw = read
34
+ result = {}
35
+ raw.keys.sort.each { |k| result[k] = raw[k] }
36
+ result
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :file_name
42
+
43
+ # @api private
44
+ def read_file
45
+ IO.read(file_name)
46
+ end
47
+
48
+ # @api private
49
+ def deserialize_string(string)
50
+ SafeYAML.load(string)
51
+ rescue SyntaxError, Psych::SyntaxError => ex
52
+ raise StateFileLoadError, "Error parsing #{file_name} (#{ex.message})"
53
+ end
54
+
55
+ # @api private
56
+ def serialize_hash(hash)
57
+ ::YAML.dump(hash)
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,155 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Fletcher Nichol (<fnichol@nichol.ca>)
4
+ #
5
+ # Copyright (C) 2012, 2013, 2014, Fletcher Nichol
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ module Polytrix
20
+ # Stateless utility methods used in different contexts. Essentially a mini
21
+ # PassiveSupport library.
22
+ module Util
23
+ # Returns the standard library Logger level constants for a given symbol
24
+ # representation.
25
+ #
26
+ # @param symbol [Symbol] symbol representation of a logger level (:debug,
27
+ # :info, :warn, :error, :fatal)
28
+ # @return [Integer] Logger::Severity constant value or nil if input is not
29
+ # valid
30
+ def self.to_logger_level(symbol)
31
+ return nil unless [:debug, :info, :warn, :error, :fatal].include?(symbol)
32
+
33
+ Logger.const_get(symbol.to_s.upcase)
34
+ end
35
+
36
+ # Returns the symbol represenation of a logging levels for a given
37
+ # standard library Logger::Severity constant.
38
+ #
39
+ # @param const [Integer] Logger::Severity constant value for a logging
40
+ # level (Logger::DEBUG, Logger::INFO, Logger::WARN, Logger::ERROR,
41
+ # Logger::FATAL)
42
+ # @return [Symbol] symbol representation of the logging level
43
+ def self.from_logger_level(const)
44
+ case const
45
+ when Logger::DEBUG then :debug
46
+ when Logger::INFO then :info
47
+ when Logger::WARN then :warn
48
+ when Logger::ERROR then :error
49
+ else :fatal
50
+ end
51
+ end
52
+
53
+ # Returns a new Hash with all key values coerced to symbols. All keys
54
+ # within a Hash are coerced by calling #to_sym and hashes within arrays
55
+ # and other hashes are traversed.
56
+ #
57
+ # @param obj [Object] the hash to be processed. While intended for
58
+ # hashes, this method safely processes arbitrary objects
59
+ # @return [Object] a converted hash with all keys as symbols
60
+ def self.symbolized_hash(obj)
61
+ if obj.is_a?(Hash)
62
+ obj.reduce({}) do |h, (k, v)|
63
+ h[k.to_sym] = symbolized_hash(v)
64
+ h
65
+ end
66
+ elsif obj.is_a?(Array)
67
+ obj.reduce([]) do |a, e|
68
+ a << symbolized_hash(e)
69
+ a
70
+ end
71
+ else
72
+ obj
73
+ end
74
+ end
75
+
76
+ # Returns a new Hash with all key values coerced to strings. All keys
77
+ # within a Hash are coerced by calling #to_s and hashes with arrays
78
+ # and other hashes are traversed.
79
+ #
80
+ # @param obj [Object] the hash to be processed. While intended for
81
+ # hashes, this method safely processes arbitrary objects
82
+ # @return [Object] a converted hash with all keys as strings
83
+ def self.stringified_hash(obj)
84
+ if obj.is_a?(Hash)
85
+ obj.reduce({}) do |h, (k, v)|
86
+ h[k.to_s] = stringified_hash(v)
87
+ h
88
+ end
89
+ elsif obj.is_a?(Array)
90
+ obj.reduce([]) do |a, e|
91
+ a << stringified_hash(e)
92
+ a
93
+ end
94
+ else
95
+ obj
96
+ end
97
+ end
98
+
99
+ # Returns a formatted string representing a duration in seconds.
100
+ #
101
+ # @param total [Integer] the total number of seconds
102
+ # @return [String] a formatted string of the form (XmYY.00s)
103
+ def self.duration(total)
104
+ total = 0 if total.nil?
105
+ minutes = (total / 60).to_i
106
+ seconds = (total - (minutes * 60))
107
+ format('(%dm%.2fs)', minutes, seconds)
108
+ end
109
+
110
+ # Generates a command (or series of commands) wrapped so that it can be
111
+ # invoked on a remote instance or locally.
112
+ #
113
+ # This method uses the Bourne shell (/bin/sh) to maximize the chance of
114
+ # cross platform portability on Unixlike systems.
115
+ #
116
+ # @param [String] the command
117
+ # @return [String] a wrapped command string
118
+ def self.wrap_command(cmd)
119
+ cmd = 'false' if cmd.nil?
120
+ cmd = 'true' if cmd.to_s.empty?
121
+ cmd = cmd.sub(/\n\Z/, '') if cmd =~ /\n\Z/
122
+
123
+ "sh -c '\n#{cmd}\n'"
124
+ end
125
+
126
+ # Modifes the given string to strip leading whitespace on each line, the
127
+ # amount which is calculated by using the first line of text.
128
+ #
129
+ # @example
130
+ #
131
+ # string = <<-STRING
132
+ # a
133
+ # b
134
+ # c
135
+ # STRING
136
+ # Util.outdent!(string) # => "a\n b\nc\n"
137
+ #
138
+ # @param string [String] the string that will be modified
139
+ # @return [String] the modified string
140
+ def self.outdent!(string)
141
+ string.gsub!(/^ {#{string.index(/[^ ]/)}}/, '')
142
+ end
143
+
144
+ # Returns a set of Bourne Shell (AKA /bin/sh) compatible helper
145
+ # functions. This function is usually called inline in a string that
146
+ # will be executed remotely on a test instance.
147
+ #
148
+ # @return [String] a string representation of useful helper functions
149
+ def self.shell_helpers
150
+ IO.read(File.join(
151
+ File.dirname(__FILE__), %w[.. .. support download_helpers.sh]
152
+ ))
153
+ end
154
+ end
155
+ end
@@ -1,7 +1,7 @@
1
1
  require 'hashie/dash'
2
2
 
3
3
  module Polytrix
4
- class Validation < Hashie::Dash
4
+ class Validation < Polytrix::ManifestSection
5
5
  ALLOWABLE_STATES = %w(passed pending failed skipped)
6
6
  property :validated_by, required: true
7
7
  property :result
@@ -1,7 +1,11 @@
1
+ require 'rspec/expectations'
2
+
1
3
  module Polytrix
2
4
  class Validator
5
+ include RSpec::Matchers
6
+
3
7
  UNIVERSAL_MATCHER = //
4
- attr_reader :suite, :sample, :callback
8
+ attr_reader :suite, :sample, :level, :callback
5
9
 
6
10
  def initialize(scope = {}, &validator)
7
11
  @suite = scope[:suite] ||= UNIVERSAL_MATCHER
@@ -10,11 +14,11 @@ module Polytrix
10
14
  end
11
15
 
12
16
  def should_validate?(challenge)
13
- !!(@suite.match(challenge.suite) && @sample.match(challenge.name))
17
+ !!(@suite.match(challenge.suite.to_s) && @sample.match(challenge.name.to_s))
14
18
  end
15
19
 
16
- # def validate(challenge)
17
- # instance_exec challenge, @callback if should_validate?(challenge)
18
- # end
20
+ def validate(challenge)
21
+ instance_exec challenge, &@callback if should_validate?(challenge)
22
+ end
19
23
  end
20
24
  end
@@ -1,3 +1,3 @@
1
1
  module Polytrix
2
- VERSION = '0.1.0.pre'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/polytrix.rb CHANGED
@@ -1,14 +1,21 @@
1
1
  require 'pathname'
2
- require 'hashie/dash'
3
- require 'hashie/mash'
4
- require 'hashie/extensions/coercion'
2
+ require 'polytrix/error'
3
+ require 'polytrix/core/hashie'
4
+ require 'polytrix/core/string_helpers'
5
5
  require 'polytrix/version'
6
+ require 'polytrix/util'
7
+ require 'polytrix/color'
6
8
  require 'polytrix/logger'
9
+ require 'polytrix/logging'
10
+ require 'polytrix/state_file'
7
11
  require 'polytrix/core/file_system_helper'
8
- require 'polytrix/executor'
12
+ require 'polytrix/runners/executor'
13
+ require 'polytrix/core/manifest_section'
9
14
  require 'polytrix/core/implementor'
10
15
  require 'polytrix/challenge_runner'
16
+ require 'polytrix/challenge_result'
11
17
  require 'polytrix/challenge'
18
+ require 'polytrix/challenges'
12
19
  require 'polytrix/manifest'
13
20
  require 'polytrix/configuration'
14
21
  require 'polytrix/validation'
@@ -21,11 +28,15 @@ require 'polytrix/validator_registry'
21
28
  require 'polytrix/rspec'
22
29
 
23
30
  module Polytrix
24
- include Polytrix::Logger
31
+ include Polytrix::DefaultLogger
32
+ include Polytrix::Logging
25
33
 
26
34
  class << self
27
35
  include Polytrix::Core::FileSystemHelper
28
36
 
37
+ # @return [Mutex] a common mutex for global coordination
38
+ attr_accessor :mutex
39
+
29
40
  def reset
30
41
  @configuration = nil
31
42
  Polytrix::ValidatorRegistry.clear
@@ -33,12 +44,12 @@ module Polytrix
33
44
 
34
45
  # The {Polytrix::Manifest} that describes the test scenarios known to Polytrix.
35
46
  def manifest
36
- configuration.test_manifest
47
+ configuration.manifest
37
48
  end
38
49
 
39
50
  # The set of {Polytrix::Implementor}s registered with Polytrix.
40
51
  def implementors
41
- configuration.implementors
52
+ manifest.implementors.values
42
53
  end
43
54
 
44
55
  def find_implementor(file)
@@ -49,12 +60,17 @@ module Polytrix
49
60
  end
50
61
  return existing_implementor if existing_implementor
51
62
 
52
- implementor_basedir = recursive_parent_search(File.dirname(file), 'polytrix.yml')
53
- return Polytrix.configuration.implementor implementor_basedir if implementor_basedir
54
-
55
63
  nil
56
64
  end
57
65
 
66
+ # Invokes the clone action for each SDK.
67
+ # @see Polytrix::Implementor#clone
68
+ def clone(*sdks)
69
+ select_implementors(sdks).each do |implementor|
70
+ implementor.clone
71
+ end
72
+ end
73
+
58
74
  # Invokes the bootstrap action for each SDK.
59
75
  # @see Polytrix::Implementor#bootstrap
60
76
  def bootstrap(*sdks)
@@ -63,18 +79,24 @@ module Polytrix
63
79
  end
64
80
  end
65
81
 
66
- def exec(file, exec_options)
67
- implementor = find_implementor(file) || exec_options[:default_implementor]
68
-
69
- extension = File.extname(file)
70
- name = File.basename(file, extension)
71
- challenge_data = {
72
- name: name,
73
- # language: extension,
74
- source_file: File.expand_path(file, Dir.pwd)
75
- }
76
- challenge = implementor.build_challenge challenge_data
77
- challenge.run
82
+ def exec(*files)
83
+ # files.map do | file |
84
+ # Dir.glob file
85
+ # end.flatten
86
+
87
+ files.each do | file |
88
+ implementor = find_implementor(file) # || exec_options[:default_implementor]
89
+
90
+ extension = File.extname(file)
91
+ name = File.basename(file, extension)
92
+ challenge_data = {
93
+ name: name,
94
+ # language: extension,
95
+ source_file: File.expand_path(file, Dir.pwd)
96
+ }
97
+ challenge = implementor.build_challenge challenge_data
98
+ challenge.exec
99
+ end
78
100
  end
79
101
 
80
102
  # Registers a {Polytrix::Validator} that will be used during test
@@ -91,11 +113,12 @@ module Polytrix
91
113
  end
92
114
 
93
115
  def load_tests
116
+ manifest.build_challenges
94
117
  Polytrix::RSpec.run_manifest(manifest)
95
118
  end
96
119
 
97
120
  # Runs all of the tests described in the {manifest}
98
- def run_tests(implementors = [])
121
+ def verify(implementors = [])
99
122
  test_env = ENV['TEST_ENV_NUMBER'].to_i
100
123
  rspec_options = %W[--color -f documentation -f Polytrix::RSpec::YAMLReport -o reports/test_report#{test_env}.yaml]
101
124
  rspec_options.concat Polytrix.configuration.rspec_options.split if Polytrix.configuration.rspec_options
@@ -128,15 +151,12 @@ module Polytrix
128
151
  yield(configuration)
129
152
  end
130
153
 
131
- # Merges multiple test results files produced the rspec {Polytrix::RSpec::YAMLReport} formatter.
132
- # @param result_files [Array] the location of the files to merge.
133
- # @return [String] the merged content
134
- def merge_results(result_files)
135
- merged_results = Polytrix::Manifest.new
136
- result_files.each do |result_file|
137
- merged_results.deep_merge! YAML.load(File.read(result_file))
138
- end
139
- YAML.dump(merged_results.to_hash)
154
+ # Returns whether or not standard output is associated with a terminal
155
+ # device (tty).
156
+ #
157
+ # @return [true,false] is there a tty?
158
+ def tty?
159
+ $stdout.tty?
140
160
  end
141
161
 
142
162
  protected
@@ -149,7 +169,7 @@ module Polytrix
149
169
  sdk_dir = File.absolute_path(sdk)
150
170
  implementors.find { |i| File.absolute_path(i.basedir) == sdk_dir } || configuration.implementor(sdk_dir)
151
171
  else
152
- implementor = implementors.find { |i| i.name == sdk }
172
+ implementor = implementors.find { |i| i.name.to_s.downcase == sdk.to_s.downcase }
153
173
  fail ArgumentError, "SDK #{sdk} not found" if implementor.nil?
154
174
  implementor
155
175
  end
@@ -157,3 +177,5 @@ module Polytrix
157
177
  end
158
178
  end
159
179
  end
180
+
181
+ Polytrix.mutex = Mutex.new
data/polytrix.gemspec CHANGED
@@ -19,10 +19,12 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_dependency "thor", "~> 0.19"
22
- spec.add_dependency "mixlib-shellout", "~> 1.3"
22
+ spec.add_dependency "logging", "~> 1.8"
23
+ spec.add_dependency "mixlib-shellout", "~> 1.3" # Used for MRI
24
+ spec.add_dependency "buff-shell_out", "~> 0.1" # Used for JRuby
23
25
  spec.add_dependency "middleware", "~> 0.1"
24
26
  spec.add_dependency "rspec", "~> 2.99"
25
- spec.add_dependency "hashie", "~> 2.1"
27
+ spec.add_dependency "hashie", "~> 3.0"
26
28
  spec.add_dependency "padrino-helpers", "~> 0.12"
27
29
  spec.add_development_dependency "bundler", "~> 1.5"
28
30
  spec.add_development_dependency "rake"
data/polytrix.rb CHANGED
@@ -1,6 +1 @@
1
1
  Polytrix.configuration.default_doc_template = 'doc-src/_markdown.md'
2
-
3
- Polytrix.configure do |polytrix|
4
- polytrix.test_manifest = 'polytrix_tests.yml'
5
- polytrix.implementor name: 'polytrix', language: 'ruby', basedir: 'samples/'
6
- end
@@ -1,4 +1,9 @@
1
1
  ---
2
+ implementors:
3
+ polytrix:
4
+ language: 'ruby'
5
+ basedir: 'samples/'
6
+
2
7
  global_env: # global_env defines input available for all scenarios
3
8
  LOCALE: <%= ENV['LANG'] %> # templating is allowed
4
9
  FAVORITE_NUMBER: 5
@@ -3,12 +3,5 @@
3
3
  # This example shows the default behavior of `Polytrix#bootstrap`
4
4
  require 'polytrix'
5
5
 
6
- Polytrix.configure do |polytrix|
7
- Dir['sdks/*'].each do |sdk|
8
- name = File.basename(sdk)
9
- polytrix.implementor name: name, basedir: sdk
10
- end
11
- end
12
-
13
6
  # Snippet: bootstrap
14
7
  Polytrix.bootstrap
data/samples/polytrix.rb CHANGED
@@ -1,14 +1,5 @@
1
1
  require 'polytrix'
2
2
 
3
- basedir = File.expand_path('..', __FILE__)
4
-
5
- Polytrix.configure do |polytrix|
6
- Dir["#{basedir}/sdks/*"].each do |sdk|
7
- name = File.basename(sdk)
8
- polytrix.implementor name: name, basedir: sdk
9
- end
10
- end
11
-
12
3
  RSpec.configure do |c|
13
4
  c.expose_current_running_example_as :example
14
5
  end
@@ -1,4 +1,15 @@
1
1
  ---
2
+ implementors:
3
+ ruby:
4
+ language: 'ruby'
5
+ basedir: 'sdks/ruby'
6
+ java:
7
+ language: 'java'
8
+ basedir: 'sdks/java'
9
+ python:
10
+ language: 'python'
11
+ basedir: 'sdks/python'
12
+
2
13
  global_env: # global_env defines input available for all scenarios
3
14
  LOCALE: <%= ENV['LANG'] %> # templating is allowed
4
15
  suites:
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env bash -e
2
2
  bundle exec polytrix bootstrap
3
3
  bundle exec polytrix exec sdks/ruby/challenges/*.rb --code2doc --target-dir=docs/ruby/
4
- bundle exec polytrix test
4
+ # bundle exec polytrix test
5
5
  bundle exec polytrix report summary
6
6
  bundle exec polytrix report summary --format=markdown
7
7
  bundle exec polytrix report summary --format=yaml
@@ -0,0 +1,20 @@
1
+ require 'hashie/mash'
2
+
3
+ # Fabricates test manifests (.polytrix.yml files)
4
+ LANGUAGES = %w(java ruby python nodejs c# golang php)
5
+ SAMPLE_NAMES = [
6
+ 'hello world',
7
+ 'quine',
8
+ 'my_kata'
9
+ ]
10
+
11
+ Fabricator(:implementor, from: Polytrix::Implementor) do
12
+ initialize_with { @_klass.new to_hash } # Hash based initialization
13
+ language { LANGUAGES.sample }
14
+ name do |attr|
15
+ "my_#{attr[:language]}_project"
16
+ end
17
+ basedir do |attr|
18
+ "sdks/#{attr[:name]}"
19
+ end
20
+ end
@@ -1,6 +1,6 @@
1
1
  require 'hashie/mash'
2
2
 
3
- # Fabricates test manifests (.polytrix_tests.yml files)
3
+ # Fabricates test manifests (.polytrix.yml files)
4
4
  LANGUAGES = %w(java ruby python nodejs c# golang php)
5
5
  SAMPLE_NAMES = [
6
6
  'hello world',
@@ -12,6 +12,9 @@ Fabricator(:manifest, from: Polytrix::Manifest) do
12
12
  initialize_with { @_klass.new to_hash } # Hash based initialization
13
13
  transient suite_count: 3
14
14
  transient samples_per_suite: 3
15
+ implementors do
16
+ Fabricate(:implementor)
17
+ end
15
18
  global_env do
16
19
  {
17
20
  VAR1: 1,
@@ -1,4 +1,14 @@
1
1
  ---
2
+ implementors:
3
+ ruby:
4
+ language: 'ruby'
5
+ basedir: 'sdks/ruby'
6
+ java:
7
+ language: 'java'
8
+ basedir: 'sdks/java'
9
+ python:
10
+ language: 'python'
11
+ basedir: 'sdks/python'
2
12
  global_env:
3
13
  LOCALE: <%= ENV['LANG'] %>
4
14
  FAVORITE_NUMBER: 5
@@ -1,13 +1,14 @@
1
1
  module Polytrix
2
2
  describe ChallengeRunner do
3
3
  subject(:runner) { ChallengeRunner.create_runner }
4
+ let(:implementor) { Fabricate(:implementor) }
4
5
  let(:challenge) do
5
- Fabricate(:challenge, name: 'factorial', source_file: 'spec/fixtures/factorial.py', basedir: 'spec/fixtures')
6
+ Fabricate(:challenge, name: 'factorial', source_file: 'spec/fixtures/factorial.py', basedir: 'spec/fixtures', implementor: implementor)
6
7
  end
7
8
 
8
9
  describe '#run_challenge' do
9
10
  it 'executes a challenge' do
10
- expect(runner.run_challenge challenge).to be_an_instance_of Challenge
11
+ expect(runner.run_challenge challenge).to be_an_instance_of Result
11
12
  end
12
13
  end
13
14
  end
@@ -5,14 +5,15 @@ module Polytrix
5
5
  implementor.build_challenge name: 'factorial', vars: {}
6
6
  end
7
7
 
8
- describe '#run' do
8
+ describe '#exec' do
9
9
  it 'executes the challenge and returns itself' do
10
- expect(challenge.run).to be_an_instance_of Challenge
11
- expect(challenge.run).to eq(challenge)
10
+ expect(challenge.exec).to be_an_instance_of Challenge
11
+ expect(challenge.exec).to eq(challenge)
12
12
  end
13
13
 
14
14
  it 'stores the result' do
15
- expect(challenge.run[:result]).to be_an_instance_of Result
15
+ result = challenge.exec[:result]
16
+ expect(result).to be_an_instance_of Result
16
17
  end
17
18
  end
18
19
  end
@@ -2,36 +2,33 @@ require 'spec_helper'
2
2
  require 'polytrix/cli'
3
3
 
4
4
  module Polytrix
5
- module CLI
6
- describe Main do
7
- let(:kernel) { double(:kernel) }
8
- subject { ThorSpy.on(described_class, kernel) }
9
- describe 'bootstrap' do
10
- context 'with no args' do
11
- it 'calls Polytrix.bootstrap' do
12
- expect(kernel).to receive(:exit).with(0)
13
- expect(Polytrix).to receive(:bootstrap)
14
- subject.bootstrap
15
- end
5
+ describe CLI do
6
+ let(:kernel) { double(:kernel) }
7
+ subject { ThorSpy.on(described_class, kernel) }
8
+ describe 'bootstrap' do
9
+ context 'with no args' do
10
+ it 'calls bootstrap on each implementor' do
11
+ expect(kernel).to receive(:exit).with(0)
12
+ # TODO: Any way to test each implementor is called? We can't use
13
+ # `Polytrix.implementors` because it will be reloaded.
14
+ subject.bootstrap
16
15
  end
16
+ end
17
17
 
18
- context 'with an existing SDK' do
19
- before do
20
- @implementor = Polytrix.configuration.implementor name: 'test', basedir: '.'
21
- end
22
-
23
- it 'calls bootstrap on the SDK' do
24
- expect(@implementor).to receive(:bootstrap)
25
- expect(kernel).to receive(:exit).with(0)
26
- expect(subject.stderr.string).to eq('')
27
- subject.bootstrap('test')
28
- end
18
+ context 'with an existing SDK' do
19
+ xit 'calls bootstrap on the SDK' do
20
+ # expect(@implementor).to receive(:bootstrap)
21
+ expect(kernel).to receive(:exit).with(0)
22
+ expect(subject.stderr.string).to eq('')
23
+ subject.bootstrap('test')
29
24
  end
25
+ end
30
26
 
31
- context 'with an non-existant SDK' do
32
- it 'fails' do
33
- expect { subject.bootstrap('missing') }.to raise_error(SystemExit, 'SDK missing not found')
34
- end
27
+ context 'with an non-existant SDK' do
28
+ it 'fails' do
29
+ expect(kernel).to receive(:exit).with(1)
30
+ subject.bootstrap('missing')
31
+ expect(subject.stdout.string).to include('No scenarios for regex')
35
32
  end
36
33
  end
37
34
  end