parallel_tests 0.9.4 → 0.10.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.
- data/.travis.yml +4 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +2 -2
- data/Readme.md +5 -1
- data/bin/parallel_cucumber +4 -1
- data/bin/parallel_rspec +4 -1
- data/bin/parallel_test +2 -3
- data/lib/parallel_tests.rb +7 -5
- data/lib/parallel_tests/cli.rb +37 -32
- data/lib/parallel_tests/cucumber/runner.rb +3 -1
- data/lib/parallel_tests/rspec/runner.rb +3 -1
- data/lib/parallel_tests/test/runner.rb +6 -0
- data/lib/parallel_tests/version.rb +1 -1
- data/spec/parallel_tests/cli_spec.rb +41 -10
- data/spec/parallel_tests/cucumber/runner_spec.rb +2 -1
- data/spec/parallel_tests/rspec/runner_spec.rb +2 -1
- data/spec/parallel_tests/test/runner_spec.rb +2 -1
- data/spec/spec_helper.rb +4 -7
- metadata +5 -4
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
@@ -26,7 +26,11 @@ gem "parallel", :group => :development
|
|
26
26
|
```
|
27
27
|
|
28
28
|
### Add to `config/database.yml`
|
29
|
-
ParallelTests uses 1 database per test-process
|
29
|
+
ParallelTests uses 1 database per test-process.
|
30
|
+
<table>
|
31
|
+
<tr><td>Process number</td><td>1</td><td>2</td><td>3</td></tr>
|
32
|
+
<tr><td>`ENV['TEST_ENV_NUMBER']`</td><td>''</td><td>'2'</td><td>'3'</td></tr>
|
33
|
+
</table>
|
30
34
|
|
31
35
|
```yaml
|
32
36
|
test:
|
data/bin/parallel_cucumber
CHANGED
@@ -1,2 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
2
|
+
$LOAD_PATH << File.expand_path("../../lib", __FILE__)
|
3
|
+
require "parallel_tests"
|
4
|
+
|
5
|
+
ParallelTests::CLI.new.run(["--type", "cucumber"] + ARGV)
|
data/bin/parallel_rspec
CHANGED
data/bin/parallel_test
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
$LOAD_PATH << File.
|
2
|
+
$LOAD_PATH << File.expand_path("../../lib", __FILE__)
|
3
3
|
require "parallel_tests"
|
4
|
-
require "parallel_tests/cli"
|
5
4
|
|
6
|
-
|
5
|
+
ParallelTests::CLI.new.run(["--type", "test"] + ARGV)
|
data/lib/parallel_tests.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require 'parallel_tests/grouper'
|
4
|
-
require 'parallel_tests/railtie' if defined? Rails::Railtie
|
1
|
+
require "parallel"
|
2
|
+
require "parallel_tests/railtie" if defined? Rails::Railtie
|
5
3
|
|
6
4
|
module ParallelTests
|
7
5
|
GREP_PROCESSES_COMMAND = "ps -ef | grep [T]EST_ENV_NUMBER= 2>&1"
|
8
6
|
|
7
|
+
autoload :CLI, "parallel_tests/cli"
|
8
|
+
autoload :VERSION, "parallel_tests/version"
|
9
|
+
autoload :Grouper, "parallel_tests/grouper"
|
10
|
+
|
9
11
|
def self.determine_number_of_processes(count)
|
10
12
|
[
|
11
13
|
count,
|
12
|
-
ENV[
|
14
|
+
ENV["PARALLEL_TEST_PROCESSORS"],
|
13
15
|
Parallel.processor_count
|
14
16
|
].detect{|c| not c.to_s.strip.empty? }.to_i
|
15
17
|
end
|
data/lib/parallel_tests/cli.rb
CHANGED
@@ -1,9 +1,8 @@
|
|
1
1
|
require 'optparse'
|
2
|
-
require 'parallel_tests/test/runner'
|
3
2
|
|
4
|
-
module
|
5
|
-
|
6
|
-
def
|
3
|
+
module ParallelTests
|
4
|
+
class CLI
|
5
|
+
def run(argv)
|
7
6
|
options = parse_options!(argv)
|
8
7
|
|
9
8
|
num_processes = ParallelTests.determine_number_of_processes(options[:count])
|
@@ -18,57 +17,50 @@ module ParallelTest
|
|
18
17
|
|
19
18
|
private
|
20
19
|
|
21
|
-
def
|
20
|
+
def run_tests_in_parallel(num_processes, options)
|
22
21
|
test_results = nil
|
23
|
-
lib = options[:type] || 'test'
|
24
|
-
runner = load_runner_for(lib)
|
25
22
|
|
26
23
|
report_time_taken do
|
27
|
-
groups = runner.tests_in_groups(options[:files], num_processes, options)
|
28
|
-
report_number_of_tests(
|
24
|
+
groups = @runner.tests_in_groups(options[:files], num_processes, options)
|
25
|
+
report_number_of_tests(groups)
|
29
26
|
|
30
27
|
test_results = Parallel.map(groups, :in_processes => groups.size) do |group|
|
31
|
-
run_tests(
|
28
|
+
run_tests(group, groups.index(group), num_processes, options)
|
32
29
|
end
|
33
30
|
|
34
|
-
report_results(
|
31
|
+
report_results(test_results)
|
35
32
|
end
|
36
33
|
|
37
|
-
abort final_fail_message
|
34
|
+
abort final_fail_message if any_test_failed?(test_results)
|
38
35
|
end
|
39
36
|
|
40
|
-
def
|
37
|
+
def run_tests(group, process_number, num_processes, options)
|
41
38
|
if group.empty?
|
42
39
|
{:stdout => '', :exit_status => 0}
|
43
40
|
else
|
44
|
-
runner.run_tests(group, process_number, num_processes, options)
|
41
|
+
@runner.run_tests(group, process_number, num_processes, options)
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
48
|
-
def
|
49
|
-
results = runner.find_results(test_results.map { |result| result[:stdout] }*"")
|
45
|
+
def report_results(test_results)
|
46
|
+
results = @runner.find_results(test_results.map { |result| result[:stdout] }*"")
|
50
47
|
puts ""
|
51
|
-
puts runner.summarize_results(results)
|
48
|
+
puts @runner.summarize_results(results)
|
52
49
|
end
|
53
50
|
|
54
|
-
def
|
55
|
-
name = runner.test_file_name
|
51
|
+
def report_number_of_tests(groups)
|
52
|
+
name = @runner.test_file_name
|
56
53
|
num_processes = groups.size
|
57
54
|
num_tests = groups.map(&:size).inject(:+)
|
58
55
|
puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{num_tests / groups.size} #{name}s per process"
|
59
56
|
end
|
60
57
|
|
61
58
|
#exit with correct status code so rake parallel:test && echo 123 works
|
62
|
-
def
|
59
|
+
def any_test_failed?(test_results)
|
63
60
|
test_results.any? { |result| result[:exit_status] != 0 }
|
64
61
|
end
|
65
62
|
|
66
|
-
def
|
67
|
-
require "parallel_tests/#{lib}/runner"
|
68
|
-
eval("ParallelTests::#{lib.capitalize.sub('Rspec','RSpec')}::Runner")
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.parse_options!(argv)
|
63
|
+
def parse_options!(argv)
|
72
64
|
options = {}
|
73
65
|
OptionParser.new do |opts|
|
74
66
|
opts.banner = <<BANNER
|
@@ -105,7 +97,14 @@ TEXT
|
|
105
97
|
|
106
98
|
opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUM']") { |path| options[:execute] = path }
|
107
99
|
opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg }
|
108
|
-
opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber")
|
100
|
+
opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber") do |type|
|
101
|
+
begin
|
102
|
+
@runner = load_runner(type)
|
103
|
+
rescue NameError, LoadError => e
|
104
|
+
puts "Runner for `#{type}` type has not been found! (#{e})"
|
105
|
+
abort
|
106
|
+
end
|
107
|
+
end
|
109
108
|
opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec") { options[:non_parallel] = true }
|
110
109
|
opts.on("--no-symlinks", "Do not traverse symbolic links to find test files") { options[:symlinks] = false }
|
111
110
|
opts.on('--ignore-tags [PATTERN]', 'When counting steps ignore scenarios with tags that match this pattern') { |arg| options[:ignore_tag_pattern] = arg }
|
@@ -124,7 +123,13 @@ TEXT
|
|
124
123
|
options
|
125
124
|
end
|
126
125
|
|
127
|
-
def
|
126
|
+
def load_runner(type)
|
127
|
+
require "parallel_tests/#{type}/runner"
|
128
|
+
klass_name = "ParallelTests::#{type.capitalize.sub("Rspec", "RSpec")}::Runner"
|
129
|
+
klass_name.split('::').inject(Object) { |x, y| x.const_get(y) }
|
130
|
+
end
|
131
|
+
|
132
|
+
def execute_shell_command_in_parallel(command, num_processes, options)
|
128
133
|
runs = (0...num_processes).to_a
|
129
134
|
results = if options[:non_parallel]
|
130
135
|
runs.map do |i|
|
@@ -139,20 +144,20 @@ TEXT
|
|
139
144
|
abort if results.any? { |r| r[:exit_status] != 0 }
|
140
145
|
end
|
141
146
|
|
142
|
-
def
|
147
|
+
def report_time_taken
|
143
148
|
start = Time.now
|
144
149
|
yield
|
145
150
|
puts "\nTook #{Time.now - start} seconds"
|
146
151
|
end
|
147
152
|
|
148
|
-
def
|
149
|
-
fail_message = "#{
|
153
|
+
def final_fail_message
|
154
|
+
fail_message = "#{@runner.name}s Failed"
|
150
155
|
fail_message = "\e[31m#{fail_message}\e[0m" if use_colors?
|
151
156
|
|
152
157
|
fail_message
|
153
158
|
end
|
154
159
|
|
155
|
-
def
|
160
|
+
def use_colors?
|
156
161
|
$stdout.tty?
|
157
162
|
end
|
158
163
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "parallel_tests/test/runner"
|
2
2
|
|
3
3
|
module ParallelTests
|
4
4
|
module Cucumber
|
5
5
|
class Runner < ParallelTests::Test::Runner
|
6
|
+
NAME = 'Cucumber'
|
7
|
+
|
6
8
|
def self.run_tests(test_files, process_number, num_processes, options)
|
7
9
|
color = ($stdout.tty? ? 'AUTOTEST=1 ; export AUTOTEST ;' : '')#display color when we are in a terminal
|
8
10
|
runtime_logging = " --format ParallelTests::Cucumber::RuntimeLogger --out #{runtime_log}"
|
@@ -1,8 +1,10 @@
|
|
1
|
-
require
|
1
|
+
require "parallel_tests/test/runner"
|
2
2
|
|
3
3
|
module ParallelTests
|
4
4
|
module RSpec
|
5
5
|
class Runner < ParallelTests::Test::Runner
|
6
|
+
NAME = 'RSpec'
|
7
|
+
|
6
8
|
def self.run_tests(test_files, process_number, num_processes, options)
|
7
9
|
exe = executable # expensive, so we cache
|
8
10
|
version = (exe =~ /\brspec\b/ ? 2 : 1)
|
@@ -1,12 +1,16 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "spec_helper"
|
2
|
+
require "parallel_tests/cli"
|
3
|
+
require "parallel_tests/rspec/runner"
|
3
4
|
|
4
|
-
|
5
|
-
|
5
|
+
|
6
|
+
describe ParallelTests::CLI do
|
7
|
+
subject { ParallelTests::CLI.new }
|
8
|
+
|
9
|
+
describe "#parse_options" do
|
6
10
|
let(:defaults){ {:files => []} }
|
7
11
|
|
8
12
|
def call(*args)
|
9
|
-
|
13
|
+
subject.send(:parse_options!, *args)
|
10
14
|
end
|
11
15
|
|
12
16
|
it "parses regular count" do
|
@@ -20,17 +24,44 @@ describe ParallelTest::CLI do
|
|
20
24
|
it "parses non-parallel as non-parallel" do
|
21
25
|
call(["--non-parallel"]).should == defaults.merge(:non_parallel => true)
|
22
26
|
end
|
27
|
+
|
28
|
+
it "finds the correct type when multiple are given" do
|
29
|
+
call(["--type", "test", "-t", "rspec"])
|
30
|
+
subject.instance_variable_get(:@runner).should == ParallelTests::RSpec::Runner
|
31
|
+
end
|
23
32
|
end
|
24
33
|
|
25
|
-
describe "
|
34
|
+
describe "#load_runner" do
|
35
|
+
it "requires and loads default runner" do
|
36
|
+
subject.should_receive(:require).with("parallel_tests/test/runner")
|
37
|
+
subject.send(:load_runner, "test").should == ParallelTests::Test::Runner
|
38
|
+
end
|
39
|
+
|
40
|
+
it "requires and loads rspec runner" do
|
41
|
+
subject.should_receive(:require).with("parallel_tests/rspec/runner")
|
42
|
+
subject.send(:load_runner, "rspec").should == ParallelTests::RSpec::Runner
|
43
|
+
end
|
44
|
+
|
45
|
+
it "fails to load unfindable runner" do
|
46
|
+
expect{
|
47
|
+
subject.send(:load_runner, "foo").should == ParallelTests::RSpec::Runner
|
48
|
+
}.to raise_error(LoadError)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#final_fail_message" do
|
53
|
+
before do
|
54
|
+
subject.instance_variable_set(:@runner, ParallelTests::Test::Runner)
|
55
|
+
end
|
56
|
+
|
26
57
|
it 'returns a plain fail message if colors are nor supported' do
|
27
|
-
|
28
|
-
|
58
|
+
subject.should_receive(:use_colors?).and_return(false)
|
59
|
+
subject.send(:final_fail_message).should == "Tests Failed"
|
29
60
|
end
|
30
61
|
|
31
62
|
it 'returns a colorized fail message if colors are supported' do
|
32
|
-
|
33
|
-
|
63
|
+
subject.should_receive(:use_colors?).and_return(true)
|
64
|
+
subject.send(:final_fail_message).should == "\e[31mTests Failed\e[0m"
|
34
65
|
end
|
35
66
|
end
|
36
67
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,15 +3,12 @@ $LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
|
|
3
3
|
FAKE_RAILS_ROOT = './tmp/pspecs/fixtures'
|
4
4
|
|
5
5
|
require 'tempfile'
|
6
|
+
|
6
7
|
require 'parallel_tests'
|
7
|
-
require 'parallel_tests/test/runner'
|
8
8
|
require 'parallel_tests/test/runtime_logger'
|
9
|
-
|
10
|
-
require 'parallel_tests/rspec/runner'
|
11
9
|
require 'parallel_tests/rspec/runtime_logger'
|
12
10
|
require 'parallel_tests/rspec/summary_logger'
|
13
11
|
|
14
|
-
require 'parallel_tests/cucumber/runner'
|
15
12
|
|
16
13
|
OutputLogger = Struct.new(:output) do
|
17
14
|
attr_reader :flock, :flush
|
@@ -62,7 +59,7 @@ def test_tests_in_groups(klass, folder, suffix)
|
|
62
59
|
test_root = "#{FAKE_RAILS_ROOT}/#{folder}"
|
63
60
|
|
64
61
|
describe :tests_in_groups do
|
65
|
-
before
|
62
|
+
before do
|
66
63
|
system "rm -rf #{FAKE_RAILS_ROOT}; mkdir -p #{test_root}/temp"
|
67
64
|
|
68
65
|
@files = [0,1,2,3,4,5,6,7].map do |i|
|
@@ -77,8 +74,8 @@ def test_tests_in_groups(klass, folder, suffix)
|
|
77
74
|
`rm -f #{@log}`
|
78
75
|
end
|
79
76
|
|
80
|
-
after
|
81
|
-
`rm -f #{
|
77
|
+
after do
|
78
|
+
`rm -f #{@log}`
|
82
79
|
end
|
83
80
|
|
84
81
|
def setup_runtime_log
|
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.
|
4
|
+
version: 0.10.0
|
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-02-
|
12
|
+
date: 2013-02-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: parallel
|
@@ -38,6 +38,7 @@ extra_rdoc_files: []
|
|
38
38
|
files:
|
39
39
|
- .gitignore
|
40
40
|
- .rspec
|
41
|
+
- .travis.yml
|
41
42
|
- Gemfile
|
42
43
|
- Gemfile.lock
|
43
44
|
- Rakefile
|
@@ -92,7 +93,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
92
93
|
version: '0'
|
93
94
|
segments:
|
94
95
|
- 0
|
95
|
-
hash:
|
96
|
+
hash: 1708090776445772692
|
96
97
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
98
|
none: false
|
98
99
|
requirements:
|
@@ -101,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
102
|
version: '0'
|
102
103
|
segments:
|
103
104
|
- 0
|
104
|
-
hash:
|
105
|
+
hash: 1708090776445772692
|
105
106
|
requirements: []
|
106
107
|
rubyforge_project:
|
107
108
|
rubygems_version: 1.8.24
|