paraduct 0.0.1.beta3 → 0.0.1.beta4

Sign up to get free protection for your applications and to get access to all the features.
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup markdown
2
+ --no-private
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## master
2
+ [full changelog](http://github.com/sue445/paraduct/compare/v0.0.1...master)
3
+
4
+ ## v0.0.1
5
+ * first release
data/README.md CHANGED
@@ -5,10 +5,13 @@
5
5
  [![Coverage Status](https://img.shields.io/coveralls/sue445/paraduct.svg)](https://coveralls.io/r/sue445/paraduct)
6
6
  [![Dependency Status](https://gemnasium.com/sue445/paraduct.svg)](https://gemnasium.com/sue445/paraduct)
7
7
 
8
- TODO: Write a gem description
8
+ Paraduct (**parallel** + **parameterize** + **product**) is matrix test runner
9
9
 
10
10
  [![Stories in Ready](https://badge.waffle.io/sue445/paraduct.svg?label=ready&title=Ready)](http://waffle.io/sue445/paraduct)
11
11
 
12
+ ## Requirements
13
+ ruby 1.9+
14
+
12
15
  ## Installation
13
16
 
14
17
  Add this line to your application's Gemfile:
@@ -26,8 +29,64 @@ Or install it yourself as:
26
29
  $ gem install paraduct
27
30
 
28
31
  ## Usage
32
+ ```bash
33
+ $ paraduct --help
34
+ Commands:
35
+ paraduct generate # generate .paraduct.yml
36
+ paraduct help [COMMAND] # Describe available commands or one specific command
37
+ paraduct test # run matrix test
38
+ ```
39
+
40
+ ### 1. Generate config file
41
+ ```bash
42
+ $ paraduct generate
43
+ create .paraduct.yml
44
+ ```
45
+
46
+ ### 2. Customize .paraduct.yml
47
+ ```bash
48
+ $ vi .paraduct.yml
49
+ ```
50
+
51
+ ### 3. Run test
52
+ ```bash
53
+ $ paraduct test
54
+ ```
55
+
56
+ ## Format
57
+ ```yaml
58
+ script: |-
59
+ echo "NAME1=${NAME1}, NAME2=${NAME2}"
60
+ work_dir: tmp/paraduct_workspace
61
+ variables:
62
+ name1:
63
+ - value1a
64
+ - value1b
65
+ name2:
66
+ - value2a
67
+ - value2b
68
+ ```
69
+
70
+ ### script
71
+ script to run
72
+
73
+ ### work_dir
74
+ diretory to run
75
+
76
+ * own job is run under `work_dir/JOB_NAME`
77
+
78
+ ### variables
79
+ Parameters to be combined
80
+
81
+ * key is capitalized (example. `name1` -> `NAME1`)
82
+ * JOB_NAME is generated with variables
29
83
 
30
- TODO: Write usage instructions here
84
+ name1 | name2 | JOB_NAME | current directory where the test is performed
85
+ ------- | ------- | ----------------------------- | ---------------------------------------
86
+ value1a | value2a | NAME1_value1a_NAME2_value2a | tmp/paraduct_workspace/NAME1_value1a_NAME2_value2a
87
+ value1a | value2b | NAME1_value1a_NAME2_value2b | tmp/paraduct_workspace/NAME1_value1a_NAME2_value2b
88
+ value1b | value2a | NAME1_value1b_NAME2_value2a | tmp/paraduct_workspace/NAME1_value1b_NAME2_value2a
89
+ value1b | value2b | NAME1_value1b_NAME2_value2b | tmp/paraduct_workspace/NAME1_value1b_NAME2_value2b
31
90
 
32
91
  ## Contributing
33
92
 
data/Rakefile CHANGED
@@ -1,7 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rspec/core/rake_task"
3
+ require 'yard'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
6
 
6
7
  task :default => :spec
7
8
 
9
+ YARD::Rake::YardocTask.new
data/lib/paraduct.rb CHANGED
@@ -6,6 +6,8 @@ require "paraduct/configuration"
6
6
  require "paraduct/variable_converter"
7
7
  require "paraduct/runner"
8
8
  require "paraduct/parallel_runner"
9
+ require "paraduct/errors"
10
+ require "paraduct/test_response"
9
11
  require "pathname"
10
12
 
11
13
  module Paraduct
data/lib/paraduct/cli.rb CHANGED
@@ -14,7 +14,9 @@ module Paraduct
14
14
  raise "require variables" if variables.blank?
15
15
 
16
16
  product_variables = Paraduct::VariableConverter.product(variables)
17
- Paraduct::ParallelRunner.perform_all(script, product_variables)
17
+ test_response = Paraduct::ParallelRunner.perform_all(script, product_variables)
18
+ puts test_response.detail_message
19
+ raise Paraduct::TestFailureError if test_response.failure?
18
20
  end
19
21
 
20
22
  desc "generate", "generate .paraduct.yml"
@@ -10,23 +10,28 @@ module Paraduct
10
10
  @config = YAML.load_file(config_file)
11
11
  end
12
12
 
13
+ # @return [Pathname]
13
14
  def variables
14
15
  @config["variables"]
15
16
  end
16
17
 
18
+ # @return [String, Array<String>]
17
19
  def script
18
20
  @config["script"]
19
21
  end
20
22
 
23
+ # @return [Pathname]
21
24
  def work_dir
22
25
  _work_dir = @config["work_dir"] || "tmp/paraduct_workspace"
23
26
  root_dir.join(_work_dir)
24
27
  end
25
28
 
29
+ # @return [Pathname]
26
30
  def config_file
27
31
  root_dir.join(".paraduct.yml")
28
32
  end
29
33
 
34
+ # @return [Pathname]
30
35
  def root_dir
31
36
  Pathname.pwd
32
37
  end
@@ -0,0 +1,14 @@
1
+ module Paraduct
2
+ class TestFailureError < StandardError; end
3
+
4
+ class ProcessError < StandardError
5
+ attr_reader :status
6
+
7
+ # @param message [String] stdout and stderr
8
+ # @param status [Process::Status]
9
+ def initialize(message, status)
10
+ super(message)
11
+ @status = status
12
+ end
13
+ end
14
+ end
@@ -1,11 +1,12 @@
1
1
  module Paraduct
2
2
  class ParallelRunner
3
+ # run script with arguments
3
4
  # @param script [String, Array<String>] script file, script(s)
4
5
  # @param product_variables [Array<Hash{String => String}>]
5
- # @return [Array<String>] stdout messages of each job
6
+ # @return [Paraduct::TestResponse]
6
7
  def self.perform_all(script, product_variables)
7
8
  threads = []
8
- stdout_messages = []
9
+ test_response = Paraduct::TestResponse.new
9
10
  base_job_dir = Paraduct.config.work_dir
10
11
  FileUtils.mkdir_p(base_job_dir) unless base_job_dir.exist?
11
12
 
@@ -18,52 +19,42 @@ START matrix test
18
19
  end
19
20
 
20
21
  product_variables.each do |params|
21
- threads << Thread.new(base_job_dir, script, params) do |_base_job_dir, _script, _params|
22
- job_dir = setup_runner(_base_job_dir, _params)
23
- stdout =
24
- begin
25
- Paraduct::Runner.perform(_script, _params)
26
- rescue Paraduct::ProcessError => e
27
- e.message
28
- end
22
+ runner = Paraduct::Runner.new(
23
+ script: script,
24
+ params: params,
25
+ base_job_dir: base_job_dir,
26
+ )
27
+ threads << Thread.new(runner) do |_runner|
28
+ _runner.setup_dir
29
+ begin
30
+ stdout = _runner.perform
31
+ successful = true
32
+ rescue Paraduct::ProcessError => e
33
+ stdout = e.message
34
+ successful = false
35
+ end
29
36
 
30
37
  puts <<-EOS
31
38
  ======================================================
32
- params: #{_params}
33
- job_dir: #{job_dir}
39
+ params: #{_runner.formatted_params}
40
+ job_name: #{_runner.job_name}
41
+ job_dir: #{_runner.job_dir}
34
42
 
35
43
  #{stdout}
36
44
  EOS
37
45
 
38
- stdout_messages << stdout
46
+ test_response.jobs_push(
47
+ job_name: _runner.job_name,
48
+ params: _runner.params,
49
+ formatted_params: _runner.formatted_params,
50
+ successful: successful,
51
+ stdout: stdout,
52
+ )
39
53
  end
40
54
  end
41
55
  threads.map(&:join)
42
56
 
43
- stdout_messages
57
+ test_response
44
58
  end
45
-
46
- # @param source_dir [Pathname]
47
- # @param destination_dir [Pathname]
48
- def self.copy_recursive(source_dir, destination_dir)
49
- FileUtils.mkdir_p(destination_dir)
50
- source_dir.children.each do |source_child_dir|
51
- begin
52
- FileUtils.cp_r(source_child_dir, destination_dir)
53
- rescue ArgumentError => e
54
- # TODO: refactoring
55
- raise unless e.message =~ /^cannot copy directory .+ to itself /
56
- end
57
- end
58
- end
59
-
60
- def self.setup_runner(base_job_dir, params)
61
- job_dir = Paraduct::Runner.parameterized_job_dir(base_job_dir, params)
62
- FileUtils.mkdir_p(job_dir) unless job_dir.exist?
63
- copy_recursive(Paraduct.config.root_dir, job_dir)
64
- Dir.chdir(job_dir)
65
- job_dir
66
- end
67
- private_class_method :setup_runner
68
59
  end
69
60
  end
@@ -1,43 +1,66 @@
1
1
  module Paraduct
2
2
  require "open3"
3
3
 
4
- class ProcessError < StandardError
5
- attr_reader :status
4
+ class Runner
5
+ attr_reader :script, :params, :base_job_dir
6
6
 
7
- # @param message [String] stdout and stderr
8
- # @param status [Process::Status]
9
- def initialize(message, status)
10
- super(message)
11
- @status = status
7
+ # @param args
8
+ # @option args :script [String, Array<String>] script file, script(s)
9
+ # @option args :params [Hash{String => String}] key is capitalized and value is quoted (ex. foo=1 => FOO="1" )
10
+ # @option args :base_job_dir [String]
11
+ def initialize(args={})
12
+ @script = args[:script]
13
+ @params = args[:params]
14
+ @base_job_dir = args[:base_job_dir]
15
+ end
16
+
17
+ def setup_dir
18
+ FileUtils.mkdir_p(job_dir) unless job_dir.exist?
19
+ self.class.copy_recursive(Paraduct.config.root_dir, job_dir)
20
+ Dir.chdir(job_dir)
12
21
  end
13
- end
14
22
 
15
- class Runner
16
23
  # run script with params
17
- # @param script [String, Array<String>] script file, script(s)
18
- # @param params [Hash{String => String}] key is capitalized and value is quoted (ex. foo=1 => FOO="1" )
19
24
  # @return [String] stdout
20
25
  # @raise [Paraduct::ProcessError] command exited error status
21
- def self.perform(script, params)
22
- variable_string = capitalize_keys(params).map{ |key, value| %(export #{key}="#{value}";) }.join(" ")
26
+ def perform
27
+ variable_string = key_capitalized_params.map{ |key, value| %(export #{key}="#{value}";) }.join(" ")
23
28
 
24
- Array.wrap(script).inject("") do |stdout, command|
29
+ Array.wrap(@script).inject("") do |stdout, command|
25
30
  stdout << run_command("#{variable_string} #{command}")
26
31
  stdout
27
32
  end
28
33
  end
29
34
 
30
- def self.parameterized_job_dir(base_job_dir, params)
31
- dir_name = capitalize_keys(params).map{ |key, value| "#{key}_#{value}" }.join("_")
32
- Pathname(base_job_dir).join(dir_name)
35
+ def job_dir
36
+ Pathname(@base_job_dir).join(job_name)
33
37
  end
34
38
 
35
- def self.run_command(command)
36
- stdout, stderr, status = Open3.capture3(command)
37
- raise ProcessError.new("#{stdout}\n#{stderr}", status) unless status.success?
38
- stdout
39
+ def job_name
40
+ key_capitalized_params.map { |key, value| "#{key}_#{value}" }.join("_")
41
+ end
42
+
43
+ def key_capitalized_params
44
+ self.class.capitalize_keys(@params)
45
+ end
46
+
47
+ def formatted_params
48
+ @params.map{ |key, value| "#{key}=#{value}" }.join(", ")
49
+ end
50
+
51
+ # @param source_dir [Pathname]
52
+ # @param destination_dir [Pathname]
53
+ def self.copy_recursive(source_dir, destination_dir)
54
+ FileUtils.mkdir_p(destination_dir)
55
+ source_dir.children.each do |source_child_dir|
56
+ begin
57
+ FileUtils.cp_r(source_child_dir, destination_dir)
58
+ rescue ArgumentError => e
59
+ # TODO: refactoring
60
+ raise unless e.message =~ /^cannot copy directory .+ to itself /
61
+ end
62
+ end
39
63
  end
40
- private_class_method :run_command
41
64
 
42
65
  def self.capitalize_keys(params)
43
66
  params.inject({}) do |res, (key, value)|
@@ -45,6 +68,12 @@ module Paraduct
45
68
  res
46
69
  end
47
70
  end
48
- private_class_method :capitalize_keys
71
+
72
+ private
73
+ def run_command(command)
74
+ stdout, stderr, status = Open3.capture3(command)
75
+ raise Paraduct::ProcessError.new("#{stdout}\n#{stderr}", status) unless status.success?
76
+ stdout
77
+ end
49
78
  end
50
79
  end
@@ -0,0 +1,38 @@
1
+ module Paraduct
2
+ class TestResponse
3
+ attr_reader :jobs
4
+
5
+ def initialize
6
+ @jobs = []
7
+ end
8
+
9
+ delegate :push, to: :jobs, prefix: true
10
+
11
+ def successful?
12
+ @jobs.all?{ |result| result[:successful] }
13
+ end
14
+
15
+ def failure?
16
+ !successful?
17
+ end
18
+
19
+ def detail_message
20
+ all_count = @jobs.count
21
+ successful_count = @jobs.select{ |result| result[:successful] }.count
22
+ failure_count = all_count - successful_count
23
+
24
+ message = "======================================================\n"
25
+
26
+ if failure_count > 0
27
+ message << "Failures:\n\n"
28
+ @jobs.select{ |result| !result[:successful] }.each_with_index do |result, i|
29
+ message << " #{i + 1}) #{result[:formatted_params]}\n"
30
+ end
31
+ message << "\n"
32
+ end
33
+ message << "#{all_count} jobs, #{failure_count} failures, #{successful_count} passed\n"
34
+
35
+ message
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module Paraduct
2
- VERSION = "0.0.1.beta3"
2
+ VERSION = "0.0.1.beta4"
3
3
  end
data/paraduct.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["sue445"]
10
10
  spec.email = ["sue445@sue445.net"]
11
11
  spec.summary = %q{matrix test runner}
12
- spec.description = %q{matrix test runner}
12
+ spec.description = %q{Paraduct(parallel + parameterize + product) is matrix test runner}
13
13
  spec.homepage = "https://github.com/sue445/paraduct"
14
14
  spec.license = "MIT"
15
15
 
@@ -28,7 +28,10 @@ Gem::Specification.new do |spec|
28
28
  spec.add_development_dependency "pry-nav"
29
29
  spec.add_development_dependency "pry-remote"
30
30
  spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "redcarpet"
31
32
  spec.add_development_dependency "rspec", "~> 3.1.0"
32
33
  spec.add_development_dependency "rspec-collection_matchers"
34
+ spec.add_development_dependency "rspec-its"
33
35
  spec.add_development_dependency "rspec-temp_dir"
36
+ spec.add_development_dependency "yard"
34
37
  end
data/spec/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ inherit_from:
2
+ - ../.hound.yml
3
+
4
+ Style/Blocks:
5
+ Enabled: false
@@ -8,33 +8,50 @@ describe Paraduct::CLI do
8
8
 
9
9
  include_context :within_temp_work_dir
10
10
 
11
- let(:script){ "./script/build_success.sh" }
12
- let(:product_variables) do
13
- [
14
- { "ruby" => "1.9.3", "database" => "mysql" , "rails" => "3.2.0" },
15
- { "ruby" => "1.9.3", "database" => "mysql" , "rails" => "4.0.0" },
16
- { "ruby" => "1.9.3", "database" => "mysql" , "rails" => "4.1.0" },
17
- { "ruby" => "1.9.3", "database" => "postgresql", "rails" => "3.2.0" },
18
- { "ruby" => "1.9.3", "database" => "postgresql", "rails" => "4.0.0" },
19
- { "ruby" => "1.9.3", "database" => "postgresql", "rails" => "4.1.0" },
20
- { "ruby" => "2.0.0", "database" => "mysql" , "rails" => "3.2.0" },
21
- { "ruby" => "2.0.0", "database" => "mysql" , "rails" => "4.0.0" },
22
- { "ruby" => "2.0.0", "database" => "mysql" , "rails" => "4.1.0" },
23
- { "ruby" => "2.0.0", "database" => "postgresql", "rails" => "3.2.0" },
24
- { "ruby" => "2.0.0", "database" => "postgresql", "rails" => "4.0.0" },
25
- { "ruby" => "2.0.0", "database" => "postgresql", "rails" => "4.1.0" },
26
- { "ruby" => "2.1.2", "database" => "mysql" , "rails" => "3.2.0" },
27
- { "ruby" => "2.1.2", "database" => "mysql" , "rails" => "4.0.0" },
28
- { "ruby" => "2.1.2", "database" => "mysql" , "rails" => "4.1.0" },
29
- { "ruby" => "2.1.2", "database" => "postgresql", "rails" => "3.2.0" },
30
- { "ruby" => "2.1.2", "database" => "postgresql", "rails" => "4.0.0" },
31
- { "ruby" => "2.1.2", "database" => "postgresql", "rails" => "4.1.0" },
32
- ]
11
+ context "successful test" do
12
+ let(:script){ "./script/build_success.sh" }
13
+ let(:product_variables) do
14
+ [
15
+ { "ruby" => "1.9.3", "database" => "mysql" , "rails" => "3.2.0" },
16
+ { "ruby" => "1.9.3", "database" => "mysql" , "rails" => "4.0.0" },
17
+ { "ruby" => "1.9.3", "database" => "mysql" , "rails" => "4.1.0" },
18
+ { "ruby" => "1.9.3", "database" => "postgresql", "rails" => "3.2.0" },
19
+ { "ruby" => "1.9.3", "database" => "postgresql", "rails" => "4.0.0" },
20
+ { "ruby" => "1.9.3", "database" => "postgresql", "rails" => "4.1.0" },
21
+ { "ruby" => "2.0.0", "database" => "mysql" , "rails" => "3.2.0" },
22
+ { "ruby" => "2.0.0", "database" => "mysql" , "rails" => "4.0.0" },
23
+ { "ruby" => "2.0.0", "database" => "mysql" , "rails" => "4.1.0" },
24
+ { "ruby" => "2.0.0", "database" => "postgresql", "rails" => "3.2.0" },
25
+ { "ruby" => "2.0.0", "database" => "postgresql", "rails" => "4.0.0" },
26
+ { "ruby" => "2.0.0", "database" => "postgresql", "rails" => "4.1.0" },
27
+ { "ruby" => "2.1.2", "database" => "mysql" , "rails" => "3.2.0" },
28
+ { "ruby" => "2.1.2", "database" => "mysql" , "rails" => "4.0.0" },
29
+ { "ruby" => "2.1.2", "database" => "mysql" , "rails" => "4.1.0" },
30
+ { "ruby" => "2.1.2", "database" => "postgresql", "rails" => "3.2.0" },
31
+ { "ruby" => "2.1.2", "database" => "postgresql", "rails" => "4.0.0" },
32
+ { "ruby" => "2.1.2", "database" => "postgresql", "rails" => "4.1.0" },
33
+ ]
34
+ end
35
+
36
+ let(:test_response) do
37
+ test_response = Paraduct::TestResponse.new
38
+ test_response.jobs_push(successful: true)
39
+ test_response
40
+ end
41
+
42
+ it "should call perform_all" do
43
+ expect(Paraduct::ParallelRunner).to receive(:perform_all).with(script, product_variables){ test_response }
44
+ subject
45
+ end
33
46
  end
34
47
 
35
- it "should call perform_all" do
36
- expect(Paraduct::ParallelRunner).to receive(:perform_all).with(script, product_variables)
37
- subject
48
+ context "failure test" do
49
+ before do
50
+ allow(Paraduct.config).to receive(:script) { %q(exit ${STATUS}) }
51
+ allow(Paraduct.config).to receive(:variables){ { status: [0, 1] } }
52
+ end
53
+
54
+ it { expect{ subject }.to raise_error Paraduct::TestFailureError }
38
55
  end
39
56
  end
40
57
 
@@ -25,8 +25,25 @@ describe Paraduct::ParallelRunner do
25
25
  ]
26
26
  end
27
27
 
28
- it { should include "RUBY=1.9\nDATABASE=mysql\n" }
29
- it { should include "RUBY=2.0\nDATABASE=postgresql\n" }
28
+ its(:jobs) do
29
+ should include(
30
+ job_name: "RUBY_1.9_DATABASE_mysql",
31
+ params: { "ruby" => "1.9", "database" => "mysql" },
32
+ formatted_params: "ruby=1.9, database=mysql",
33
+ successful: true,
34
+ stdout: "RUBY=1.9\nDATABASE=mysql\n"
35
+ )
36
+ end
37
+
38
+ its(:jobs) do
39
+ should include(
40
+ job_name: "RUBY_2.0_DATABASE_postgresql",
41
+ params: { "ruby" => "2.0", "database" => "postgresql" },
42
+ formatted_params: "ruby=2.0, database=postgresql",
43
+ successful: true,
44
+ stdout: "RUBY=2.0\nDATABASE=postgresql\n"
45
+ )
46
+ end
30
47
 
31
48
  describe "should create job directories" do
32
49
  before do
@@ -53,8 +70,25 @@ describe Paraduct::ParallelRunner do
53
70
  ]
54
71
  end
55
72
 
56
- it { should include "RUBY=1.9 DATABASE=mysql\n" }
57
- it { should include "RUBY=2.0 DATABASE=postgresql\n" }
73
+ its(:jobs) do
74
+ should include(
75
+ job_name: "RUBY_1.9_DATABASE_mysql",
76
+ params: { "ruby" => "1.9", "database" => "mysql" },
77
+ formatted_params: "ruby=1.9, database=mysql",
78
+ successful: true,
79
+ stdout: "RUBY=1.9 DATABASE=mysql\n"
80
+ )
81
+ end
82
+
83
+ its(:jobs) do
84
+ should include(
85
+ job_name: "RUBY_2.0_DATABASE_postgresql",
86
+ params: { "ruby" => "2.0", "database" => "postgresql" },
87
+ formatted_params: "ruby=2.0, database=postgresql",
88
+ successful: true,
89
+ stdout: "RUBY=2.0 DATABASE=postgresql\n"
90
+ )
91
+ end
58
92
 
59
93
  describe "should create job directories" do
60
94
  before do
@@ -72,32 +106,4 @@ describe Paraduct::ParallelRunner do
72
106
  end
73
107
  end
74
108
  end
75
-
76
- describe "#copy_recursive" do
77
- subject{ Paraduct::ParallelRunner.copy_recursive(source_dir, destination_dir) }
78
-
79
- include_context "uses temp dir"
80
-
81
- let(:source_dir) { temp_dir_path }
82
- let(:destination_dir){ temp_dir_path.join("tmp/paraduct_workspace/RUBY_1.9_DATABASE_mysql") }
83
- let(:copied_file) { destination_dir.join("build_success.sh") }
84
- let(:not_copied_file){ destination_dir.join("tmp/paraduct_workspace/dummy.txt") }
85
-
86
- before do
87
- # setup
88
- FileUtils.cp_r(spec_dir.join("script/tmp/paraduct_workspace"), source_dir)
89
- FileUtils.cp_r(spec_dir.join("script/build_success.sh"), source_dir)
90
-
91
- # exercise
92
- subject
93
- end
94
-
95
- # after do
96
- # puts `tree #{source_dir}`
97
- # end
98
-
99
- it { expect(destination_dir).to be_exist }
100
- it { expect(copied_file).to be_exist }
101
- it { expect(not_copied_file).not_to be_exist }
102
- end
103
109
  end
@@ -1,6 +1,18 @@
1
1
  describe Paraduct::Runner do
2
+ let(:runner) do
3
+ Paraduct::Runner.new(
4
+ script: script,
5
+ params: params,
6
+ base_job_dir: base_job_dir,
7
+ )
8
+ end
9
+
10
+ let(:base_job_dir){ "/tmp/jobs" }
11
+ let(:script) { "" }
12
+ let(:params) { {} }
13
+
2
14
  describe "#perform" do
3
- subject{ Paraduct::Runner.perform(script, params) }
15
+ subject{ runner.perform }
4
16
 
5
17
  let(:script) { "./script/build_success.sh" }
6
18
  let(:params) { { "ruby" => "1.9", "database" => "mysql" } }
@@ -8,7 +20,7 @@ describe Paraduct::Runner do
8
20
 
9
21
  context "with mock system" do
10
22
  it "script is call with capitalized variable" do
11
- expect(Paraduct::Runner).to receive(:run_command).with(command).and_return("stdout")
23
+ expect(runner).to receive(:run_command).with(command).and_return("stdout")
12
24
  subject
13
25
  end
14
26
  end
@@ -49,12 +61,47 @@ DATABASE=mysql
49
61
  end
50
62
  end
51
63
 
52
- describe "#parameterized_job_dir" do
53
- subject{ Paraduct::Runner.parameterized_job_dir(base_job_dir, params) }
64
+ describe "#job_dir" do
65
+ subject{ runner.job_dir }
54
66
 
55
- let(:base_job_dir){ "/tmp/jobs" }
56
- let(:params) { { "ruby" => "1.9", "database" => "mysql" } }
67
+ let(:params) { { "ruby" => "1.9", "database" => "mysql" } }
57
68
 
58
69
  it { should eq Pathname("/tmp/jobs/RUBY_1.9_DATABASE_mysql") }
59
70
  end
71
+
72
+ describe "#copy_recursive" do
73
+ subject{ Paraduct::Runner.copy_recursive(source_dir, destination_dir) }
74
+
75
+ include_context "uses temp dir"
76
+
77
+ let(:source_dir) { temp_dir_path }
78
+ let(:destination_dir){ temp_dir_path.join("tmp/paraduct_workspace/RUBY_1.9_DATABASE_mysql") }
79
+ let(:copied_file) { destination_dir.join("build_success.sh") }
80
+ let(:not_copied_file){ destination_dir.join("tmp/paraduct_workspace/dummy.txt") }
81
+
82
+ before do
83
+ # setup
84
+ FileUtils.cp_r(spec_dir.join("script/tmp/paraduct_workspace"), source_dir)
85
+ FileUtils.cp_r(spec_dir.join("script/build_success.sh"), source_dir)
86
+
87
+ # exercise
88
+ subject
89
+ end
90
+
91
+ # after do
92
+ # puts `tree #{source_dir}`
93
+ # end
94
+
95
+ it { expect(destination_dir).to be_exist }
96
+ it { expect(copied_file).to be_exist }
97
+ it { expect(not_copied_file).not_to be_exist }
98
+ end
99
+
100
+ describe "#formatted_params" do
101
+ subject{ runner.formatted_params }
102
+
103
+ let(:params){ { "ruby" => "1.9", "database" => "mysql" } }
104
+
105
+ it{ should eq "ruby=1.9, database=mysql" }
106
+ end
60
107
  end
@@ -0,0 +1,64 @@
1
+ describe Paraduct::TestResponse do
2
+ let(:test_response){ Paraduct::TestResponse.new }
3
+
4
+ describe "#successful?" do
5
+ subject{ test_response.successful? }
6
+
7
+ context "not include failure" do
8
+ before do
9
+ test_response.jobs_push(successful: true)
10
+ test_response.jobs_push(successful: true)
11
+ end
12
+
13
+ it { should be true }
14
+ end
15
+
16
+ context "include failure" do
17
+ before do
18
+ test_response.jobs_push(successful: true)
19
+ test_response.jobs_push(successful: false)
20
+ end
21
+
22
+ it { should be false }
23
+ end
24
+ end
25
+
26
+ describe "#detail_message" do
27
+ subject{ test_response.detail_message }
28
+
29
+ context "when successful" do
30
+ before do
31
+ test_response.jobs_push(successful: true)
32
+ test_response.jobs_push(successful: true)
33
+ test_response.jobs_push(successful: true)
34
+ end
35
+
36
+ it do
37
+ should eq <<-EOS
38
+ ======================================================
39
+ 3 jobs, 0 failures, 3 passed
40
+ EOS
41
+ end
42
+ end
43
+
44
+ context "when failure" do
45
+ before do
46
+ test_response.jobs_push(successful: true)
47
+ test_response.jobs_push(successful: false, params: { "ruby" => "1.9", "database" => "mysql" } , formatted_params: "ruby=1.9, database=mysql")
48
+ test_response.jobs_push(successful: false, params: { "ruby" => "2.0", "database" => "postgresql" }, formatted_params: "ruby=2.0, database=postgresql")
49
+ end
50
+
51
+ it do
52
+ should eq <<-EOS
53
+ ======================================================
54
+ Failures:
55
+
56
+ 1) ruby=1.9, database=mysql
57
+ 2) ruby=2.0, database=postgresql
58
+
59
+ 3 jobs, 2 failures, 1 passed
60
+ EOS
61
+ end
62
+ end
63
+ end
64
+ end
data/spec/spec_helper.rb CHANGED
@@ -17,6 +17,7 @@ require 'paraduct'
17
17
  require 'paraduct/cli'
18
18
  require 'rspec/collection_matchers'
19
19
  require 'rspec/temp_dir'
20
+ require 'rspec/its'
20
21
  require 'pry'
21
22
 
22
23
  def spec_dir
@@ -115,4 +116,9 @@ RSpec.configure do |config|
115
116
  =end
116
117
 
117
118
  config.order = :random
119
+
120
+ config.before do
121
+ # quiet
122
+ allow(Object).to receive(:puts)
123
+ end
118
124
  end
metadata CHANGED
@@ -1,184 +1,257 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: paraduct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta3
4
+ version: 0.0.1.beta4
5
+ prerelease: 6
5
6
  platform: ruby
6
7
  authors:
7
8
  - sue445
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2014-10-18 00:00:00.000000000 Z
12
+ date: 2014-10-19 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: activesupport
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
- - - ">="
19
+ - - ! '>='
18
20
  - !ruby/object:Gem::Version
19
21
  version: '0'
20
22
  type: :runtime
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
- - - ">="
27
+ - - ! '>='
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0'
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: thor
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
- - - ">="
35
+ - - ! '>='
32
36
  - !ruby/object:Gem::Version
33
37
  version: '0'
34
38
  type: :runtime
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
- - - ">="
43
+ - - ! '>='
39
44
  - !ruby/object:Gem::Version
40
45
  version: '0'
41
46
  - !ruby/object:Gem::Dependency
42
47
  name: bundler
43
48
  requirement: !ruby/object:Gem::Requirement
49
+ none: false
44
50
  requirements:
45
- - - ">="
51
+ - - ! '>='
46
52
  - !ruby/object:Gem::Version
47
53
  version: '1.5'
48
54
  type: :development
49
55
  prerelease: false
50
56
  version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
51
58
  requirements:
52
- - - ">="
59
+ - - ! '>='
53
60
  - !ruby/object:Gem::Version
54
61
  version: '1.5'
55
62
  - !ruby/object:Gem::Dependency
56
63
  name: codeclimate-test-reporter
57
64
  requirement: !ruby/object:Gem::Requirement
65
+ none: false
58
66
  requirements:
59
- - - ">="
67
+ - - ! '>='
60
68
  - !ruby/object:Gem::Version
61
69
  version: '0'
62
70
  type: :development
63
71
  prerelease: false
64
72
  version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
65
74
  requirements:
66
- - - ">="
75
+ - - ! '>='
67
76
  - !ruby/object:Gem::Version
68
77
  version: '0'
69
78
  - !ruby/object:Gem::Dependency
70
79
  name: coveralls
71
80
  requirement: !ruby/object:Gem::Requirement
81
+ none: false
72
82
  requirements:
73
- - - ">="
83
+ - - ! '>='
74
84
  - !ruby/object:Gem::Version
75
85
  version: '0'
76
86
  type: :development
77
87
  prerelease: false
78
88
  version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
79
90
  requirements:
80
- - - ">="
91
+ - - ! '>='
81
92
  - !ruby/object:Gem::Version
82
93
  version: '0'
83
94
  - !ruby/object:Gem::Dependency
84
95
  name: pry
85
96
  requirement: !ruby/object:Gem::Requirement
97
+ none: false
86
98
  requirements:
87
- - - ">="
99
+ - - ! '>='
88
100
  - !ruby/object:Gem::Version
89
101
  version: '0'
90
102
  type: :development
91
103
  prerelease: false
92
104
  version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
93
106
  requirements:
94
- - - ">="
107
+ - - ! '>='
95
108
  - !ruby/object:Gem::Version
96
109
  version: '0'
97
110
  - !ruby/object:Gem::Dependency
98
111
  name: pry-nav
99
112
  requirement: !ruby/object:Gem::Requirement
113
+ none: false
100
114
  requirements:
101
- - - ">="
115
+ - - ! '>='
102
116
  - !ruby/object:Gem::Version
103
117
  version: '0'
104
118
  type: :development
105
119
  prerelease: false
106
120
  version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
107
122
  requirements:
108
- - - ">="
123
+ - - ! '>='
109
124
  - !ruby/object:Gem::Version
110
125
  version: '0'
111
126
  - !ruby/object:Gem::Dependency
112
127
  name: pry-remote
113
128
  requirement: !ruby/object:Gem::Requirement
129
+ none: false
114
130
  requirements:
115
- - - ">="
131
+ - - ! '>='
116
132
  - !ruby/object:Gem::Version
117
133
  version: '0'
118
134
  type: :development
119
135
  prerelease: false
120
136
  version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
121
138
  requirements:
122
- - - ">="
139
+ - - ! '>='
123
140
  - !ruby/object:Gem::Version
124
141
  version: '0'
125
142
  - !ruby/object:Gem::Dependency
126
143
  name: rake
127
144
  requirement: !ruby/object:Gem::Requirement
145
+ none: false
128
146
  requirements:
129
- - - "~>"
147
+ - - ~>
130
148
  - !ruby/object:Gem::Version
131
149
  version: '10.0'
132
150
  type: :development
133
151
  prerelease: false
134
152
  version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
135
154
  requirements:
136
- - - "~>"
155
+ - - ~>
137
156
  - !ruby/object:Gem::Version
138
157
  version: '10.0'
158
+ - !ruby/object:Gem::Dependency
159
+ name: redcarpet
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ! '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
139
174
  - !ruby/object:Gem::Dependency
140
175
  name: rspec
141
176
  requirement: !ruby/object:Gem::Requirement
177
+ none: false
142
178
  requirements:
143
- - - "~>"
179
+ - - ~>
144
180
  - !ruby/object:Gem::Version
145
181
  version: 3.1.0
146
182
  type: :development
147
183
  prerelease: false
148
184
  version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
149
186
  requirements:
150
- - - "~>"
187
+ - - ~>
151
188
  - !ruby/object:Gem::Version
152
189
  version: 3.1.0
153
190
  - !ruby/object:Gem::Dependency
154
191
  name: rspec-collection_matchers
155
192
  requirement: !ruby/object:Gem::Requirement
193
+ none: false
156
194
  requirements:
157
- - - ">="
195
+ - - ! '>='
158
196
  - !ruby/object:Gem::Version
159
197
  version: '0'
160
198
  type: :development
161
199
  prerelease: false
162
200
  version_requirements: !ruby/object:Gem::Requirement
201
+ none: false
163
202
  requirements:
164
- - - ">="
203
+ - - ! '>='
204
+ - !ruby/object:Gem::Version
205
+ version: '0'
206
+ - !ruby/object:Gem::Dependency
207
+ name: rspec-its
208
+ requirement: !ruby/object:Gem::Requirement
209
+ none: false
210
+ requirements:
211
+ - - ! '>='
212
+ - !ruby/object:Gem::Version
213
+ version: '0'
214
+ type: :development
215
+ prerelease: false
216
+ version_requirements: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
165
220
  - !ruby/object:Gem::Version
166
221
  version: '0'
167
222
  - !ruby/object:Gem::Dependency
168
223
  name: rspec-temp_dir
169
224
  requirement: !ruby/object:Gem::Requirement
225
+ none: false
226
+ requirements:
227
+ - - ! '>='
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ none: false
234
+ requirements:
235
+ - - ! '>='
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ - !ruby/object:Gem::Dependency
239
+ name: yard
240
+ requirement: !ruby/object:Gem::Requirement
241
+ none: false
170
242
  requirements:
171
- - - ">="
243
+ - - ! '>='
172
244
  - !ruby/object:Gem::Version
173
245
  version: '0'
174
246
  type: :development
175
247
  prerelease: false
176
248
  version_requirements: !ruby/object:Gem::Requirement
249
+ none: false
177
250
  requirements:
178
- - - ">="
251
+ - - ! '>='
179
252
  - !ruby/object:Gem::Version
180
253
  version: '0'
181
- description: matrix test runner
254
+ description: Paraduct(parallel + parameterize + product) is matrix test runner
182
255
  email:
183
256
  - sue445@sue445.net
184
257
  executables:
@@ -186,11 +259,13 @@ executables:
186
259
  extensions: []
187
260
  extra_rdoc_files: []
188
261
  files:
189
- - ".coveralls.yml"
190
- - ".gitignore"
191
- - ".hound.yml"
192
- - ".rspec"
193
- - ".travis.yml"
262
+ - .coveralls.yml
263
+ - .gitignore
264
+ - .hound.yml
265
+ - .rspec
266
+ - .travis.yml
267
+ - .yardopts
268
+ - CHANGELOG.md
194
269
  - Gemfile
195
270
  - LICENSE.txt
196
271
  - README.md
@@ -199,17 +274,21 @@ files:
199
274
  - lib/paraduct.rb
200
275
  - lib/paraduct/cli.rb
201
276
  - lib/paraduct/configuration.rb
277
+ - lib/paraduct/errors.rb
202
278
  - lib/paraduct/parallel_runner.rb
203
279
  - lib/paraduct/runner.rb
204
280
  - lib/paraduct/templates/.paraduct.yml.tt
281
+ - lib/paraduct/test_response.rb
205
282
  - lib/paraduct/variable_converter.rb
206
283
  - lib/paraduct/version.rb
207
284
  - paraduct.gemspec
208
285
  - spec/.paraduct.yml
286
+ - spec/.rubocop.yml
209
287
  - spec/paraduct/cli_spec.rb
210
288
  - spec/paraduct/configuration_spec.rb
211
289
  - spec/paraduct/parallel_runner_spec.rb
212
290
  - spec/paraduct/runner_spec.rb
291
+ - spec/paraduct/test_response_spec.rb
213
292
  - spec/paraduct/variable_converter_spec.rb
214
293
  - spec/paraduct_spec.rb
215
294
  - spec/script/build_error.sh
@@ -222,33 +301,39 @@ files:
222
301
  homepage: https://github.com/sue445/paraduct
223
302
  licenses:
224
303
  - MIT
225
- metadata: {}
226
304
  post_install_message:
227
305
  rdoc_options: []
228
306
  require_paths:
229
307
  - lib
230
308
  required_ruby_version: !ruby/object:Gem::Requirement
309
+ none: false
231
310
  requirements:
232
- - - ">="
311
+ - - ! '>='
233
312
  - !ruby/object:Gem::Version
234
313
  version: '0'
314
+ segments:
315
+ - 0
316
+ hash: 3632247312778024801
235
317
  required_rubygems_version: !ruby/object:Gem::Requirement
318
+ none: false
236
319
  requirements:
237
- - - ">"
320
+ - - ! '>'
238
321
  - !ruby/object:Gem::Version
239
322
  version: 1.3.1
240
323
  requirements: []
241
324
  rubyforge_project:
242
- rubygems_version: 2.2.2
325
+ rubygems_version: 1.8.23.2
243
326
  signing_key:
244
- specification_version: 4
327
+ specification_version: 3
245
328
  summary: matrix test runner
246
329
  test_files:
247
330
  - spec/.paraduct.yml
331
+ - spec/.rubocop.yml
248
332
  - spec/paraduct/cli_spec.rb
249
333
  - spec/paraduct/configuration_spec.rb
250
334
  - spec/paraduct/parallel_runner_spec.rb
251
335
  - spec/paraduct/runner_spec.rb
336
+ - spec/paraduct/test_response_spec.rb
252
337
  - spec/paraduct/variable_converter_spec.rb
253
338
  - spec/paraduct_spec.rb
254
339
  - spec/script/build_error.sh
@@ -257,3 +342,4 @@ test_files:
257
342
  - spec/spec_helper.rb
258
343
  - spec/support/contexts/within_spec_dir.rb
259
344
  - spec/support/contexts/within_temp_work_dir.rb
345
+ has_rdoc:
checksums.yaml DELETED
@@ -1,7 +0,0 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 2bfdf4b0f687c1c04c8bfc0f8c033f3caf15eea3
4
- data.tar.gz: 818e75eb679ccc987626cee5c2e230d0650040f8
5
- SHA512:
6
- metadata.gz: 2e5adbac7a7ae89fc4911a08cfcd98a8b25e5a3426dbfd60db7a933ebacb69240c32509ce9b0e8da1f75419bd2c418000b5ac57c89224ac56a139398ce95e3c7
7
- data.tar.gz: 20df8dfe7842b1ff4ef0ca5b5b130d0ae114aa063abb3ce84716f8c5c5d6a0c71c3d21ffb879bcd98b51d2549cdf5f86e08693f810e31919f80ca3e5e1d58e80