parallel_tests 0.10.2 → 0.10.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -2
- data/Gemfile.lock +2 -2
- data/Readme.md +2 -0
- data/lib/parallel_tests/cli.rb +24 -4
- data/lib/parallel_tests/cucumber/runner.rb +1 -1
- data/lib/parallel_tests/rspec/runner.rb +1 -1
- data/lib/parallel_tests/test/runner.rb +8 -6
- data/lib/parallel_tests/version.rb +1 -1
- data/spec/integration_spec.rb +15 -0
- data/spec/parallel_tests/test/runner_spec.rb +8 -0
- data/spec/spec_helper.rb +3 -0
- metadata +4 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
parallel_tests (0.10.
|
4
|
+
parallel_tests (0.10.3)
|
5
5
|
parallel
|
6
6
|
|
7
7
|
GEM
|
@@ -19,7 +19,7 @@ GEM
|
|
19
19
|
gherkin (2.7.6)
|
20
20
|
json (>= 1.4.6)
|
21
21
|
json (1.7.5)
|
22
|
-
parallel (0.6.
|
22
|
+
parallel (0.6.3)
|
23
23
|
rake (10.0.3)
|
24
24
|
rspec (2.12.0)
|
25
25
|
rspec-core (~> 2.12.0)
|
data/Readme.md
CHANGED
@@ -165,6 +165,7 @@ Options are:
|
|
165
165
|
-e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUM']
|
166
166
|
-o, --test-options '[OPTIONS]' execute test commands with those options
|
167
167
|
-t, --type [TYPE] test(default) / rspec / cucumber
|
168
|
+
--serialize-stdout Serialize stdout output, nothing will be written until everything is done
|
168
169
|
--non-parallel execute same commands but do not in parallel, needs --exec
|
169
170
|
--no-symlinks Do not traverse symbolic links to find test files
|
170
171
|
--ignore-tags [PATTERN] When counting steps ignore scenarios with tags that match this pattern
|
@@ -259,6 +260,7 @@ inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-
|
|
259
260
|
- [Joseph Shraibman](https://github.com/jshraibman-mdsol)
|
260
261
|
- [David Davis](https://github.com/daviddavis)
|
261
262
|
- [Ari Pollak](https://github.com/aripollak)
|
263
|
+
- [Aaron Jensen](https://github.com/aaronjensen)
|
262
264
|
|
263
265
|
[Michael Grosser](http://grosser.it)<br/>
|
264
266
|
michael@grosser.it<br/>
|
data/lib/parallel_tests/cli.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'optparse'
|
2
|
+
require 'tempfile'
|
2
3
|
|
3
4
|
module ParallelTests
|
4
5
|
class CLI
|
@@ -17,6 +18,16 @@ module ParallelTests
|
|
17
18
|
|
18
19
|
private
|
19
20
|
|
21
|
+
def execute_in_parallel(items, num_processes, options)
|
22
|
+
Tempfile.open 'parallel_tests-lock' do |lock|
|
23
|
+
return Parallel.map(items, :in_processes => num_processes) do |item|
|
24
|
+
result = yield(item)
|
25
|
+
report_output(result, lock) if options[:serialize_stdout]
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
20
31
|
def run_tests_in_parallel(num_processes, options)
|
21
32
|
test_results = nil
|
22
33
|
|
@@ -24,7 +35,7 @@ module ParallelTests
|
|
24
35
|
groups = @runner.tests_in_groups(options[:files], num_processes, options)
|
25
36
|
report_number_of_tests(groups)
|
26
37
|
|
27
|
-
test_results =
|
38
|
+
test_results = execute_in_parallel(groups, groups.size, options) do |group|
|
28
39
|
run_tests(group, groups.index(group), num_processes, options)
|
29
40
|
end
|
30
41
|
|
@@ -42,6 +53,14 @@ module ParallelTests
|
|
42
53
|
end
|
43
54
|
end
|
44
55
|
|
56
|
+
def report_output(result, lock)
|
57
|
+
lock.flock File::LOCK_EX
|
58
|
+
$stdout.puts result[:stdout]
|
59
|
+
$stdout.flush
|
60
|
+
ensure
|
61
|
+
lock.flock File::LOCK_UN
|
62
|
+
end
|
63
|
+
|
45
64
|
def report_results(test_results)
|
46
65
|
results = @runner.find_results(test_results.map { |result| result[:stdout] }*"")
|
47
66
|
puts ""
|
@@ -105,6 +124,7 @@ TEXT
|
|
105
124
|
abort
|
106
125
|
end
|
107
126
|
end
|
127
|
+
opts.on("--serialize-stdout", "Serialize stdout output, nothing will be written until everything is done") { options[:serialize_stdout] = true }
|
108
128
|
opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec") { options[:non_parallel] = true }
|
109
129
|
opts.on("--no-symlinks", "Do not traverse symbolic links to find test files") { options[:symlinks] = false }
|
110
130
|
opts.on('--ignore-tags [PATTERN]', 'When counting steps ignore scenarios with tags that match this pattern') { |arg| options[:ignore_tag_pattern] = arg }
|
@@ -133,11 +153,11 @@ TEXT
|
|
133
153
|
runs = (0...num_processes).to_a
|
134
154
|
results = if options[:non_parallel]
|
135
155
|
runs.map do |i|
|
136
|
-
ParallelTests::Test::Runner.execute_command(command, i, num_processes)
|
156
|
+
ParallelTests::Test::Runner.execute_command(command, i, num_processes, options)
|
137
157
|
end
|
138
158
|
else
|
139
|
-
|
140
|
-
ParallelTests::Test::Runner.execute_command(command, i, num_processes)
|
159
|
+
execute_in_parallel(runs, num_processes, options) do |i|
|
160
|
+
ParallelTests::Test::Runner.execute_command(command, i, num_processes, options)
|
141
161
|
end
|
142
162
|
end.flatten
|
143
163
|
|
@@ -9,7 +9,7 @@ module ParallelTests
|
|
9
9
|
exe = executable # expensive, so we cache
|
10
10
|
version = (exe =~ /\brspec\b/ ? 2 : 1)
|
11
11
|
cmd = "#{rspec_1_color if version == 1}#{exe} #{options[:test_options]} #{rspec_2_color if version == 2}#{spec_opts} #{test_files*' '}"
|
12
|
-
execute_command(cmd, process_number, num_processes)
|
12
|
+
execute_command(cmd, process_number, num_processes, options)
|
13
13
|
end
|
14
14
|
|
15
15
|
def self.executable
|
@@ -24,7 +24,7 @@ module ParallelTests
|
|
24
24
|
def self.run_tests(test_files, process_number, num_processes, options)
|
25
25
|
require_list = test_files.map { |filename| %{"#{File.expand_path filename}"} }.join(",")
|
26
26
|
cmd = "ruby -Itest -e '[#{require_list}].each {|f| require f }' -- #{options[:test_options]}"
|
27
|
-
execute_command(cmd, process_number, num_processes)
|
27
|
+
execute_command(cmd, process_number, num_processes, options)
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.line_is_result?(line)
|
@@ -45,11 +45,11 @@ module ParallelTests
|
|
45
45
|
Grouper.in_even_groups_by_size(tests, num_groups, options)
|
46
46
|
end
|
47
47
|
|
48
|
-
def self.execute_command(cmd, process_number, num_processes)
|
48
|
+
def self.execute_command(cmd, process_number, num_processes, options)
|
49
49
|
prefix = "PARALLEL_TEST_GROUPS=#{ num_processes } ; export PARALLEL_TEST_GROUPS;"
|
50
50
|
cmd = "#{prefix} TEST_ENV_NUMBER=#{test_env_number(process_number)} ; export TEST_ENV_NUMBER; #{cmd}"
|
51
51
|
f = open("|#{cmd}", 'r')
|
52
|
-
output = fetch_output(f)
|
52
|
+
output = fetch_output(f, options)
|
53
53
|
f.close
|
54
54
|
{:stdout => output, :exit_status => $?.exitstatus}
|
55
55
|
end
|
@@ -85,12 +85,14 @@ module ParallelTests
|
|
85
85
|
end
|
86
86
|
|
87
87
|
# read output of the process and print it in chunks
|
88
|
-
def self.fetch_output(process)
|
88
|
+
def self.fetch_output(process, options)
|
89
89
|
all = ''
|
90
90
|
while buffer = process.readpartial(1000000)
|
91
91
|
all << buffer
|
92
|
-
|
93
|
-
|
92
|
+
unless options[:serialize_stdout]
|
93
|
+
$stdout.print buffer
|
94
|
+
$stdout.flush
|
95
|
+
end
|
94
96
|
end rescue EOFError
|
95
97
|
|
96
98
|
all
|
data/spec/integration_spec.rb
CHANGED
@@ -78,6 +78,15 @@ describe 'CLI' do
|
|
78
78
|
result.scan('2 examples, 1 failure').size.should == 1
|
79
79
|
end
|
80
80
|
|
81
|
+
it "can serialize stdout" do
|
82
|
+
write 'spec/xxx_spec.rb', '5.times{describe("it"){it("should"){sleep 0.01; puts "TEST1"}}}'
|
83
|
+
write 'spec/xxx2_spec.rb', 'sleep 0.01; 5.times{describe("it"){it("should"){sleep 0.01; puts "TEST2"}}}'
|
84
|
+
result = run_tests "spec", :type => 'rspec', :add => "--serialize-stdout"
|
85
|
+
|
86
|
+
result.should_not =~ /TEST1.*TEST2.*TEST1/m
|
87
|
+
result.should_not =~ /TEST2.*TEST1.*TEST2/m
|
88
|
+
end
|
89
|
+
|
81
90
|
context "with given commands" do
|
82
91
|
it "can exec given commands with ENV['TEST_ENV_NUM']" do
|
83
92
|
result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4`
|
@@ -89,6 +98,12 @@ describe 'CLI' do
|
|
89
98
|
result.split("\n").should == %w["" "2" "3" "4"]
|
90
99
|
end
|
91
100
|
|
101
|
+
it "can serialize stdout" do
|
102
|
+
result = `#{executable} -e 'ruby -e "5.times{sleep 0.01;puts ENV[:TEST_ENV_NUMBER.to_s].to_i;STDOUT.flush}"' -n 2 --serialize-stdout`
|
103
|
+
result.should_not =~ /0.*2.*0/m
|
104
|
+
result.should_not =~ /2.*0.*2/m
|
105
|
+
end
|
106
|
+
|
92
107
|
it "exists with success if all sub-processes returned success" do
|
93
108
|
system("#{executable} -e 'cat /dev/null' -n 4").should == true
|
94
109
|
end
|
@@ -37,6 +37,14 @@ describe ParallelTests::Test::Runner do
|
|
37
37
|
ParallelTests::Test::Runner.should_receive(:open).and_return io
|
38
38
|
call(['xxx'],1,22,{})[:stdout].should =~ /\$LOAD_PATH << File/
|
39
39
|
end
|
40
|
+
|
41
|
+
it "does not output to stdout when serializing output" do
|
42
|
+
io = open('spec/spec_helper.rb')
|
43
|
+
$stdout.should_not_receive(:print)
|
44
|
+
$stdout.should_not_receive(:flush)
|
45
|
+
ParallelTests::Test::Runner.should_receive(:open).and_return io
|
46
|
+
call(['xxx'],1,22,{:serialize_stdout => true})[:stdout]
|
47
|
+
end
|
40
48
|
end
|
41
49
|
|
42
50
|
describe :test_in_groups do
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel_tests
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-03-
|
12
|
+
date: 2013-03-20 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parallel
|
@@ -93,7 +93,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
93
93
|
version: '0'
|
94
94
|
segments:
|
95
95
|
- 0
|
96
|
-
hash:
|
96
|
+
hash: -3820588893429922123
|
97
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
98
|
none: false
|
99
99
|
requirements:
|
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
102
|
version: '0'
|
103
103
|
segments:
|
104
104
|
- 0
|
105
|
-
hash:
|
105
|
+
hash: -3820588893429922123
|
106
106
|
requirements: []
|
107
107
|
rubyforge_project:
|
108
108
|
rubygems_version: 1.8.25
|