friendlyfashion-parallel_tests 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +2 -0
  2. data/Gemfile +8 -0
  3. data/Gemfile.lock +44 -0
  4. data/Rakefile +6 -0
  5. data/Readme.md +232 -0
  6. data/ReadmeRails2.md +48 -0
  7. data/bin/parallel_cucumber +2 -0
  8. data/bin/parallel_rspec +2 -0
  9. data/bin/parallel_test +6 -0
  10. data/lib/parallel_tests.rb +30 -0
  11. data/lib/parallel_tests/cli.rb +159 -0
  12. data/lib/parallel_tests/cucumber/gherkin_listener.rb +60 -0
  13. data/lib/parallel_tests/cucumber/runner.rb +90 -0
  14. data/lib/parallel_tests/cucumber/runtime_logger.rb +58 -0
  15. data/lib/parallel_tests/grouper.rb +53 -0
  16. data/lib/parallel_tests/railtie.rb +8 -0
  17. data/lib/parallel_tests/rspec/failures_logger.rb +44 -0
  18. data/lib/parallel_tests/rspec/logger_base.rb +52 -0
  19. data/lib/parallel_tests/rspec/runner.rb +59 -0
  20. data/lib/parallel_tests/rspec/runtime_logger.rb +34 -0
  21. data/lib/parallel_tests/rspec/summary_logger.rb +19 -0
  22. data/lib/parallel_tests/tasks.rb +134 -0
  23. data/lib/parallel_tests/test/runner.rb +134 -0
  24. data/lib/parallel_tests/test/runtime_logger.rb +92 -0
  25. data/lib/parallel_tests/version.rb +3 -0
  26. data/parallel_tests.gemspec +14 -0
  27. data/spec/integration_spec.rb +244 -0
  28. data/spec/parallel_tests/cli_spec.rb +36 -0
  29. data/spec/parallel_tests/cucumber/gherkin_listener_spec.rb +48 -0
  30. data/spec/parallel_tests/cucumber/runner_spec.rb +173 -0
  31. data/spec/parallel_tests/grouper_spec.rb +52 -0
  32. data/spec/parallel_tests/rspec/failure_logger_spec.rb +82 -0
  33. data/spec/parallel_tests/rspec/runner_spec.rb +178 -0
  34. data/spec/parallel_tests/rspec/runtime_logger_spec.rb +76 -0
  35. data/spec/parallel_tests/rspec/summary_logger_spec.rb +37 -0
  36. data/spec/parallel_tests/tasks_spec.rb +151 -0
  37. data/spec/parallel_tests/test/runner_spec.rb +273 -0
  38. data/spec/parallel_tests/test/runtime_logger_spec.rb +84 -0
  39. data/spec/parallel_tests_spec.rb +73 -0
  40. data/spec/spec_helper.rb +151 -0
  41. metadata +109 -0
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require 'parallel_tests/cli'
3
+
4
+ describe ParallelTest::CLI do
5
+ describe ".parse_options" do
6
+ let(:defaults){ {:files => []} }
7
+
8
+ def call(*args)
9
+ ParallelTest::CLI.send(:parse_options!, *args)
10
+ end
11
+
12
+ it "parses regular count" do
13
+ call(["-n3"]).should == defaults.merge(:count => 3)
14
+ end
15
+
16
+ it "parses count 0 as non-parallel" do
17
+ call(["-n0"]).should == defaults.merge(:non_parallel => true)
18
+ end
19
+
20
+ it "parses non-parallel as non-parallel" do
21
+ call(["--non-parallel"]).should == defaults.merge(:non_parallel => true)
22
+ end
23
+ end
24
+
25
+ describe ".final_fail_message" do
26
+ it 'returns a plain fail message if colors are nor supported' do
27
+ ParallelTest::CLI.should_receive(:use_colors?).and_return false
28
+ ParallelTest::CLI.send(:final_fail_message, "Test").should == "Tests Failed"
29
+ end
30
+
31
+ it 'returns a colorized fail message if colors are supported' do
32
+ ParallelTest::CLI.should_receive(:use_colors?).and_return true
33
+ ParallelTest::CLI.send(:final_fail_message, "Test").should == "\e[31mTests Failed\e[0m"
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,48 @@
1
+ require 'parallel_tests/cucumber/gherkin_listener'
2
+
3
+ describe ParallelTests::Cucumber::GherkinListener do
4
+ describe :collect do
5
+ before(:each) do
6
+ @listener = ParallelTests::Cucumber::GherkinListener.new
7
+ @listener.uri("feature_file")
8
+ end
9
+
10
+ it "returns steps count" do
11
+ 3.times {@listener.step(nil)}
12
+ @listener.collect.should == {"feature_file" => 3}
13
+ end
14
+
15
+ it "counts background steps separately" do
16
+ @listener.background("background")
17
+ 5.times {@listener.step(nil)}
18
+ @listener.collect.should == {"feature_file" => 0}
19
+
20
+ @listener.scenario("scenario")
21
+ 2.times {@listener.step(nil)}
22
+ @listener.collect.should == {"feature_file" => 2}
23
+
24
+ @listener.scenario("scenario")
25
+ @listener.collect.should == {"feature_file" => 2}
26
+
27
+ @listener.eof
28
+ @listener.collect.should == {"feature_file" => 12}
29
+ end
30
+
31
+ it "counts scenario outlines steps separately" do
32
+ @listener.scenario_outline("outline")
33
+ 5.times {@listener.step(nil)}
34
+ @listener.collect.should == {"feature_file" => 0}
35
+
36
+ @listener.scenario("scenario")
37
+ 2.times {@listener.step(nil)}
38
+ @listener.collect.should == {"feature_file" => 2}
39
+
40
+ @listener.scenario("scenario")
41
+ @listener.collect.should == {"feature_file" => 2}
42
+
43
+ 3.times {@listener.examples}
44
+ @listener.eof
45
+ @listener.collect.should == {"feature_file" => 17}
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,173 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelTests::Cucumber do
4
+ test_tests_in_groups(ParallelTests::Cucumber::Runner, 'features', ".feature")
5
+
6
+ describe :run_tests do
7
+ before do
8
+ ParallelTests.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
+ def call(*args)
14
+ ParallelTests::Cucumber::Runner.run_tests(*args)
15
+ end
16
+
17
+ it "uses TEST_ENV_NUMBER=blank when called for process 0" do
18
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
19
+ call(['xxx'],0,{})
20
+ end
21
+
22
+ it "uses TEST_ENV_NUMBER=2 when called for process 1" do
23
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
24
+ call(['xxx'],1,{})
25
+ end
26
+
27
+ it "returns the output" do
28
+ io = open('spec/spec_helper.rb')
29
+ $stdout.stub!(:print)
30
+ ParallelTests::Cucumber::Runner.should_receive(:open).and_return io
31
+ call(['xxx'],1,{})[:stdout].should =~ /\$LOAD_PATH << File/
32
+ end
33
+
34
+ it "runs bundle exec cucumber when on bundler 0.9" do
35
+ ParallelTests.stub!(:bundler_enabled?).and_return true
36
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{bundle exec cucumber}}.and_return mocked_process
37
+ call(['xxx'],1,{})
38
+ end
39
+
40
+ it "runs script/cucumber when script/cucumber is found" do
41
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber}}.and_return mocked_process
42
+ call(['xxx'],1,{})
43
+ end
44
+
45
+ it "runs cucumber by default" do
46
+ File.stub!(:file?).with('script/cucumber').and_return false
47
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x !~ %r{(script/cucumber)|(bundle exec cucumber)}}.and_return mocked_process
48
+ call(['xxx'],1,{})
49
+ end
50
+
51
+ it "uses options passed in" do
52
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* -p default}}.and_return mocked_process
53
+ call(['xxx'],1,:test_options => '-p default')
54
+ end
55
+
56
+ context "with parallel profile in config/cucumber.yml" do
57
+ before do
58
+ file_contents = 'parallel: -f progress'
59
+ Dir.stub(:glob).and_return ['config/cucumber.yml']
60
+ File.stub(:read).with('config/cucumber.yml').and_return file_contents
61
+ end
62
+
63
+ it "uses parallel profile" do
64
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* foo bar --profile parallel xxx}}.and_return mocked_process
65
+ call(['xxx'],1, :test_options => 'foo bar')
66
+ end
67
+
68
+ it "uses given profile via --profile" do
69
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* --profile foo xxx$}}.and_return mocked_process
70
+ call(['xxx'],1, :test_options => '--profile foo')
71
+ end
72
+
73
+ it "uses given profile via -p" do
74
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* -p foo xxx$}}.and_return mocked_process
75
+ call(['xxx'],1, :test_options => '-p foo')
76
+ end
77
+ end
78
+
79
+ it "does not use parallel profile if config/cucumber.yml does not contain it" do
80
+ file_contents = 'blob: -f progress'
81
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .* foo bar}}.and_return mocked_process
82
+ Dir.should_receive(:glob).and_return ['config/cucumber.yml']
83
+ File.should_receive(:read).with('config/cucumber.yml').and_return file_contents
84
+ call(['xxx'],1,:test_options => 'foo bar')
85
+ end
86
+
87
+ it "does not use the parallel profile if config/cucumber.yml does not exist" do
88
+ ParallelTests::Cucumber::Runner.should_receive(:open).with{|x,y| x =~ %r{script/cucumber .*}}.and_return mocked_process
89
+ Dir.should_receive(:glob).and_return []
90
+ call(['xxx'],1,{})
91
+ end
92
+ end
93
+
94
+ describe :line_is_result? do
95
+ it "should match lines with only one scenario" do
96
+ line = "1 scenario (1 failed)"
97
+ ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
98
+ end
99
+
100
+ it "should match lines with multiple scenarios" do
101
+ line = "2 scenarios (1 failed, 1 passed)"
102
+ ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
103
+ end
104
+
105
+ it "should match lines with only one step" do
106
+ line = "1 step (1 failed)"
107
+ ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
108
+ end
109
+
110
+ it "should match lines with multiple steps" do
111
+ line = "5 steps (1 failed, 4 passed)"
112
+ ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
113
+ end
114
+
115
+ it "should not match other lines" do
116
+ line = ' And I should have "2" emails # features/step_definitions/user_steps.rb:25'
117
+ ParallelTests::Cucumber::Runner.line_is_result?(line).should be_false
118
+ end
119
+ end
120
+
121
+ describe :find_results do
122
+ it "finds multiple results in test output" do
123
+ output = <<EOF
124
+ And I should not see "/en/" # features/step_definitions/webrat_steps.rb:87
125
+
126
+ 7 scenarios (3 failed, 4 passed)
127
+ 33 steps (3 failed, 2 skipped, 28 passed)
128
+ /apps/rs/features/signup.feature:2
129
+ Given I am on "/" # features/step_definitions/common_steps.rb:12
130
+ When I click "register" # features/step_definitions/common_steps.rb:6
131
+ And I should have "2" emails # features/step_definitions/user_steps.rb:25
132
+
133
+ 4 scenarios (4 passed)
134
+ 40 steps (40 passed)
135
+
136
+ And I should not see "foo" # features/step_definitions/webrat_steps.rb:87
137
+
138
+ 1 scenario (1 passed)
139
+ 1 step (1 passed)
140
+
141
+ EOF
142
+ ParallelTests::Cucumber::Runner.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)", "1 scenario (1 passed)", "1 step (1 passed)"]
143
+ end
144
+ end
145
+
146
+ describe :summarize_results do
147
+ def call(*args)
148
+ ParallelTests::Cucumber::Runner.summarize_results(*args)
149
+ end
150
+
151
+ it "sums up results for scenarios and steps separately from each other" do
152
+ results = ["7 scenarios (3 failed, 4 passed)", "33 steps (3 failed, 2 skipped, 28 passed)", "4 scenarios (4 passed)",
153
+ "40 steps (40 passed)", "1 scenario (1 passed)", "1 step (1 passed)"]
154
+ call(results).should == "12 scenarios (3 failed, 9 passed)\n74 steps (3 failed, 2 skipped, 69 passed)"
155
+ end
156
+
157
+ it "adds same results with plurals" do
158
+ results = ["1 scenario (1 passed)", "2 steps (2 passed)",
159
+ "2 scenarios (2 passed)", "7 steps (7 passed)"]
160
+ call(results).should == "3 scenarios (3 passed)\n9 steps (9 passed)"
161
+ end
162
+
163
+ it "adds non-similar results" do
164
+ results = ["1 scenario (1 passed)", "1 step (1 passed)",
165
+ "2 scenarios (1 failed, 1 pending)", "2 steps (1 failed, 1 pending)"]
166
+ call(results).should == "3 scenarios (1 failed, 1 pending, 1 passed)\n3 steps (1 failed, 1 pending, 1 passed)"
167
+ end
168
+
169
+ it "does not pluralize 1" do
170
+ call(["1 scenario (1 passed)", "1 step (1 passed)"]).should == "1 scenario (1 passed)\n1 step (1 passed)"
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'parallel_tests/grouper'
3
+ require 'tmpdir'
4
+
5
+ describe ParallelTests::Grouper do
6
+ describe :by_steps do
7
+ def write(file, content)
8
+ File.open(file,'w'){|f| f.write content }
9
+ end
10
+
11
+ it "sorts features by steps" do
12
+ tmpdir = nil
13
+ result = Dir.mktmpdir do |dir|
14
+ tmpdir = dir
15
+ write("#{dir}/a.feature", "Feature: xxx\n Scenario: xxx\n Given something")
16
+ write("#{dir}/b.feature", "Feature: xxx\n Scenario: xxx\n Given something\n Scenario: yyy\n Given something")
17
+ write("#{dir}/c.feature", "Feature: xxx\n Scenario: xxx\n Given something")
18
+ ParallelTests::Grouper.by_steps(["#{dir}/a.feature", "#{dir}/b.feature", "#{dir}/c.feature"],2)
19
+ end
20
+
21
+ # testing inside mktmpdir is always green
22
+ result.should =~ [
23
+ ["#{tmpdir}/a.feature", "#{tmpdir}/c.feature"],
24
+ ["#{tmpdir}/b.feature"]
25
+ ]
26
+ end
27
+ end
28
+
29
+ describe :in_even_groups_by_size do
30
+ let(:files_with_size){ {"1" => 1, "2" => 2, "3" => 3, "4" => 4, "5" => 5} }
31
+
32
+ def call(num_groups)
33
+ ParallelTests::Grouper.in_even_groups_by_size(files_with_size, num_groups)
34
+ end
35
+
36
+ it "groups 1 by 1 for same groups as size" do
37
+ call(5).should == [["5"], ["4"], ["3"], ["2"], ["1"]]
38
+ end
39
+
40
+ it "groups into even groups" do
41
+ call(2).should == [["1", "2", "5"], ["3", "4"]]
42
+ end
43
+
44
+ it "groups into a single group" do
45
+ call(1).should == [["1", "2", "3", "4", "5"]]
46
+ end
47
+
48
+ it "adds empty groups if there are more groups than feature files" do
49
+ call(6).should == [["5"], ["4"], ["3"], ["2"], ["1"], []]
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelTests::RSpec::FailuresLogger do
4
+ def silence_warnings
5
+ old_verbose, $VERBOSE = $VERBOSE, nil
6
+ yield
7
+ ensure
8
+ $VERBOSE = old_verbose
9
+ end
10
+
11
+ before do
12
+ @output = OutputLogger.new([])
13
+ @example1 = mock( 'example', :location => "#{Dir.pwd}/spec/path/to/example:123", :full_description => 'should do stuff', :description => 'd' )
14
+ @example2 = mock( 'example', :location => "#{Dir.pwd}/spec/path/to/example2:456", :full_description => 'should do other stuff', :description => 'd')
15
+ @exception1 = mock( :to_s => 'exception', :backtrace => [ '/path/to/error/line:33' ] )
16
+ @failure1 = mock( 'example', :location => "#{Dir.pwd}/example:123", :header => 'header', :exception => @exception1 )
17
+ @logger = ParallelTests::RSpec::FailuresLogger.new(@output)
18
+ end
19
+
20
+ after do
21
+ silence_warnings{ ParallelTests::RSpec::LoggerBase::RSPEC_1 = false }
22
+ end
23
+
24
+ def clean_output
25
+ @output.output.join("\n").gsub(/\e\[\d+m/,'')
26
+ end
27
+
28
+ it "should produce a list of command lines for failing examples" do
29
+ @logger.example_failed @example1
30
+ @logger.example_failed @example2
31
+
32
+ @logger.dump_failures
33
+ @logger.dump_summary(1,2,3,4)
34
+
35
+ clean_output.should =~ /^rspec .*? should do stuff/
36
+ clean_output.should =~ /^rspec .*? should do other stuff/
37
+ end
38
+
39
+ it "should invoke spec for rspec 1" do
40
+ silence_warnings{ ParallelTests::RSpec::LoggerBase::RSPEC_1 = true }
41
+ ParallelTests.stub!(:bundler_enabled?).and_return true
42
+ ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
43
+ @logger.example_failed @example1
44
+
45
+ @logger.dump_failures
46
+ @logger.dump_summary(1,2,3,4)
47
+
48
+ clean_output.should =~ /^bundle exec spec/
49
+ end
50
+
51
+ it "should invoke rspec for rspec 2" do
52
+ ParallelTests.stub!(:bundler_enabled?).and_return true
53
+ ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
54
+ @logger.example_failed @example1
55
+
56
+ @logger.dump_failures
57
+ @logger.dump_summary(1,2,3,4)
58
+
59
+ clean_output.should =~ /^rspec/
60
+ end
61
+
62
+ it "should return relative paths" do
63
+ @logger.example_failed @example1
64
+ @logger.example_failed @example2
65
+
66
+ @logger.dump_failures
67
+ @logger.dump_summary(1,2,3,4)
68
+
69
+ clean_output.should =~ %r(\./spec/path/to/example:123)
70
+ clean_output.should =~ %r(\./spec/path/to/example2:456)
71
+ end
72
+
73
+
74
+ # should not longer be a problem since its using native rspec methods
75
+ xit "should not log examples without location" do
76
+ example = mock('example', :location => 'bla', :full_description => 'before :all')
77
+ @logger.example_failed example
78
+ @logger.dump_failures
79
+ @logger.dump_summary(1,2,3,4)
80
+ clean_output.should == ''
81
+ end
82
+ end
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelTests::RSpec::Runner do
4
+ test_tests_in_groups(ParallelTests::RSpec::Runner, '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
+ File.stub!(:file?).with('.rspec_parallel').and_return false
12
+ ParallelTests.stub!(:bundler_enabled?).and_return false
13
+ end
14
+
15
+ def call(*args)
16
+ ParallelTests::RSpec::Runner.run_tests(*args)
17
+ end
18
+
19
+ it "uses TEST_ENV_NUMBER=blank when called for process 0" do
20
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y|x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
21
+ call(['xxx'], 0, {})
22
+ end
23
+
24
+ it "uses TEST_ENV_NUMBER=2 when called for process 1" do
25
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
26
+ call(['xxx'],1,{})
27
+ end
28
+
29
+ it "runs with color when called from cmdline" do
30
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/ --tty /}.and_return mocked_process
31
+ $stdout.should_receive(:tty?).and_return true
32
+ call(['xxx'],1,{})
33
+ end
34
+
35
+ it "runs without color when not called from cmdline" do
36
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ / --tty /}.and_return mocked_process
37
+ $stdout.should_receive(:tty?).and_return false
38
+ call(['xxx'],1,{})
39
+ end
40
+
41
+ it "runs with color for rspec 1 when called for the cmdline" do
42
+ File.should_receive(:file?).with('script/spec').and_return true
43
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x=~/ RSPEC_COLOR=1 /}.and_return mocked_process
44
+ $stdout.should_receive(:tty?).and_return true
45
+ call(['xxx'],1,{})
46
+ end
47
+
48
+ it "runs without color for rspec 1 when not called for the cmdline" do
49
+ File.should_receive(:file?).with('script/spec').and_return true
50
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ / RSPEC_COLOR=1 /}.and_return mocked_process
51
+ $stdout.should_receive(:tty?).and_return false
52
+ call(['xxx'],1,{})
53
+ end
54
+
55
+ it "run bundle exec spec when on bundler rspec 1" do
56
+ File.stub!(:file?).with('script/spec').and_return false
57
+ ParallelTests.stub!(:bundler_enabled?).and_return true
58
+ ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
59
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{bundle exec spec}}.and_return mocked_process
60
+ call(['xxx'],1,{})
61
+ end
62
+
63
+ it "run bundle exec rspec when on bundler rspec 2" do
64
+ File.stub!(:file?).with('script/spec').and_return false
65
+ ParallelTests.stub!(:bundler_enabled?).and_return true
66
+ ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
67
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{bundle exec rspec}}.and_return mocked_process
68
+ call(['xxx'],1,{})
69
+ end
70
+
71
+ it "runs script/spec when script/spec can be found" do
72
+ File.should_receive(:file?).with('script/spec').and_return true
73
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec}}.and_return mocked_process
74
+ call(['xxx'],1,{})
75
+ end
76
+
77
+ it "runs spec when script/spec cannot be found" do
78
+ File.stub!(:file?).with('script/spec').and_return false
79
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ %r{script/spec}}.and_return mocked_process
80
+ call(['xxx'],1,{})
81
+ end
82
+
83
+ it "uses no -O when no opts where found" do
84
+ File.stub!(:file?).with('spec/spec.opts').and_return false
85
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x !~ %r{spec/spec.opts}}.and_return mocked_process
86
+ call(['xxx'],1,{})
87
+ end
88
+
89
+ it "uses -O spec/spec.opts when found (with script/spec)" do
90
+ File.stub!(:file?).with('script/spec').and_return true
91
+ File.stub!(:file?).with('spec/spec.opts').and_return true
92
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+ -O spec/spec.opts}}.and_return mocked_process
93
+ call(['xxx'],1,{})
94
+ end
95
+
96
+ it "uses -O spec/parallel_spec.opts when found (with script/spec)" do
97
+ File.stub!(:file?).with('script/spec').and_return true
98
+ File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
99
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+ -O spec/parallel_spec.opts}}.and_return mocked_process
100
+ call(['xxx'],1,{})
101
+ end
102
+
103
+ it "uses -O .rspec_parallel when found (with script/spec)" do
104
+ File.stub!(:file?).with('script/spec').and_return true
105
+ File.should_receive(:file?).with('.rspec_parallel').and_return true
106
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{script/spec\s+ -O .rspec_parallel}}.and_return mocked_process
107
+ call(['xxx'],1,{})
108
+ end
109
+
110
+ it "uses -O spec/parallel_spec.opts with rspec1" do
111
+ File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
112
+
113
+ ParallelTests.stub!(:bundler_enabled?).and_return true
114
+ ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
115
+
116
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{spec\s+ -O spec/parallel_spec.opts}}.and_return mocked_process
117
+ call(['xxx'],1,{})
118
+ end
119
+
120
+ it "uses -O spec/parallel_spec.opts with rspec2" do
121
+ File.should_receive(:file?).with('spec/parallel_spec.opts').and_return true
122
+
123
+ ParallelTests.stub!(:bundler_enabled?).and_return true
124
+ ParallelTests::RSpec::Runner.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.4.2"
125
+
126
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{rspec\s+ --color --tty -O spec/parallel_spec.opts}}.and_return mocked_process
127
+ call(['xxx'],1,{})
128
+ end
129
+
130
+ it "uses options passed in" do
131
+ ParallelTests::RSpec::Runner.should_receive(:open).with{|x,y| x =~ %r{rspec -f n}}.and_return mocked_process
132
+ call(['xxx'],1, :test_options => '-f n')
133
+ end
134
+
135
+ it "returns the output" do
136
+ io = open('spec/spec_helper.rb')
137
+ $stdout.stub!(:print)
138
+ ParallelTests::RSpec::Runner.should_receive(:open).and_return io
139
+ call(['xxx'],1,{})[:stdout].should =~ /\$LOAD_PATH << File/
140
+ end
141
+ end
142
+
143
+ describe :find_results do
144
+ def call(*args)
145
+ ParallelTests::RSpec::Runner.find_results(*args)
146
+ end
147
+
148
+ it "finds multiple results in spec output" do
149
+ output = "
150
+ ....F...
151
+ ..
152
+ failute fsddsfsd
153
+ ...
154
+ ff.**..
155
+ 0 examples, 0 failures, 0 pending
156
+ ff.**..
157
+ 1 example, 1 failure, 1 pending
158
+ "
159
+
160
+ call(output).should == ['0 examples, 0 failures, 0 pending','1 example, 1 failure, 1 pending']
161
+ end
162
+
163
+ it "is robust against scrambeled output" do
164
+ output = "
165
+ ....F...
166
+ ..
167
+ failute fsddsfsd
168
+ ...
169
+ ff.**..
170
+ 0 exFampl*es, 0 failures, 0 pend.ing
171
+ ff.**..
172
+ 1 exampF.les, 1 failures, 1 pend.ing
173
+ "
174
+
175
+ call(output).should == ['0 examples, 0 failures, 0 pending','1 examples, 1 failures, 1 pending']
176
+ end
177
+ end
178
+ end