parallel_tests 0.10.4 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parallel_tests (0.10.4)
4
+ parallel_tests (0.11.0)
5
5
  parallel
6
6
 
7
7
  GEM
@@ -6,10 +6,9 @@ module ParallelTests
6
6
  NAME = 'Cucumber'
7
7
 
8
8
  def self.run_tests(test_files, process_number, num_processes, options)
9
- color = ($stdout.tty? ? 'AUTOTEST=1 ; export AUTOTEST ;' : '')#display color when we are in a terminal
9
+ options = options.merge(:env => {"AUTOTEST" => "1"}) if $stdout.tty? # display color when we are in a terminal
10
10
  runtime_logging = " --format ParallelTests::Cucumber::RuntimeLogger --out #{runtime_log}"
11
11
  cmd = [
12
- color,
13
12
  executable,
14
13
  (runtime_logging if File.directory?(File.dirname(runtime_log))),
15
14
  cucumber_opts(options[:test_options]),
@@ -8,7 +8,8 @@ module ParallelTests
8
8
  def self.run_tests(test_files, process_number, num_processes, options)
9
9
  exe = executable # expensive, so we cache
10
10
  version = (exe =~ /\brspec\b/ ? 2 : 1)
11
- cmd = "#{rspec_1_color if version == 1}#{exe} #{options[:test_options]} #{rspec_2_color if version == 2}#{spec_opts} #{test_files*' '}"
11
+ cmd = [exe, options[:test_options], (rspec_2_color if version == 2), spec_opts, *test_files].compact.join(" ")
12
+ options = options.merge(:env => rspec_1_color) if version == 1
12
13
  execute_command(cmd, process_number, num_processes, options)
13
14
  end
14
15
 
@@ -44,11 +45,15 @@ module ParallelTests
44
45
  end
45
46
 
46
47
  def self.rspec_1_color
47
- 'RSPEC_COLOR=1 ; export RSPEC_COLOR ;' if $stdout.tty?
48
+ if $stdout.tty?
49
+ {'RSPEC_COLOR' => "1"}
50
+ else
51
+ {}
52
+ end
48
53
  end
49
54
 
50
55
  def self.rspec_2_color
51
- '--color --tty ' if $stdout.tty?
56
+ '--color --tty' if $stdout.tty?
52
57
  end
53
58
 
54
59
  def self.spec_opts
@@ -1,3 +1,5 @@
1
+ require 'open3'
2
+
1
3
  module ParallelTests
2
4
  module Test
3
5
  class Runner
@@ -46,12 +48,35 @@ module ParallelTests
46
48
  end
47
49
 
48
50
  def self.execute_command(cmd, process_number, num_processes, options)
49
- prefix = "PARALLEL_TEST_GROUPS=#{ num_processes } ; export PARALLEL_TEST_GROUPS;"
50
- cmd = "#{prefix} TEST_ENV_NUMBER=#{test_env_number(process_number)} ; export TEST_ENV_NUMBER; #{cmd}"
51
- f = open("|#{cmd}", 'r')
52
- output = fetch_output(f, options)
53
- f.close
54
- {:stdout => output, :exit_status => $?.exitstatus}
51
+ env = (options[:env] || {}).merge(
52
+ "TEST_ENV_NUMBER" => test_env_number(process_number),
53
+ "PARALLEL_TEST_GROUPS" => num_processes
54
+ )
55
+ execute_command_and_capture_output(env, cmd, options[:serialize_stdout])
56
+ end
57
+
58
+ def self.execute_command_and_capture_output(env, cmd, silence)
59
+ # make processes descriptive / visible in ps -ef
60
+ exports = env.map do |k,v|
61
+ "#{k}=#{v};export #{k}"
62
+ end.join(";")
63
+ cmd = "#{exports};#{cmd}"
64
+
65
+ output, errput, exitstatus = nil
66
+ if RUBY_VERSION =~ /^1\.8/
67
+ open("|#{cmd}", "r") do |output|
68
+ output, errput = capture_output(output, nil, silence)
69
+ end
70
+ exitstatus = $?.exitstatus
71
+ else
72
+ Open3.popen3(cmd) do |stdin, stdout, stderr, thread|
73
+ stdin.close
74
+ output, errput = capture_output(stdout, stderr, silence)
75
+ exitstatus = thread.value.exitstatus
76
+ end
77
+ end
78
+
79
+ {:stdout => output, :stderr => errput, :exit_status => exitstatus}
55
80
  end
56
81
 
57
82
  def self.find_results(test_output)
@@ -84,26 +109,29 @@ module ParallelTests
84
109
  def self.sum_up_results(results)
85
110
  results = results.join(' ').gsub(/s\b/,'') # combine and singularize results
86
111
  counts = results.scan(/(\d+) (\w+)/)
87
- sums = counts.inject(Hash.new(0)) do |sum, (number, word)|
112
+ counts.inject(Hash.new(0)) do |sum, (number, word)|
88
113
  sum[word] += number.to_i
89
114
  sum
90
115
  end
91
-
92
- sums
93
116
  end
94
117
 
95
118
  # read output of the process and print it in chunks
96
- def self.fetch_output(process, options)
97
- all = ''
98
- while buffer = process.readpartial(1000000)
99
- all << buffer
100
- unless options[:serialize_stdout]
101
- $stdout.print buffer
102
- $stdout.flush
119
+ def self.capture_output(out, err, silence)
120
+ results = ["", ""]
121
+ loop do
122
+ [[out, $stdout, 0], [err, $stderr, 1]].each do |input, output, index|
123
+ next unless input
124
+ begin
125
+ read = input.readpartial(1000000) # read whatever chunk we can get
126
+ results[index] << read
127
+ output.print read if index == 1 || !silence
128
+
129
+ rescue EOFError
130
+ raise if index == 0 # we only care about the end of stdout
131
+ end
103
132
  end
104
133
  end rescue EOFError
105
-
106
- all
134
+ results
107
135
  end
108
136
 
109
137
  def self.with_runtime_info(tests)
@@ -1,3 +1,3 @@
1
1
  module ParallelTests
2
- VERSION = Version = '0.10.4'
2
+ VERSION = Version = '0.11.0'
3
3
  end
@@ -188,7 +188,7 @@ describe 'CLI' do
188
188
  end
189
189
 
190
190
  it "can wait_for_other_processes_to_finish" do
191
- write "test/a_test.rb", "require 'parallel_tests'; ParallelTests.wait_for_other_processes_to_finish; puts 'a'"
191
+ write "test/a_test.rb", "require 'parallel_tests'; sleep 0.5 ; ParallelTests.wait_for_other_processes_to_finish; puts 'a'"
192
192
  write "test/b_test.rb", "sleep 1; puts 'b'"
193
193
  write "test/c_test.rb", "sleep 1.5; puts 'c'"
194
194
  write "test/d_test.rb", "sleep 2; puts 'd'"
@@ -15,54 +15,36 @@ describe ParallelTests::Cucumber do
15
15
  ParallelTests::Cucumber::Runner.run_tests(*args)
16
16
  end
17
17
 
18
- it "uses TEST_ENV_NUMBER=blank when called for process 0" do
19
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
20
- call(['xxx'],0,22,{})
21
- end
22
-
23
- it "uses TEST_ENV_NUMBER=2 when called for process 1" do
24
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
25
- call(['xxx'],1,22,{})
26
- end
27
-
28
- it 'sets PARALLEL_TEST_GROUPS so child processes know that they are being run under parallel_tests' do
29
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x=~/PARALLEL_TEST_GROUPS=22/}.and_return mocked_process
30
- call(['xxx'],1,22,{})
18
+ def should_run_with(regex)
19
+ ParallelTests::Test::Runner.should_receive(:execute_command).with{|a,b,c,d| a =~ regex}
31
20
  end
32
21
 
33
22
  it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do
34
23
  ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec'
35
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x=~/script\/custom_rspec/}.and_return mocked_process
24
+ should_run_with /script\/custom_rspec/
36
25
  call(['xxx'],1,22,{})
37
26
  ENV.delete('PARALLEL_TESTS_EXECUTABLE')
38
27
  end
39
28
 
40
- it "returns the output" do
41
- io = open('spec/spec_helper.rb')
42
- $stdout.stub!(:print)
43
- ParallelTests::Cucumber::Runner.should_receive(:open).and_return io
44
- call(['xxx'],1,22,{})[:stdout].should =~ /\$LOAD_PATH << File/
45
- end
46
-
47
29
  it "runs bundle exec cucumber when on bundler 0.9" do
48
30
  ParallelTests.stub!(:bundler_enabled?).and_return true
49
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{bundle exec cucumber}}.and_return mocked_process
31
+ should_run_with %r{bundle exec cucumber}
50
32
  call(['xxx'],1,22,{})
51
33
  end
52
34
 
53
35
  it "runs script/cucumber when script/cucumber is found" do
54
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber}}.and_return mocked_process
36
+ should_run_with %r{script/cucumber}
55
37
  call(['xxx'],1,22,{})
56
38
  end
57
39
 
58
40
  it "runs cucumber by default" do
59
41
  File.stub!(:file?).with('script/cucumber').and_return false
60
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x !~ %r{(script/cucumber)|(bundle exec cucumber)}}.and_return mocked_process
42
+ should_run_with %r{^cucumber}
61
43
  call(['xxx'],1,22,{})
62
44
  end
63
45
 
64
46
  it "uses options passed in" do
65
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* -p default}}.and_return mocked_process
47
+ should_run_with %r{script/cucumber .* -p default}
66
48
  call(['xxx'],1,22,:test_options => '-p default')
67
49
  end
68
50
 
@@ -74,31 +56,31 @@ describe ParallelTests::Cucumber do
74
56
  end
75
57
 
76
58
  it "uses parallel profile" do
77
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* foo bar --profile parallel xxx}}.and_return mocked_process
59
+ should_run_with %r{script/cucumber .* foo bar --profile parallel xxx}
78
60
  call(['xxx'],1,22, :test_options => 'foo bar')
79
61
  end
80
62
 
81
63
  it "uses given profile via --profile" do
82
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* --profile foo xxx$}}.and_return mocked_process
64
+ should_run_with %r{script/cucumber .* --profile foo xxx$}
83
65
  call(['xxx'],1,22, :test_options => '--profile foo')
84
66
  end
85
67
 
86
68
  it "uses given profile via -p" do
87
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* -p foo xxx$}}.and_return mocked_process
69
+ should_run_with %r{script/cucumber .* -p foo xxx$}
88
70
  call(['xxx'],1,22, :test_options => '-p foo')
89
71
  end
90
72
  end
91
73
 
92
74
  it "does not use parallel profile if config/cucumber.yml does not contain it" do
93
75
  file_contents = 'blob: -f progress'
94
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* foo bar}}.and_return mocked_process
76
+ should_run_with %r{script/cucumber .* foo bar}
95
77
  Dir.should_receive(:glob).and_return ['config/cucumber.yml']
96
78
  File.should_receive(:read).with('config/cucumber.yml').and_return file_contents
97
79
  call(['xxx'],1,22,:test_options => 'foo bar')
98
80
  end
99
81
 
100
82
  it "does not use the parallel profile if config/cucumber.yml does not exist" do
101
- ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .*}}.and_return mocked_process
83
+ should_run_with %r{script/cucumber} # TODO this test looks useless...
102
84
  Dir.should_receive(:glob).and_return []
103
85
  call(['xxx'],1,22,{})
104
86
  end
@@ -17,107 +17,93 @@ describe ParallelTests::RSpec::Runner do
17
17
  ParallelTests::RSpec::Runner.run_tests(*args)
18
18
  end
19
19
 
20
- it "uses TEST_ENV_NUMBER=blank when called for process 0" do
21
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y|x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
22
- call(['xxx'], 0, 22, {})
20
+ def should_run_with(regex)
21
+ ParallelTests::Test::Runner.should_receive(:execute_command).with{|a,b,c,d| a =~ regex}
23
22
  end
24
23
 
25
- it "uses TEST_ENV_NUMBER=2 when called for process 1" do
26
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
27
- call(['xxx'],1,22,{})
28
- end
29
-
30
- it 'sets PARALLEL_TEST_GROUPS so child processes know that they are being run under parallel_tests' do
31
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/PARALLEL_TEST_GROUPS=22/}.and_return mocked_process
32
- call(['xxx'],1,22,{})
33
- end
34
-
35
- it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do
36
- ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec'
37
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/script\/custom_rspec/}.and_return mocked_process
38
- call(['xxx'],1,22,{})
39
- ENV.delete('PARALLEL_TESTS_EXECUTABLE')
24
+ def should_not_run_with(regex)
25
+ ParallelTests::Test::Runner.should_receive(:execute_command).with{|a,b,c,d| a !~ regex}
40
26
  end
41
27
 
42
28
  it "runs with color when called from cmdline" do
43
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/ --tty /}.and_return mocked_process
29
+ should_run_with %r{ --tty}
44
30
  $stdout.should_receive(:tty?).and_return true
45
- call(['xxx'],1,22,{})
31
+ call('xxx', 1, 22, {})
46
32
  end
47
33
 
48
34
  it "runs without color when not called from cmdline" do
49
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ / --tty /}.and_return mocked_process
35
+ should_not_run_with %r{ --tty}
50
36
  $stdout.should_receive(:tty?).and_return false
51
- call(['xxx'],1,22,{})
37
+ call('xxx', 1, 22, {})
52
38
  end
53
39
 
54
40
  it "runs with color for rspec 1 when called for the cmdline" do
55
41
  File.should_receive(:file?).with('script/spec').and_return true
56
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/ RSPEC_COLOR=1 /}.and_return mocked_process
42
+ ParallelTests::Test::Runner.should_receive(:execute_command).with { |a, b, c, d| d[:env] == {"RSPEC_COLOR" => "1"} }
57
43
  $stdout.should_receive(:tty?).and_return true
58
- call(['xxx'],1,22,{})
44
+ call('xxx', 1, 22, {})
59
45
  end
60
46
 
61
47
  it "runs without color for rspec 1 when not called for the cmdline" do
62
48
  File.should_receive(:file?).with('script/spec').and_return true
63
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ / RSPEC_COLOR=1 /}.and_return mocked_process
49
+ ParallelTests::Test::Runner.should_receive(:execute_command).with { |a, b, c, d| d[:env] == {} }
64
50
  $stdout.should_receive(:tty?).and_return false
65
- call(['xxx'],1,22,{})
51
+ call('xxx', 1, 22, {})
66
52
  end
67
53
 
68
54
  it "run bundle exec spec when on bundler rspec 1" do
69
55
  File.stub!(:file?).with('script/spec').and_return false
70
56
  ParallelTests.stub!(:bundler_enabled?).and_return true
71
57
  ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec-core").and_return "Could not find gem 'rspec-core' in bundler."
72
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{bundle exec spec}}.and_return mocked_process
73
- call(['xxx'],1,22,{})
58
+ should_run_with %r{bundle exec spec}
59
+ call('xxx', 1, 22, {})
74
60
  end
75
61
 
76
62
  it "run bundle exec rspec when on bundler rspec 2" do
77
63
  File.stub!(:file?).with('script/spec').and_return false
78
64
  ParallelTests.stub!(:bundler_enabled?).and_return true
79
65
  ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec-core").and_return "/foo/bar/rspec-core-2.0.2"
80
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{bundle exec rspec}}.and_return mocked_process
81
- call(['xxx'],1,22,{})
66
+ should_run_with %r{bundle exec rspec}
67
+ call('xxx', 1, 22, {})
82
68
  end
83
69
 
84
70
  it "runs script/spec when script/spec can be found" do
85
71
  File.should_receive(:file?).with('script/spec').and_return true
86
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec}}.and_return mocked_process
87
- call(['xxx'],1,22,{})
72
+ should_run_with %r{script/spec}
73
+ call('xxx' ,1, 22, {})
88
74
  end
89
75
 
90
76
  it "runs spec when script/spec cannot be found" do
91
77
  File.stub!(:file?).with('script/spec').and_return false
92
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ %r{script/spec}}.and_return mocked_process
93
- call(['xxx'],1,22,{})
78
+ should_not_run_with %r{ script/spec}
79
+ call('xxx', 1, 22, {})
94
80
  end
95
81
 
96
82
  it "uses no -O when no opts where found" do
97
83
  File.stub!(:file?).with('spec/spec.opts').and_return false
98
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ %r{spec/spec.opts}}.and_return mocked_process
99
- call(['xxx'],1,22,{})
84
+ should_not_run_with %r{spec/spec.opts}
85
+ call('xxx', 1, 22, {})
100
86
  end
101
87
 
102
88
  it "uses -O spec/spec.opts when found (with script/spec)" do
103
89
  File.stub!(:file?).with('script/spec').and_return true
104
90
  File.stub!(:file?).with('spec/spec.opts').and_return true
105
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+ -O spec/spec.opts}}.and_return mocked_process
106
- call(['xxx'],1,22,{})
91
+ should_run_with %r{script/spec\s+-O spec/spec.opts}
92
+ call('xxx', 1, 22, {})
107
93
  end
108
94
 
109
95
  it "uses -O spec/parallel_spec.opts when found (with script/spec)" do
110
96
  File.stub!(:file?).with('script/spec').and_return true
111
97
  File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
112
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+ -O spec/parallel_spec.opts}}.and_return mocked_process
113
- call(['xxx'],1,22,{})
98
+ should_run_with %r{script/spec\s+-O spec/parallel_spec.opts}
99
+ call('xxx', 1, 22, {})
114
100
  end
115
101
 
116
102
  it "uses -O .rspec_parallel when found (with script/spec)" do
117
103
  File.stub!(:file?).with('script/spec').and_return true
118
104
  File.should_receive(:file?).with('.rspec_parallel').and_return true
119
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+ -O .rspec_parallel}}.and_return mocked_process
120
- call(['xxx'],1,22,{})
105
+ should_run_with %r{script/spec\s+-O .rspec_parallel}
106
+ call('xxx', 1, 22, {})
121
107
  end
122
108
 
123
109
  it "uses -O spec/parallel_spec.opts with rspec1" do
@@ -126,8 +112,8 @@ describe ParallelTests::RSpec::Runner do
126
112
  ParallelTests.stub!(:bundler_enabled?).and_return true
127
113
  ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec-core").and_return "Could not find gem 'rspec-core'."
128
114
 
129
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{spec\s+ -O spec/parallel_spec.opts}}.and_return mocked_process
130
- call(['xxx'],1,22,{})
115
+ should_run_with %r{spec\s+-O spec/parallel_spec.opts}
116
+ call('xxx', 1, 22, {})
131
117
  end
132
118
 
133
119
  it "uses -O spec/parallel_spec.opts with rspec2" do
@@ -136,20 +122,18 @@ describe ParallelTests::RSpec::Runner do
136
122
  ParallelTests.stub!(:bundler_enabled?).and_return true
137
123
  ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec-core").and_return "/foo/bar/rspec-core-2.4.2"
138
124
 
139
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{rspec\s+ --color --tty -O spec/parallel_spec.opts}}.and_return mocked_process
140
- call(['xxx'],1,22,{})
125
+ should_run_with %r{rspec\s+--color --tty -O spec/parallel_spec.opts}
126
+ call('xxx', 1, 22, {})
141
127
  end
142
128
 
143
129
  it "uses options passed in" do
144
- ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{rspec -f n}}.and_return mocked_process
145
- call(['xxx'],1,22, :test_options => '-f n')
130
+ should_run_with %r{rspec -f n}
131
+ call('xxx', 1, 22, :test_options => '-f n')
146
132
  end
147
133
 
148
134
  it "returns the output" do
149
- io = open('spec/spec_helper.rb')
150
- $stdout.stub!(:print)
151
- ParallelTests::RSpec::Runner.should_receive(:open).and_return io
152
- call(['xxx'],1,22,{})[:stdout].should =~ /\$LOAD_PATH << File/
135
+ ParallelTests::RSpec::Runner.should_receive(:execute_command).and_return :x => 1
136
+ call('xxx', 1, 22, {}).should == {:x => 1}
153
137
  end
154
138
  end
155
139
 
@@ -4,57 +4,33 @@ require "parallel_tests/test/runner"
4
4
  describe ParallelTests::Test::Runner do
5
5
  test_tests_in_groups(ParallelTests::Test::Runner, 'test', '_test.rb')
6
6
 
7
- describe :run_tests do
7
+ describe ".run_tests" do
8
8
  def call(*args)
9
9
  ParallelTests::Test::Runner.run_tests(*args)
10
10
  end
11
11
 
12
- it "uses TEST_ENV_NUMBER=blank when called for process 0" do
13
- ParallelTests::Test::Runner.should_receive(:open).with{|x,y|x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
14
- call(['xxx'],0,22,{})
15
- end
16
-
17
- it "uses TEST_ENV_NUMBER=2 when called for process 1" do
18
- ParallelTests::Test::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
19
- call(['xxx'],1,22,{})
20
- end
21
-
22
- it 'sets PARALLEL_TEST_GROUPS so child processes know that they are being run under parallel_tests' do
23
- ENV['PARALLEL_TEST_PROCESSORS'] = '22'
24
- ParallelTests::Test::Runner.should_receive(:open).with{|x,y| x=~/PARALLEL_TEST_GROUPS=22/}.and_return mocked_process
25
- call(['xxx'],1,22,{})
26
- ENV.delete('PARALLEL_TEST_PROCESSORS')
27
- end
28
-
29
12
  it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do
30
- ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec'
31
- ParallelTests::Test::Runner.should_receive(:open).with{|x,y| x=~/script\/custom_rspec/}.and_return mocked_process
32
- call(['xxx'],1,22,{})
33
- ENV.delete('PARALLEL_TESTS_EXECUTABLE')
13
+ begin
14
+ ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec'
15
+ ParallelTests::Test::Runner.should_receive(:execute_command).with{|a,b,c,d| a.include?("script/custom_rspec") }
16
+ call(['xxx'], 1, 22, {})
17
+ ensure
18
+ ENV.delete('PARALLEL_TESTS_EXECUTABLE')
19
+ end
34
20
  end
35
21
 
36
22
  it "uses options" do
37
- ParallelTests::Test::Runner.should_receive(:open).with{|x,y| x=~ %r{ruby -Itest .* -- -v}}.and_return mocked_process
38
- call(['xxx'],1,22,:test_options => '-v')
23
+ ParallelTests::Test::Runner.should_receive(:execute_command).with{|a,b,c,d| a =~ %r{ruby -Itest .* -- -v}}
24
+ call(['xxx'], 1, 22, :test_options => '-v')
39
25
  end
40
26
 
41
27
  it "returns the output" do
42
- io = open('spec/spec_helper.rb')
43
- $stdout.stub!(:print)
44
- ParallelTests::Test::Runner.should_receive(:open).and_return io
45
- call(['xxx'],1,22,{})[:stdout].should =~ /\$LOAD_PATH << File/
46
- end
47
-
48
- it "does not output to stdout when serializing output" do
49
- io = open('spec/spec_helper.rb')
50
- $stdout.should_not_receive(:print)
51
- $stdout.should_not_receive(:flush)
52
- ParallelTests::Test::Runner.should_receive(:open).and_return io
53
- call(['xxx'],1,22,{:serialize_stdout => true})[:stdout]
28
+ ParallelTests::Test::Runner.should_receive(:execute_command).and_return({:x => 1})
29
+ call(['xxx'], 1, 22, {}).should == {:x => 1}
54
30
  end
55
31
  end
56
32
 
57
- describe :test_in_groups do
33
+ describe ".test_in_groups" do
58
34
  def call(*args)
59
35
  ParallelTests::Test::Runner.tests_in_groups(*args)
60
36
  end
@@ -98,7 +74,7 @@ describe ParallelTests::Test::Runner do
98
74
  end
99
75
  end
100
76
 
101
- describe :find_results do
77
+ describe ".find_results" do
102
78
  def call(*args)
103
79
  ParallelTests::Test::Runner.find_results(*args)
104
80
  end
@@ -150,7 +126,7 @@ EOF
150
126
  end
151
127
  end
152
128
 
153
- describe :find_tests do
129
+ describe ".find_tests" do
154
130
  def call(*args)
155
131
  ParallelTests::Test::Runner.send(:find_tests, *args)
156
132
  end
@@ -268,7 +244,7 @@ EOF
268
244
  end
269
245
  end
270
246
 
271
- describe :summarize_results do
247
+ describe ".summarize_results" do
272
248
  def call(*args)
273
249
  ParallelTests::Test::Runner.summarize_results(*args)
274
250
  end
@@ -293,4 +269,155 @@ EOF
293
269
  call(['1 xxx 2 yyy']).should == '1 xxx, 2 yyys'
294
270
  end
295
271
  end
272
+
273
+ describe ".execute_command" do
274
+ def call(*args)
275
+ ParallelTests::Test::Runner.execute_command(*args)
276
+ end
277
+
278
+ def capture_output
279
+ $stdout, $stderr = StringIO.new, StringIO.new
280
+ yield
281
+ [$stdout.string, $stderr.string]
282
+ ensure
283
+ $stdout, $stderr = STDOUT, STDERR
284
+ end
285
+
286
+ def run_with_file(content)
287
+ capture_output do
288
+ Tempfile.open("xxx") do |f|
289
+ f.write(content)
290
+ f.flush
291
+ yield f.path
292
+ end
293
+ end
294
+ end
295
+
296
+ it "sets process number to 2 for 1" do
297
+ run_with_file("puts ENV['TEST_ENV_NUMBER']") do |path|
298
+ result = call("ruby #{path}", 1, 4, {})
299
+ result.should == {
300
+ :stdout => "2\n",
301
+ :stderr => "",
302
+ :exit_status => 0
303
+ }
304
+ end
305
+ end
306
+
307
+ it "sets process number to '' for 0" do
308
+ run_with_file("puts ENV['TEST_ENV_NUMBER'].inspect") do |path|
309
+ result = call("ruby #{path}", 0, 4, {})
310
+ result.should == {
311
+ :stdout => "\"\"\n",
312
+ :stderr => "",
313
+ :exit_status => 0
314
+ }
315
+ end
316
+ end
317
+
318
+ it 'sets PARALLEL_TEST_GROUPS so child processes know that they are being run under parallel_tests' do
319
+ run_with_file("puts ENV['PARALLEL_TEST_GROUPS']") do |path|
320
+ result = call("ruby #{path}", 1, 4, {})
321
+ result.should == {
322
+ :stdout => "4\n",
323
+ :stderr => "",
324
+ :exit_status => 0
325
+ }
326
+ end
327
+ end
328
+
329
+ it "skips reads from stdin" do
330
+ if RUBY_VERSION =~ /^1\.8/
331
+ pending
332
+ else
333
+ run_with_file("$stdin.read; puts 123") do |path|
334
+ result = call("ruby #{path}", 1, 2, {})
335
+ result.should == {
336
+ :stdout => "123\n",
337
+ :stderr => "",
338
+ :exit_status => 0
339
+ }
340
+ end
341
+ end
342
+ end
343
+
344
+ it "waits for process to finish" do
345
+ run_with_file("sleep 0.5; puts 123; sleep 0.5; puts 345") do |path|
346
+ result = call("ruby #{path}", 1, 4, {})
347
+ result.should == {
348
+ :stdout => "123\n345\n",
349
+ :stderr => "",
350
+ :exit_status => 0
351
+ }
352
+ end
353
+ end
354
+
355
+ it "prints output while running" do
356
+ run_with_file("$stdout.sync = true; puts 123; sleep 0.1; print 345; sleep 0.1; puts 567") do |path|
357
+ $stdout.should_receive(:print).with("123\n")
358
+ if RUBY_VERSION =~ /^1\.8/
359
+ $stdout.should_receive(:print).with("345")
360
+ $stdout.should_receive(:print).with("567\n")
361
+ else
362
+ $stdout.should_receive(:print).with("345567\n")
363
+ end
364
+ result = call("ruby #{path}", 1, 4, {})
365
+ result.should == {
366
+ :stdout => "123\n345567\n",
367
+ :stderr => "",
368
+ :exit_status => 0
369
+ }
370
+ end
371
+ end
372
+
373
+ it "works with synced stdout" do
374
+ run_with_file("$stdout.sync = true; puts 123; sleep 0.1; puts 345") do |path|
375
+ result = call("ruby #{path}", 1, 4, {})
376
+ result.should == {
377
+ :stdout => "123\n345\n",
378
+ :stderr => "",
379
+ :exit_status => 0
380
+ }
381
+ end
382
+ end
383
+
384
+ it "does not print to stdout with :serialize_stdout" do
385
+ run_with_file("puts 123") do |path|
386
+ $stdout.should_not_receive(:print)
387
+ result = call("ruby #{path}", 1, 4, :serialize_stdout => true)
388
+ result.should == {
389
+ :stdout => "123\n",
390
+ :stderr => "",
391
+ :exit_status => 0
392
+ }
393
+ end
394
+ end
395
+
396
+ it "returns correct exit status" do
397
+ run_with_file("puts 123; exit 5") do |path|
398
+ result = call("ruby #{path}", 1, 4, {})
399
+ result.should == {
400
+ :stdout => "123\n",
401
+ :stderr => "",
402
+ :exit_status => 5
403
+ }
404
+ end
405
+ end
406
+
407
+ it "prints each stream to the correct stream" do
408
+ if RUBY_VERSION =~ /^1\.8/
409
+ pending
410
+ else
411
+ out, err = run_with_file("puts 123 ; $stderr.puts 345 ; exit 5") do |path|
412
+ result = call("ruby #{path}", 1, 4, {})
413
+ result.should == {
414
+ :stdout => "123\n",
415
+ :stderr => "345\n",
416
+ :exit_status => 5
417
+ }
418
+ end
419
+ err.should == "345\n"
420
+ end
421
+ end
422
+ end
296
423
  end
data/spec/spec_helper.rb CHANGED
@@ -27,7 +27,7 @@ RSpec.configure do |config|
27
27
  end
28
28
 
29
29
  def mocked_process
30
- open('|cat /dev/null')
30
+ StringIO.new
31
31
  end
32
32
 
33
33
  def size_of(group)
metadata CHANGED
@@ -1,41 +1,47 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: parallel_tests
3
- version: !ruby/object:Gem::Version
4
- version: 0.10.4
3
+ version: !ruby/object:Gem::Version
4
+ hash: 51
5
5
  prerelease:
6
+ segments:
7
+ - 0
8
+ - 11
9
+ - 0
10
+ version: 0.11.0
6
11
  platform: ruby
7
- authors:
12
+ authors:
8
13
  - Michael Grosser
9
14
  autorequire:
10
15
  bindir: bin
11
16
  cert_chain: []
12
- date: 2013-03-25 00:00:00.000000000 Z
13
- dependencies:
14
- - !ruby/object:Gem::Dependency
17
+
18
+ date: 2013-04-13 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
15
21
  name: parallel
16
- requirement: !ruby/object:Gem::Requirement
17
- none: false
18
- requirements:
19
- - - ! '>='
20
- - !ruby/object:Gem::Version
21
- version: '0'
22
- type: :runtime
23
22
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
23
+ type: :runtime
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ version_requirements: *id001
30
34
  description:
31
35
  email: michael@grosser.it
32
- executables:
36
+ executables:
33
37
  - parallel_cucumber
34
38
  - parallel_rspec
35
39
  - parallel_test
36
40
  extensions: []
41
+
37
42
  extra_rdoc_files: []
38
- files:
43
+
44
+ files:
39
45
  - .gitignore
40
46
  - .rspec
41
47
  - .travis.yml
@@ -79,34 +85,37 @@ files:
79
85
  - spec/parallel_tests_spec.rb
80
86
  - spec/spec_helper.rb
81
87
  homepage: http://github.com/grosser/parallel_tests
82
- licenses:
88
+ licenses:
83
89
  - MIT
84
90
  post_install_message:
85
91
  rdoc_options: []
86
- require_paths:
92
+
93
+ require_paths:
87
94
  - lib
88
- required_ruby_version: !ruby/object:Gem::Requirement
95
+ required_ruby_version: !ruby/object:Gem::Requirement
89
96
  none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
94
- segments:
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ hash: 3
101
+ segments:
95
102
  - 0
96
- hash: -3747523208207304867
97
- required_rubygems_version: !ruby/object:Gem::Requirement
103
+ version: "0"
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
105
  none: false
99
- requirements:
100
- - - ! '>='
101
- - !ruby/object:Gem::Version
102
- version: '0'
103
- segments:
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ hash: 3
110
+ segments:
104
111
  - 0
105
- hash: -3747523208207304867
112
+ version: "0"
106
113
  requirements: []
114
+
107
115
  rubyforge_project:
108
116
  rubygems_version: 1.8.25
109
117
  signing_key:
110
118
  specification_version: 3
111
119
  summary: Run Test::Unit / RSpec / Cucumber in parallel
112
120
  test_files: []
121
+