moxiesoft_parallel_tests 0.4.12
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +34 -0
- data/Rakefile +21 -0
- data/Readme.md +156 -0
- data/VERSION +1 -0
- data/bin/parallel_cucumber +2 -0
- data/bin/parallel_spec +2 -0
- data/bin/parallel_test +98 -0
- data/lib/parallel_cucumber.rb +29 -0
- data/lib/parallel_specs/spec_runtime_logger.rb +49 -0
- data/lib/parallel_specs.rb +48 -0
- data/lib/parallel_tests/grouper.rb +31 -0
- data/lib/parallel_tests/railtie.rb +10 -0
- data/lib/parallel_tests/tasks.rb +80 -0
- data/lib/parallel_tests.rb +122 -0
- data/lib/tasks/parallel_tests.rake +1 -0
- data/spec/integration_spec.rb +114 -0
- data/spec/parallel_cucumber_spec.rb +72 -0
- data/spec/parallel_specs_spec.rb +149 -0
- data/spec/parallel_tests_spec.rb +142 -0
- data/spec/spec_helper.rb +110 -0
- metadata +104 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'parallel'
|
2
|
+
require 'parallel_tests/grouper'
|
3
|
+
require 'parallel_tests/railtie'
|
4
|
+
|
5
|
+
class ParallelTests
|
6
|
+
VERSION = File.read( File.join(File.dirname(__FILE__),'..','VERSION') ).strip
|
7
|
+
|
8
|
+
# parallel:spec[2,controller] <-> parallel:spec[controller]
|
9
|
+
def self.parse_rake_args(args)
|
10
|
+
num_processes = Parallel.processor_count
|
11
|
+
options = ""
|
12
|
+
if args[:count].to_s =~ /^\d*$/ # number or empty
|
13
|
+
num_processes = args[:count] unless args[:count].to_s.empty?
|
14
|
+
prefix = args[:path_prefix]
|
15
|
+
options = args[:options] if args[:options]
|
16
|
+
else # something stringy
|
17
|
+
prefix = args[:count]
|
18
|
+
end
|
19
|
+
[num_processes.to_i, prefix.to_s, options]
|
20
|
+
end
|
21
|
+
|
22
|
+
# finds all tests and partitions them into groups
|
23
|
+
def self.tests_in_groups(root, num_groups, options={})
|
24
|
+
if root.nil?
|
25
|
+
root = ['unit', 'functional', 'integration'].collect { |dir| File.join(Dir.pwd, 'test', dir) }
|
26
|
+
end
|
27
|
+
|
28
|
+
if options[:no_sort] == true
|
29
|
+
Grouper.in_groups(find_tests(root), num_groups)
|
30
|
+
else
|
31
|
+
Grouper.in_even_groups_by_size(tests_with_runtime(root), num_groups)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.run_tests(test_files, process_number, options)
|
36
|
+
require_list = test_files.map { |filename| "\"#{filename}\"" }.join(",")
|
37
|
+
cmd = "ruby -Itest #{options} -e '[#{require_list}].each {|f| require f }'"
|
38
|
+
execute_command(cmd, process_number)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.execute_command(cmd, process_number)
|
42
|
+
cmd = "TEST_ENV_NUMBER=#{test_env_number(process_number)} ; export TEST_ENV_NUMBER; #{cmd}"
|
43
|
+
f = open("|#{cmd}", 'r')
|
44
|
+
all = ''
|
45
|
+
while char = f.getc
|
46
|
+
char = (char.is_a?(Fixnum) ? char.chr : char) # 1.8 <-> 1.9
|
47
|
+
all << char
|
48
|
+
print char
|
49
|
+
STDOUT.flush
|
50
|
+
end
|
51
|
+
f.close
|
52
|
+
{:stdout => all, :exit_status => $?.exitstatus}
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.find_results(test_output)
|
56
|
+
test_output.split("\n").map {|line|
|
57
|
+
line = line.gsub(/\.|F|\*/,'')
|
58
|
+
next unless line_is_result?(line)
|
59
|
+
line
|
60
|
+
}.compact
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.test_env_number(process_number)
|
64
|
+
process_number == 0 ? '' : process_number + 1
|
65
|
+
end
|
66
|
+
|
67
|
+
protected
|
68
|
+
|
69
|
+
# copied from http://github.com/carlhuda/bundler Bundler::SharedHelpers#find_gemfile
|
70
|
+
def self.bundler_enabled?
|
71
|
+
return true if Object.const_defined?(:Bundler)
|
72
|
+
|
73
|
+
previous = nil
|
74
|
+
current = File.expand_path(Dir.pwd)
|
75
|
+
|
76
|
+
until !File.directory?(current) || current == previous
|
77
|
+
filename = File.join(current, "Gemfile")
|
78
|
+
return true if File.exists?(filename)
|
79
|
+
current, previous = File.expand_path("..", current), current
|
80
|
+
end
|
81
|
+
|
82
|
+
false
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.line_is_result?(line)
|
86
|
+
line =~ /\d+ failure/
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.test_suffix
|
90
|
+
"_test.rb"
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.tests_with_runtime(root)
|
94
|
+
tests = find_tests(root)
|
95
|
+
runtime_file = File.join(root,'..','tmp','parallel_profile.log')
|
96
|
+
lines = File.read(runtime_file).split("\n") rescue []
|
97
|
+
|
98
|
+
# use recorded test runtime if we got enough data
|
99
|
+
if lines.size * 1.5 > tests.size
|
100
|
+
times = Hash.new(1)
|
101
|
+
lines.each do |line|
|
102
|
+
test, time = line.split(":")
|
103
|
+
times[test] = time.to_f
|
104
|
+
end
|
105
|
+
tests.sort.map{|test| [test, times[test]] }
|
106
|
+
else # use file sizes
|
107
|
+
tests.sort.map{|test| [test, File.stat(test).size] }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.find_tests(root)
|
112
|
+
if root.is_a?(Array)
|
113
|
+
if root.first && Dir.exists?(root.first)
|
114
|
+
root.collect { |dir| find_tests(dir) }.flatten
|
115
|
+
else
|
116
|
+
root
|
117
|
+
end
|
118
|
+
else
|
119
|
+
Dir["#{root}**/**/*#{self.test_suffix}"]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "/../parallel_tests/tasks")
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe 'CLI' do
|
4
|
+
before do
|
5
|
+
`rm -rf #{folder}`
|
6
|
+
end
|
7
|
+
|
8
|
+
after do
|
9
|
+
`rm -rf #{folder}`
|
10
|
+
end
|
11
|
+
|
12
|
+
def folder
|
13
|
+
"/tmp/parallel_tests_tests"
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(file, content)
|
17
|
+
path = "#{folder}/spec/#{file}"
|
18
|
+
`mkdir -p #{File.dirname(path)}` unless File.exist?(File.dirname(path))
|
19
|
+
File.open(path, 'w'){|f| f.write content }
|
20
|
+
path
|
21
|
+
end
|
22
|
+
|
23
|
+
def bin_folder
|
24
|
+
"#{File.expand_path(File.dirname(__FILE__))}/../bin"
|
25
|
+
end
|
26
|
+
|
27
|
+
def executable
|
28
|
+
"#{bin_folder}/parallel_test"
|
29
|
+
end
|
30
|
+
|
31
|
+
def run_specs(options={})
|
32
|
+
`cd #{folder} && #{executable} -t spec -n #{options[:processes]||2} #{options[:add]} 2>&1`
|
33
|
+
end
|
34
|
+
|
35
|
+
it "runs tests in parallel" do
|
36
|
+
write 'xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}'
|
37
|
+
write 'xxx2_spec.rb', 'describe("it"){it("should"){puts "TEST2"}}'
|
38
|
+
result = run_specs
|
39
|
+
|
40
|
+
# test ran and gave their puts
|
41
|
+
result.should include('TEST1')
|
42
|
+
result.should include('TEST2')
|
43
|
+
|
44
|
+
# all results present
|
45
|
+
result.scan('1 example, 0 failure').size.should == 4 # 2 results + 2 result summary
|
46
|
+
result.scan(/Finished in \d+\.\d+ seconds/).size.should == 2
|
47
|
+
result.scan(/Took \d+\.\d+ seconds/).size.should == 1 # parallel summary
|
48
|
+
$?.success?.should == true
|
49
|
+
end
|
50
|
+
|
51
|
+
it "fails when tests fail" do
|
52
|
+
write 'xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}'
|
53
|
+
write 'xxx2_spec.rb', 'describe("it"){it("should"){1.should == 2}}'
|
54
|
+
result = run_specs
|
55
|
+
|
56
|
+
result.scan('1 example, 1 failure').size.should == 2
|
57
|
+
result.scan('1 example, 0 failure').size.should == 2
|
58
|
+
$?.success?.should == false
|
59
|
+
end
|
60
|
+
|
61
|
+
it "can exec given commands with ENV['TEST_ENV_NUM']" do
|
62
|
+
result = `#{executable} -e 'ruby -e "puts ENV[:TEST_ENV_NUMBER.to_s].inspect"' -n 4`
|
63
|
+
result.split("\n").sort.should == %w["" "2" "3" "4"]
|
64
|
+
end
|
65
|
+
|
66
|
+
it "can exec given command non-parallel" do
|
67
|
+
result = `#{executable} -e 'ruby -e "sleep(rand(10)/100.0); puts ENV[:TEST_ENV_NUMBER.to_s].inspect"' -n 4 --non-parallel`
|
68
|
+
result.split("\n").should == %w["" "2" "3" "4"]
|
69
|
+
end
|
70
|
+
|
71
|
+
it "exists with success if all sub-processes returned success" do
|
72
|
+
system("#{executable} -e 'cat /dev/null' -n 4").should == true
|
73
|
+
end
|
74
|
+
|
75
|
+
it "exists with failure if any sub-processes returned failure" do
|
76
|
+
system("#{executable} -e 'test -e xxxx' -n 4").should == false
|
77
|
+
end
|
78
|
+
|
79
|
+
it "can run through parallel_spec / parallel_cucumber" do
|
80
|
+
version = `#{executable} -v`
|
81
|
+
`#{bin_folder}/parallel_spec -v`.should == version
|
82
|
+
`#{bin_folder}/parallel_cucumber -v`.should == version
|
83
|
+
end
|
84
|
+
|
85
|
+
it "runs faster with more processes" do
|
86
|
+
write 'xxx_spec.rb', 'describe("it"){it("should"){sleep 2}}'
|
87
|
+
write 'xxx2_spec.rb', 'describe("it"){it("should"){sleep 2}}'
|
88
|
+
write 'xxx3_spec.rb', 'describe("it"){it("should"){sleep 2}}'
|
89
|
+
write 'xxx4_spec.rb', 'describe("it"){it("should"){sleep 2}}'
|
90
|
+
write 'xxx5_spec.rb', 'describe("it"){it("should"){sleep 2}}'
|
91
|
+
write 'xxx6_spec.rb', 'describe("it"){it("should"){sleep 2}}'
|
92
|
+
t = Time.now
|
93
|
+
run_specs :processes => 6
|
94
|
+
expected = 10
|
95
|
+
(Time.now - t).should <= expected
|
96
|
+
end
|
97
|
+
|
98
|
+
it "can can with given files" do
|
99
|
+
write "x1_spec.rb", "puts '111'"
|
100
|
+
write "x2_spec.rb", "puts '222'"
|
101
|
+
write "x3_spec.rb", "puts '333'"
|
102
|
+
result = run_specs(:add => 'spec/x1_spec.rb spec/x3_spec.rb')
|
103
|
+
result.should include('111')
|
104
|
+
result.should include('333')
|
105
|
+
result.should_not include('222')
|
106
|
+
end
|
107
|
+
|
108
|
+
it "can run with test-options" do
|
109
|
+
write "x1_spec.rb", ""
|
110
|
+
write "x2_spec.rb", ""
|
111
|
+
result = run_specs(:add => "--test-options ' --version'", :processes => 2)
|
112
|
+
result.should =~ /\d+\.\d+\.\d+.*\d+\.\d+\.\d+/m # prints version twice
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ParallelCucumber do
|
4
|
+
test_tests_in_groups(ParallelCucumber, 'features', ".feature")
|
5
|
+
|
6
|
+
describe :run_tests do
|
7
|
+
before do
|
8
|
+
ParallelCucumber.stub!(:bundler_enabled?).and_return false
|
9
|
+
File.stub!(:file?).with('.bundle/environment.rb').and_return false
|
10
|
+
File.stub!(:file?).with('script/cucumber').and_return true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "uses TEST_ENV_NUMBER=blank when called for process 0" do
|
14
|
+
ParallelCucumber.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
|
15
|
+
ParallelCucumber.run_tests(['xxx'],0,'')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "uses TEST_ENV_NUMBER=2 when called for process 1" do
|
19
|
+
ParallelCucumber.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
|
20
|
+
ParallelCucumber.run_tests(['xxx'],1,'')
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns the output" do
|
24
|
+
io = open('spec/spec_helper.rb')
|
25
|
+
ParallelCucumber.stub!(:print)
|
26
|
+
ParallelCucumber.should_receive(:open).and_return io
|
27
|
+
ParallelCucumber.run_tests(['xxx'],1,'')[:stdout].should =~ /\$LOAD_PATH << File/
|
28
|
+
end
|
29
|
+
|
30
|
+
it "runs bundle exec cucumber when on bundler 0.9" do
|
31
|
+
ParallelCucumber.stub!(:bundler_enabled?).and_return true
|
32
|
+
ParallelCucumber.should_receive(:open).with{|x,y| x =~ %r{bundle exec cucumber}}.and_return mocked_process
|
33
|
+
ParallelCucumber.run_tests(['xxx'],1,'')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "runs script/cucumber when script/cucumber is found" do
|
37
|
+
ParallelCucumber.should_receive(:open).with{|x,y| x =~ %r{script/cucumber}}.and_return mocked_process
|
38
|
+
ParallelCucumber.run_tests(['xxx'],1,'')
|
39
|
+
end
|
40
|
+
|
41
|
+
it "runs cucumber by default" do
|
42
|
+
File.stub!(:file?).with('script/cucumber').and_return false
|
43
|
+
ParallelCucumber.should_receive(:open).with{|x,y| x !~ %r{(script/cucumber)|(bundle exec cucumber)}}.and_return mocked_process
|
44
|
+
ParallelCucumber.run_tests(['xxx'],1,'')
|
45
|
+
end
|
46
|
+
|
47
|
+
it "uses options passed in" do
|
48
|
+
ParallelCucumber.should_receive(:open).with{|x,y| x =~ %r{script/cucumber -p default}}.and_return mocked_process
|
49
|
+
ParallelCucumber.run_tests(['xxx'],1,'-p default')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe :find_results do
|
54
|
+
it "finds multiple results in test output" do
|
55
|
+
output = <<EOF
|
56
|
+
And I should not see "/en/" # features/step_definitions/webrat_steps.rb:87
|
57
|
+
|
58
|
+
7 scenarios (3 failed, 4 passed)
|
59
|
+
33 steps (3 failed, 2 skipped, 28 passed)
|
60
|
+
/apps/rs/features/signup.feature:2
|
61
|
+
Given I am on "/" # features/step_definitions/common_steps.rb:12
|
62
|
+
When I click "register" # features/step_definitions/common_steps.rb:6
|
63
|
+
And I should have "2" emails # features/step_definitions/user_steps.rb:25
|
64
|
+
|
65
|
+
4 scenarios (4 passed)
|
66
|
+
40 steps (40 passed)
|
67
|
+
|
68
|
+
EOF
|
69
|
+
ParallelCucumber.find_results(output).should == ["7 scenarios (3 failed, 4 passed)", "33 steps (3 failed, 2 skipped, 28 passed)", "4 scenarios (4 passed)", "40 steps (40 passed)"]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ParallelSpecs do
|
4
|
+
test_tests_in_groups(ParallelSpecs, 'spec', '_spec.rb')
|
5
|
+
|
6
|
+
describe :run_tests do
|
7
|
+
before do
|
8
|
+
File.stub!(:file?).with('script/spec').and_return false
|
9
|
+
File.stub!(:file?).with('spec/spec.opts').and_return false
|
10
|
+
File.stub!(:file?).with('spec/parallel_spec.opts').and_return false
|
11
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return false
|
12
|
+
end
|
13
|
+
|
14
|
+
it "uses TEST_ENV_NUMBER=blank when called for process 0" do
|
15
|
+
ParallelSpecs.should_receive(:open).with{|x,y|x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
|
16
|
+
ParallelSpecs.run_tests(['xxx'],0,'')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "uses TEST_ENV_NUMBER=2 when called for process 1" do
|
20
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
|
21
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "runs with color when called from cmdline" do
|
25
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x=~/RSPEC_COLOR=1/}.and_return mocked_process
|
26
|
+
$stdout.should_receive(:tty?).and_return true
|
27
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "runs without color when not called from cmdline" do
|
31
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x !~ /RSPEC_COLOR/}.and_return mocked_process
|
32
|
+
$stdout.should_receive(:tty?).and_return false
|
33
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
34
|
+
end
|
35
|
+
|
36
|
+
it "run bundle exec spec when on bundler rspec 1" do
|
37
|
+
File.stub!(:file?).with('script/spec').and_return false
|
38
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return true
|
39
|
+
ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
|
40
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{bundle exec spec}}.and_return mocked_process
|
41
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
42
|
+
end
|
43
|
+
|
44
|
+
it "run bundle exec rspec when on bundler rspec 2" do
|
45
|
+
File.stub!(:file?).with('script/spec').and_return false
|
46
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return true
|
47
|
+
ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
|
48
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{bundle exec rspec}}.and_return mocked_process
|
49
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "runs script/spec when script/spec can be found" do
|
53
|
+
File.should_receive(:file?).with('script/spec').and_return true
|
54
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{script/spec}}.and_return mocked_process
|
55
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "runs spec when script/spec cannot be found" do
|
59
|
+
File.stub!(:file?).with('script/spec').and_return false
|
60
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x !~ %r{script/spec}}.and_return mocked_process
|
61
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
62
|
+
end
|
63
|
+
|
64
|
+
it "uses no -O when no opts where found" do
|
65
|
+
File.stub!(:file?).with('spec/spec.opts').and_return false
|
66
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x !~ %r{spec/spec.opts}}.and_return mocked_process
|
67
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
68
|
+
end
|
69
|
+
|
70
|
+
it "uses -O spec/spec.opts when found (with script/spec)" do
|
71
|
+
File.stub!(:file?).with('script/spec').and_return true
|
72
|
+
File.stub!(:file?).with('spec/spec.opts').and_return true
|
73
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+-O spec/spec.opts}}.and_return mocked_process
|
74
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
75
|
+
end
|
76
|
+
|
77
|
+
it "uses -O spec/parallel_spec.opts when found (with script/spec)" do
|
78
|
+
File.stub!(:file?).with('script/spec').and_return true
|
79
|
+
File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
|
80
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+-O spec/parallel_spec.opts}}.and_return mocked_process
|
81
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
82
|
+
end
|
83
|
+
|
84
|
+
it "uses -O spec/parallel_spec.opts with rspec1" do
|
85
|
+
File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
|
86
|
+
|
87
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return true
|
88
|
+
ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
|
89
|
+
|
90
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{spec\s+ -O spec/parallel_spec.opts}}.and_return mocked_process
|
91
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
92
|
+
end
|
93
|
+
|
94
|
+
it "uses inline options with rspec2" do
|
95
|
+
File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
|
96
|
+
File.should_receive(:read).with('spec/parallel_spec.opts').and_return "--foo\n--bar\n"
|
97
|
+
|
98
|
+
ParallelSpecs.stub!(:bundler_enabled?).and_return true
|
99
|
+
ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
|
100
|
+
|
101
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{rspec\s+ --foo --bar}}.and_return mocked_process
|
102
|
+
ParallelSpecs.run_tests(['xxx'],1,'')
|
103
|
+
end
|
104
|
+
|
105
|
+
it "uses options passed in" do
|
106
|
+
ParallelSpecs.should_receive(:open).with{|x,y| x =~ %r{rspec -f n}}.and_return mocked_process
|
107
|
+
ParallelSpecs.run_tests(['xxx'],1,'-f n')
|
108
|
+
end
|
109
|
+
|
110
|
+
it "returns the output" do
|
111
|
+
io = open('spec/spec_helper.rb')
|
112
|
+
ParallelSpecs.stub!(:print)
|
113
|
+
ParallelSpecs.should_receive(:open).and_return io
|
114
|
+
ParallelSpecs.run_tests(['xxx'],1,'')[:stdout].should =~ /\$LOAD_PATH << File/
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe :find_results do
|
119
|
+
it "finds multiple results in spec output" do
|
120
|
+
output = <<EOF
|
121
|
+
....F...
|
122
|
+
..
|
123
|
+
failute fsddsfsd
|
124
|
+
...
|
125
|
+
ff.**..
|
126
|
+
0 examples, 0 failures, 0 pending
|
127
|
+
ff.**..
|
128
|
+
1 example, 1 failure, 1 pending
|
129
|
+
EOF
|
130
|
+
|
131
|
+
ParallelSpecs.find_results(output).should == ['0 examples, 0 failures, 0 pending','1 example, 1 failure, 1 pending']
|
132
|
+
end
|
133
|
+
|
134
|
+
it "is robust against scrambeled output" do
|
135
|
+
output = <<EOF
|
136
|
+
....F...
|
137
|
+
..
|
138
|
+
failute fsddsfsd
|
139
|
+
...
|
140
|
+
ff.**..
|
141
|
+
0 exFampl*es, 0 failures, 0 pend.ing
|
142
|
+
ff.**..
|
143
|
+
1 exampF.les, 1 failures, 1 pend.ing
|
144
|
+
EOF
|
145
|
+
|
146
|
+
ParallelSpecs.find_results(output).should == ['0 examples, 0 failures, 0 pending','1 examples, 1 failures, 1 pending']
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe ParallelTests do
|
4
|
+
test_tests_in_groups(ParallelTests, 'test', '_test.rb')
|
5
|
+
|
6
|
+
describe :parse_rake_args do
|
7
|
+
it "should return the count" do
|
8
|
+
args = {:count => 2}
|
9
|
+
ParallelTests.parse_rake_args(args).should == [2, '', ""]
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should default to the prefix" do
|
13
|
+
args = {:count => "models"}
|
14
|
+
ParallelTests.parse_rake_args(args).should == [Parallel.processor_count, "models", ""]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return the count and prefix" do
|
18
|
+
args = {:count => 2, :path_prefix => "models"}
|
19
|
+
ParallelTests.parse_rake_args(args).should == [2, "models", ""]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return the count, prefix, and options" do
|
23
|
+
args = {:count => 2, :path_prefix => "plain", :options => "-p default" }
|
24
|
+
ParallelTests.parse_rake_args(args).should == [2, "plain", "-p default"]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe :run_tests do
|
29
|
+
it "uses TEST_ENV_NUMBER=blank when called for process 0" do
|
30
|
+
ParallelTests.should_receive(:open).with{|x,y|x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
|
31
|
+
ParallelTests.run_tests(['xxx'],0,'')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "uses TEST_ENV_NUMBER=2 when called for process 1" do
|
35
|
+
ParallelTests.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
|
36
|
+
ParallelTests.run_tests(['xxx'],1,'')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "uses options" do
|
40
|
+
ParallelTests.should_receive(:open).with{|x,y| x=~ %r{ruby -Itest -v}}.and_return mocked_process
|
41
|
+
ParallelTests.run_tests(['xxx'],1,'-v')
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns the output" do
|
45
|
+
io = open('spec/spec_helper.rb')
|
46
|
+
ParallelTests.stub!(:print)
|
47
|
+
ParallelTests.should_receive(:open).and_return io
|
48
|
+
ParallelTests.run_tests(['xxx'],1,'')[:stdout].should =~ /\$LOAD_PATH << File/
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe :test_in_groups do
|
53
|
+
it "does not sort when passed false do_sort option" do
|
54
|
+
ParallelTests.should_not_receive(:smallest_first)
|
55
|
+
ParallelTests.tests_in_groups [], 1, :no_sort => true
|
56
|
+
end
|
57
|
+
|
58
|
+
it "does sort when not passed do_sort option" do
|
59
|
+
ParallelTests.stub!(:tests_with_runtime).and_return([])
|
60
|
+
ParallelTests::Grouper.should_receive(:smallest_first).and_return([])
|
61
|
+
ParallelTests.tests_in_groups [], 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe :find_results do
|
66
|
+
it "finds multiple results in test output" do
|
67
|
+
output = <<EOF
|
68
|
+
Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
|
69
|
+
Started
|
70
|
+
..............
|
71
|
+
Finished in 0.145069 seconds.
|
72
|
+
|
73
|
+
10 tests, 20 assertions, 0 failures, 0 errors
|
74
|
+
Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
|
75
|
+
Started
|
76
|
+
..............
|
77
|
+
Finished in 0.145069 seconds.
|
78
|
+
|
79
|
+
14 tests, 20 assertions, 0 failures, 0 errors
|
80
|
+
|
81
|
+
EOF
|
82
|
+
|
83
|
+
ParallelTests.find_results(output).should == ['10 tests, 20 assertions, 0 failures, 0 errors','14 tests, 20 assertions, 0 failures, 0 errors']
|
84
|
+
end
|
85
|
+
|
86
|
+
it "is robust against scrambeled output" do
|
87
|
+
output = <<EOF
|
88
|
+
Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
|
89
|
+
Started
|
90
|
+
..............
|
91
|
+
Finished in 0.145069 seconds.
|
92
|
+
|
93
|
+
10 tests, 20 assertions, 0 failures, 0 errors
|
94
|
+
Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
|
95
|
+
Started
|
96
|
+
..............
|
97
|
+
Finished in 0.145069 seconds.
|
98
|
+
|
99
|
+
14 te.dsts, 20 assertions, 0 failures, 0 errors
|
100
|
+
EOF
|
101
|
+
|
102
|
+
ParallelTests.find_results(output).should == ['10 tests, 20 assertions, 0 failures, 0 errors','14 tedsts, 20 assertions, 0 failures, 0 errors']
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe :bundler_enabled? do
|
107
|
+
before do
|
108
|
+
Object.stub!(:const_defined?).with(:Bundler).and_return false
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should return false" do
|
112
|
+
use_temporary_directory_for do
|
113
|
+
ParallelTests.send(:bundler_enabled?).should == false
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should return true when there is a constant called Bundler" do
|
118
|
+
use_temporary_directory_for do
|
119
|
+
Object.stub!(:const_defined?).with(:Bundler).and_return true
|
120
|
+
ParallelTests.send(:bundler_enabled?).should == true
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should be true when there is a Gemfile" do
|
125
|
+
use_temporary_directory_for do
|
126
|
+
FileUtils.touch("Gemfile")
|
127
|
+
ParallelTests.send(:bundler_enabled?).should == true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should be true when there is a Gemfile in the parent directory" do
|
132
|
+
use_temporary_directory_for do
|
133
|
+
FileUtils.touch(File.join("..", "Gemfile"))
|
134
|
+
ParallelTests.send(:bundler_enabled?).should == true
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
it "has a version" do
|
140
|
+
ParallelTests::VERSION.should =~ /^\d+\.\d+\.\d+$/
|
141
|
+
end
|
142
|
+
end
|