friendlyfashion-parallel_tests 0.9.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.
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