parallel_tests 0.13.3 → 0.14.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 (33) hide show
  1. data/Gemfile +1 -0
  2. data/Gemfile.lock +8 -2
  3. data/Rakefile +5 -1
  4. data/Readme.md +5 -2
  5. data/bin/parallel_spinach +5 -0
  6. data/lib/parallel_tests.rb +40 -38
  7. data/lib/parallel_tests/cli.rb +2 -2
  8. data/lib/parallel_tests/cucumber/failures_logger.rb +2 -2
  9. data/lib/parallel_tests/cucumber/runner.rb +5 -88
  10. data/lib/parallel_tests/{cucumber → gherkin}/io.rb +1 -1
  11. data/lib/parallel_tests/{cucumber/gherkin_listener.rb → gherkin/listener.rb} +2 -2
  12. data/lib/parallel_tests/gherkin/runner.rb +102 -0
  13. data/lib/parallel_tests/{cucumber → gherkin}/runtime_logger.rb +2 -2
  14. data/lib/parallel_tests/grouper.rb +41 -41
  15. data/lib/parallel_tests/rspec/failures_logger.rb +1 -1
  16. data/lib/parallel_tests/rspec/runner.rb +50 -48
  17. data/lib/parallel_tests/spinach/runner.rb +19 -0
  18. data/lib/parallel_tests/tasks.rb +7 -3
  19. data/lib/parallel_tests/test/runner.rb +125 -123
  20. data/lib/parallel_tests/test/runtime_logger.rb +57 -53
  21. data/lib/parallel_tests/version.rb +1 -1
  22. data/parallel_tests.gemspec +2 -2
  23. data/spec/integration_spec.rb +61 -0
  24. data/spec/parallel_tests/cucumber/failure_logger_spec.rb +1 -1
  25. data/spec/parallel_tests/cucumber/runner_spec.rb +5 -172
  26. data/spec/parallel_tests/{cucumber/gherkin_listener_spec.rb → gherkin/listener_spec.rb} +3 -3
  27. data/spec/parallel_tests/gherkin/runner_behaviour.rb +177 -0
  28. data/spec/parallel_tests/rspec/{failure_logger_spec.rb → failures_logger_spec.rb} +0 -0
  29. data/spec/parallel_tests/spinach/runner_spec.rb +12 -0
  30. data/spec/parallel_tests/test/runtime_logger_spec.rb +1 -1
  31. data/spec/parallel_tests_spec.rb +2 -2
  32. data/spec/spec_helper.rb +1 -1
  33. metadata +16 -10
@@ -6,73 +6,77 @@ module ParallelTests
6
6
  class RuntimeLogger
7
7
  @@has_started = false
8
8
 
9
- def self.log(test, start_time, end_time)
10
- return if test.is_a? ::Test::Unit::TestSuite # don't log for suites-of-suites
9
+ class << self
10
+ def log(test, start_time, end_time)
11
+ return if test.is_a? ::Test::Unit::TestSuite # don't log for suites-of-suites
11
12
 
12
- if !@@has_started # make empty log file
13
- File.open(logfile, 'w'){}
14
- @@has_started = true
15
- end
13
+ if !@@has_started # make empty log file
14
+ File.open(logfile, 'w'){}
15
+ @@has_started = true
16
+ end
16
17
 
17
- locked_appending_to(logfile) do |file|
18
- file.puts(message(test, start_time, end_time))
18
+ locked_appending_to(logfile) do |file|
19
+ file.puts(message(test, start_time, end_time))
20
+ end
19
21
  end
20
- end
21
22
 
22
- def self.message(test, start_time, end_time)
23
- delta = "%.2f" % (end_time.to_f-start_time.to_f)
24
- filename = class_directory(test.class) + class_to_filename(test.class) + ".rb"
25
- "#{filename}:#{delta}"
26
- end
23
+ private
24
+
25
+ def message(test, start_time, end_time)
26
+ delta = "%.2f" % (end_time.to_f-start_time.to_f)
27
+ filename = class_directory(test.class) + class_to_filename(test.class) + ".rb"
28
+ "#{filename}:#{delta}"
29
+ end
27
30
 
28
- # Note: this is a best guess at conventional test directory structure, and may need
29
- # tweaking / post-processing to match correctly for any given project
30
- def self.class_directory(suspect)
31
- result = "test/"
31
+ # Note: this is a best guess at conventional test directory structure, and may need
32
+ # tweaking / post-processing to match correctly for any given project
33
+ def class_directory(suspect)
34
+ result = "test/"
32
35
 
33
- if defined?(Rails)
34
- result += case suspect.superclass.name
35
- when "ActionDispatch::IntegrationTest"
36
- "integration/"
37
- when "ActionDispatch::PerformanceTest"
38
- "performance/"
39
- when "ActionController::TestCase"
40
- "functional/"
41
- when "ActionView::TestCase"
42
- "unit/helpers/"
43
- else
44
- "unit/"
36
+ if defined?(Rails)
37
+ result += case suspect.superclass.name
38
+ when "ActionDispatch::IntegrationTest"
39
+ "integration/"
40
+ when "ActionDispatch::PerformanceTest"
41
+ "performance/"
42
+ when "ActionController::TestCase"
43
+ "functional/"
44
+ when "ActionView::TestCase"
45
+ "unit/helpers/"
46
+ else
47
+ "unit/"
48
+ end
45
49
  end
50
+ result
46
51
  end
47
- result
48
- end
49
52
 
50
- # based on https://github.com/grosser/single_test/blob/master/lib/single_test.rb#L117
51
- def self.class_to_filename(suspect)
52
- word = suspect.to_s.dup
53
- return word unless word.match /^[A-Z]/ and not word.match %r{/[a-z]}
53
+ # based on https://github.com/grosser/single_test/blob/master/lib/single_test.rb#L117
54
+ def class_to_filename(suspect)
55
+ word = suspect.to_s.dup
56
+ return word unless word.match /^[A-Z]/ and not word.match %r{/[a-z]}
54
57
 
55
- word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
56
- word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
57
- word.gsub!(/\:\:/, '/')
58
- word.tr!("-", "_")
59
- word.downcase!
60
- word
61
- end
58
+ word.gsub!(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
59
+ word.gsub!(/([a-z\d])([A-Z])/, '\1_\2')
60
+ word.gsub!(/\:\:/, '/')
61
+ word.tr!("-", "_")
62
+ word.downcase!
63
+ word
64
+ end
62
65
 
63
- def self.locked_appending_to(file)
64
- File.open(file, 'a') do |f|
65
- begin
66
- f.flock File::LOCK_EX
67
- yield f
68
- ensure
69
- f.flock File::LOCK_UN
66
+ def locked_appending_to(file)
67
+ File.open(file, 'a') do |f|
68
+ begin
69
+ f.flock File::LOCK_EX
70
+ yield f
71
+ ensure
72
+ f.flock File::LOCK_UN
73
+ end
70
74
  end
71
75
  end
72
- end
73
76
 
74
- def self.logfile
75
- ParallelTests::Test::Runner.runtime_log
77
+ def logfile
78
+ ParallelTests::Test::Runner.runtime_log
79
+ end
76
80
  end
77
81
  end
78
82
  end
@@ -1,3 +1,3 @@
1
1
  module ParallelTests
2
- VERSION = Version = '0.13.3'
2
+ VERSION = Version = '0.14.0'
3
3
  end
@@ -3,12 +3,12 @@ name = "parallel_tests"
3
3
  require "#{name}/version"
4
4
 
5
5
  Gem::Specification.new name, ParallelTests::VERSION do |s|
6
- s.summary = "Run Test::Unit / RSpec / Cucumber in parallel"
6
+ s.summary = "Run Test::Unit / RSpec / Cucumber / Spinach in parallel"
7
7
  s.authors = ["Michael Grosser"]
8
8
  s.email = "michael@grosser.it"
9
9
  s.homepage = "http://github.com/grosser/#{name}"
10
10
  s.files = `git ls-files`.split("\n")
11
11
  s.license = "MIT"
12
- s.executables = ["parallel_cucumber", "parallel_rspec", "parallel_test"]
12
+ s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"]
13
13
  s.add_runtime_dependency "parallel"
14
14
  end
@@ -132,6 +132,11 @@ describe 'CLI' do
132
132
  `#{bin_folder}/parallel_cucumber -v`.should == version
133
133
  end
134
134
 
135
+ it "runs through parallel_spinach" do
136
+ version = `#{executable} -v`
137
+ `#{bin_folder}/parallel_spinach -v`.should == version
138
+ end
139
+
135
140
  it "runs with --group-by found" do
136
141
  # it only tests that it does not blow up, as it did before fixing...
137
142
  write "spec/x1_spec.rb", "puts '111'"
@@ -282,4 +287,60 @@ describe 'CLI' do
282
287
  results.should include("Took")
283
288
  end
284
289
  end
290
+
291
+ context "Spinach", :fails_on_ruby_187 => true do
292
+ before do
293
+ write "features/steps/a.rb", "class A < Spinach::FeatureSteps\n Given 'I print TEST_ENV_NUMBER' do\n puts \"YOUR TEST ENV IS \#{ENV['TEST_ENV_NUMBER']}!\"\n end\n And 'I sleep a bit' do\n sleep 0.2\n end\nend"
294
+ end
295
+
296
+ it "runs tests which outputs accented characters" do
297
+ write "features/good1.feature", "Feature: a\n Scenario: xxx\n Given I print accented characters"
298
+ write "features/steps/a.rb", "#encoding: utf-8\nclass A < Spinach::FeatureSteps\nGiven 'I print accented characters' do\n puts \"I tu też\" \n end\nend"
299
+ result = run_tests "features", :type => "spinach", :add => 'features/good1.feature'#, :add => '--pattern good'
300
+ result.should include('I tu też')
301
+ end
302
+
303
+ it "passes TEST_ENV_NUMBER when running with pattern (issue #86)" do
304
+ write "features/good1.feature", "Feature: a\n Scenario: xxx\n Given I print TEST_ENV_NUMBER"
305
+ write "features/good2.feature", "Feature: a\n Scenario: xxx\n Given I print TEST_ENV_NUMBER"
306
+ write "features/b.feature", "Feature: b\n Scenario: xxx\n Given I FAIL" #Expect this not to be run
307
+ write "features/steps/a.rb", "class A < Spinach::FeatureSteps\nGiven('I print TEST_ENV_NUMBER'){ puts \"YOUR TEST ENV IS \#{ENV['TEST_ENV_NUMBER']}!\" }\nend"
308
+
309
+ result = run_tests "features", :type => "spinach", :add => '--pattern good'
310
+
311
+ result.should include('YOUR TEST ENV IS 2!')
312
+ result.should include('YOUR TEST ENV IS !')
313
+ result.should_not include('I FAIL')
314
+ end
315
+
316
+ it "writes a runtime log" do
317
+ pending 'not yet implemented -- custom runtime logging'
318
+ log = "tmp/parallel_runtime_spinach.log"
319
+ write(log, "x")
320
+
321
+ 2.times{|i|
322
+ # needs sleep so that runtime loggers dont overwrite each other initially
323
+ write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit"
324
+ }
325
+ result = run_tests "features", :type => "spinach"
326
+ read(log).gsub(/\.\d+/,'').split("\n").should =~ [
327
+ "features/good0.feature:0",
328
+ "features/good1.feature:0"
329
+ ]
330
+ end
331
+
332
+ it "runs each feature once when there are more processes then features (issue #89)" do
333
+ 2.times{|i|
334
+ write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n"
335
+ }
336
+ result = run_tests "features", :type => "spinach", :add => '-n 3'
337
+ result.scan(/YOUR TEST ENV IS \d?!/).sort.should == ["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]
338
+ end
339
+
340
+ it "runs successfully without any files" do
341
+ results = run_tests("", :type => "spinach")
342
+ results.should include("2 processes for 0 features")
343
+ results.should include("Took")
344
+ end
345
+ end
285
346
  end
@@ -1,5 +1,5 @@
1
1
  require 'spec_helper'
2
- require 'parallel_tests/cucumber/io'
2
+ require 'parallel_tests/gherkin/io'
3
3
  require 'parallel_tests/cucumber/failures_logger'
4
4
 
5
5
  describe ParallelTests::Cucumber::FailuresLogger do
@@ -1,179 +1,12 @@
1
1
  require "spec_helper"
2
+ require "parallel_tests/gherkin/runner_behaviour"
2
3
  require "parallel_tests/cucumber/runner"
3
4
 
4
- describe ParallelTests::Cucumber do
5
+ describe ParallelTests::Cucumber::Runner do
5
6
  test_tests_in_groups(ParallelTests::Cucumber::Runner, 'features', ".feature")
6
7
 
7
- describe :run_tests do
8
- before do
9
- ParallelTests.stub!(:bundler_enabled?).and_return false
10
- File.stub!(:file?).with('.bundle/environment.rb').and_return false
11
- File.stub!(:file?).with('script/cucumber').and_return true
12
- end
13
-
14
- def call(*args)
15
- ParallelTests::Cucumber::Runner.run_tests(*args)
16
- end
17
-
18
- def should_run_with(regex)
19
- ParallelTests::Test::Runner.should_receive(:execute_command).with{|a,b,c,d| a =~ regex}
20
- end
21
-
22
- it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do
23
- ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec'
24
- should_run_with /script\/custom_rspec/
25
- call(['xxx'],1,22,{})
26
- ENV.delete('PARALLEL_TESTS_EXECUTABLE')
27
- end
28
-
29
- it "runs bundle exec cucumber when on bundler 0.9" do
30
- ParallelTests.stub!(:bundler_enabled?).and_return true
31
- should_run_with %r{bundle exec cucumber}
32
- call(['xxx'],1,22,{})
33
- end
34
-
35
- it "runs script/cucumber when script/cucumber is found" do
36
- should_run_with %r{script/cucumber}
37
- call(['xxx'],1,22,{})
38
- end
39
-
40
- it "runs cucumber by default" do
41
- File.stub!(:file?).with('script/cucumber').and_return false
42
- should_run_with %r{^cucumber}
43
- call(['xxx'],1,22,{})
44
- end
45
-
46
- it "uses bin/cucumber when present" do
47
- File.stub(:exists?).with("bin/cucumber").and_return true
48
- should_run_with %r{bin/cucumber}
49
- call(['xxx'],1,22,{})
50
- end
51
-
52
- it "uses options passed in" do
53
- should_run_with %r{script/cucumber .* -p default}
54
- call(['xxx'],1,22,:test_options => '-p default')
55
- end
56
-
57
- it "sanitizes dangerous file names" do
58
- should_run_with %r{xx\\ x}
59
- call(['xx x'],1,22,{})
60
- end
61
-
62
- context "with parallel profile in config/cucumber.yml" do
63
- before do
64
- file_contents = 'parallel: -f progress'
65
- Dir.stub(:glob).and_return ['config/cucumber.yml']
66
- File.stub(:read).with('config/cucumber.yml').and_return file_contents
67
- end
68
-
69
- it "uses parallel profile" do
70
- should_run_with %r{script/cucumber .* foo bar --profile parallel xxx}
71
- call(['xxx'],1,22, :test_options => 'foo bar')
72
- end
73
-
74
- it "uses given profile via --profile" do
75
- should_run_with %r{script/cucumber .* --profile foo xxx$}
76
- call(['xxx'],1,22, :test_options => '--profile foo')
77
- end
78
-
79
- it "uses given profile via -p" do
80
- should_run_with %r{script/cucumber .* -p foo xxx$}
81
- call(['xxx'],1,22, :test_options => '-p foo')
82
- end
83
- end
84
-
85
- it "does not use parallel profile if config/cucumber.yml does not contain it" do
86
- file_contents = 'blob: -f progress'
87
- should_run_with %r{script/cucumber .* foo bar}
88
- Dir.should_receive(:glob).and_return ['config/cucumber.yml']
89
- File.should_receive(:read).with('config/cucumber.yml').and_return file_contents
90
- call(['xxx'],1,22,:test_options => 'foo bar')
91
- end
92
-
93
- it "does not use the parallel profile if config/cucumber.yml does not exist" do
94
- should_run_with %r{script/cucumber} # TODO this test looks useless...
95
- Dir.should_receive(:glob).and_return []
96
- call(['xxx'],1,22,{})
97
- end
98
- end
99
-
100
- describe :line_is_result? do
101
- it "should match lines with only one scenario" do
102
- line = "1 scenario (1 failed)"
103
- ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
104
- end
105
-
106
- it "should match lines with multiple scenarios" do
107
- line = "2 scenarios (1 failed, 1 passed)"
108
- ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
109
- end
110
-
111
- it "should match lines with only one step" do
112
- line = "1 step (1 failed)"
113
- ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
114
- end
115
-
116
- it "should match lines with multiple steps" do
117
- line = "5 steps (1 failed, 4 passed)"
118
- ParallelTests::Cucumber::Runner.line_is_result?(line).should be_true
119
- end
120
-
121
- it "should not match other lines" do
122
- line = ' And I should have "2" emails # features/step_definitions/user_steps.rb:25'
123
- ParallelTests::Cucumber::Runner.line_is_result?(line).should be_false
124
- end
125
- end
126
-
127
- describe :find_results do
128
- it "finds multiple results in test output" do
129
- output = <<EOF
130
- And I should not see "/en/" # features/step_definitions/webrat_steps.rb:87
131
-
132
- 7 scenarios (3 failed, 4 passed)
133
- 33 steps (3 failed, 2 skipped, 28 passed)
134
- /apps/rs/features/signup.feature:2
135
- Given I am on "/" # features/step_definitions/common_steps.rb:12
136
- When I click "register" # features/step_definitions/common_steps.rb:6
137
- And I should have "2" emails # features/step_definitions/user_steps.rb:25
138
-
139
- 4 scenarios (4 passed)
140
- 40 steps (40 passed)
141
-
142
- And I should not see "foo" # features/step_definitions/webrat_steps.rb:87
143
-
144
- 1 scenario (1 passed)
145
- 1 step (1 passed)
146
-
147
- EOF
148
- 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)"]
149
- end
150
- end
151
-
152
- describe :summarize_results do
153
- def call(*args)
154
- ParallelTests::Cucumber::Runner.summarize_results(*args)
155
- end
156
-
157
- it "sums up results for scenarios and steps separately from each other" do
158
- results = ["7 scenarios (3 failed, 4 passed)", "33 steps (3 failed, 2 skipped, 28 passed)", "4 scenarios (4 passed)",
159
- "40 steps (40 passed)", "1 scenario (1 passed)", "1 step (1 passed)"]
160
- call(results).should == "12 scenarios (3 failed, 9 passed)\n74 steps (3 failed, 2 skipped, 69 passed)"
161
- end
162
-
163
- it "adds same results with plurals" do
164
- results = ["1 scenario (1 passed)", "2 steps (2 passed)",
165
- "2 scenarios (2 passed)", "7 steps (7 passed)"]
166
- call(results).should == "3 scenarios (3 passed)\n9 steps (9 passed)"
167
- end
168
-
169
- it "adds non-similar results" do
170
- results = ["1 scenario (1 passed)", "1 step (1 passed)",
171
- "2 scenarios (1 failed, 1 pending)", "2 steps (1 failed, 1 pending)"]
172
- call(results).should == "3 scenarios (1 failed, 1 pending, 1 passed)\n3 steps (1 failed, 1 pending, 1 passed)"
173
- end
174
-
175
- it "does not pluralize 1" do
176
- call(["1 scenario (1 passed)", "1 step (1 passed)"]).should == "1 scenario (1 passed)\n1 step (1 passed)"
177
- end
8
+ it_should_behave_like 'gherkin runners' do
9
+ let(:runner_name) {'cucumber'}
10
+ let(:runner_class){ParallelTests::Cucumber::Runner}
178
11
  end
179
12
  end
@@ -1,9 +1,9 @@
1
- require 'parallel_tests/cucumber/gherkin_listener'
1
+ require 'parallel_tests/gherkin/listener'
2
2
 
3
- describe ParallelTests::Cucumber::GherkinListener do
3
+ describe ParallelTests::Gherkin::Listener do
4
4
  describe :collect do
5
5
  before(:each) do
6
- @listener = ParallelTests::Cucumber::GherkinListener.new
6
+ @listener = ParallelTests::Gherkin::Listener.new
7
7
  @listener.uri("feature_file")
8
8
  end
9
9
 
@@ -0,0 +1,177 @@
1
+ require "spec_helper"
2
+ require "parallel_tests/gherkin/runner"
3
+
4
+ shared_examples_for 'gherkin runners' do
5
+ describe :run_tests do
6
+ before do
7
+ ParallelTests.stub!(:bundler_enabled?).and_return false
8
+ File.stub!(:file?).with('.bundle/environment.rb').and_return false
9
+ File.stub!(:file?).with("script/#{runner_name}").and_return true
10
+ end
11
+
12
+ def call(*args)
13
+ runner_class().run_tests(*args)
14
+ end
15
+
16
+ def should_run_with(regex)
17
+ ParallelTests::Test::Runner.should_receive(:execute_command).with { |a, b, c, d| a =~ regex }
18
+ end
19
+
20
+ it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do
21
+ ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec'
22
+ should_run_with /script\/custom_rspec/
23
+ call(['xxx'], 1, 22, {})
24
+ ENV.delete('PARALLEL_TESTS_EXECUTABLE')
25
+ end
26
+
27
+ it "runs bundle exec {runner_name} when on bundler 0.9" do
28
+ ParallelTests.stub!(:bundler_enabled?).and_return true
29
+ should_run_with %r{bundle exec #{runner_name}}
30
+ call(['xxx'], 1, 22, {})
31
+ end
32
+
33
+ it "runs script/{runner_name} when script/{runner_name} is found" do
34
+ should_run_with %r{script/#{runner_name}}
35
+ call(['xxx'], 1, 22, {})
36
+ end
37
+
38
+ it "runs {runner_name} by default" do
39
+ File.stub!(:file?).with("script/#{runner_name}").and_return false
40
+ should_run_with %r{^#{runner_name}}
41
+ call(['xxx'], 1, 22, {})
42
+ end
43
+
44
+ it "uses bin/{runner_name} when present" do
45
+ File.stub(:exists?).with("bin/#{runner_name}").and_return true
46
+ should_run_with %r{bin/#{runner_name}}
47
+ call(['xxx'], 1, 22, {})
48
+ end
49
+
50
+ it "uses options passed in" do
51
+ should_run_with %r{script/#{runner_name} .* -p default}
52
+ call(['xxx'], 1, 22, :test_options => '-p default')
53
+ end
54
+
55
+ it "sanitizes dangerous file runner_names" do
56
+ should_run_with %r{xx\\ x}
57
+ call(['xx x'], 1, 22, {})
58
+ end
59
+
60
+ context "with parallel profile in config/{runner_name}.yml" do
61
+ before do
62
+ file_contents = 'parallel: -f progress'
63
+ Dir.stub(:glob).and_return ["config/#{runner_name}.yml"]
64
+ File.stub(:read).with("config/#{runner_name}.yml").and_return file_contents
65
+ end
66
+
67
+ it "uses parallel profile" do
68
+ should_run_with %r{script/#{runner_name} .* foo bar --profile parallel xxx}
69
+ call(['xxx'], 1, 22, :test_options => 'foo bar')
70
+ end
71
+
72
+ it "uses given profile via --profile" do
73
+ should_run_with %r{script/#{runner_name} .* --profile foo xxx$}
74
+ call(['xxx'], 1, 22, :test_options => '--profile foo')
75
+ end
76
+
77
+ it "uses given profile via -p" do
78
+ should_run_with %r{script/#{runner_name} .* -p foo xxx$}
79
+ call(['xxx'], 1, 22, :test_options => '-p foo')
80
+ end
81
+ end
82
+
83
+ it "does not use parallel profile if config/{runner_name}.yml does not contain it" do
84
+ file_contents = 'blob: -f progress'
85
+ should_run_with %r{script/#{runner_name} .* foo bar}
86
+ Dir.should_receive(:glob).and_return ["config/#{runner_name}.yml"]
87
+ File.should_receive(:read).with("config/#{runner_name}.yml").and_return file_contents
88
+ call(['xxx'], 1, 22, :test_options => 'foo bar')
89
+ end
90
+
91
+ it "does not use the parallel profile if config/{runner_name}.yml does not exist" do
92
+ should_run_with %r{script/#{runner_name}} # TODO this test looks useless...
93
+ Dir.should_receive(:glob).and_return []
94
+ call(['xxx'], 1, 22, {})
95
+ end
96
+ end
97
+
98
+ describe :line_is_result? do
99
+ it "should match lines with only one scenario" do
100
+ line = "1 scenario (1 failed)"
101
+ runner_class().line_is_result?(line).should be_true
102
+ end
103
+
104
+ it "should match lines with multiple scenarios" do
105
+ line = "2 scenarios (1 failed, 1 passed)"
106
+ runner_class().line_is_result?(line).should be_true
107
+ end
108
+
109
+ it "should match lines with only one step" do
110
+ line = "1 step (1 failed)"
111
+ runner_class().line_is_result?(line).should be_true
112
+ end
113
+
114
+ it "should match lines with multiple steps" do
115
+ line = "5 steps (1 failed, 4 passed)"
116
+ runner_class().line_is_result?(line).should be_true
117
+ end
118
+
119
+ it "should not match other lines" do
120
+ line = ' And I should have "2" emails # features/step_definitions/user_steps.rb:25'
121
+ runner_class().line_is_result?(line).should be_false
122
+ end
123
+ end
124
+
125
+ describe :find_results do
126
+ it "finds multiple results in test output" do
127
+ output = <<EOF
128
+ And I should not see "/en/" # features/step_definitions/webrat_steps.rb:87
129
+
130
+ 7 scenarios (3 failed, 4 passed)
131
+ 33 steps (3 failed, 2 skipped, 28 passed)
132
+ /apps/rs/features/signup.feature:2
133
+ Given I am on "/" # features/step_definitions/common_steps.rb:12
134
+ When I click "register" # features/step_definitions/common_steps.rb:6
135
+ And I should have "2" emails # features/step_definitions/user_steps.rb:25
136
+
137
+ 4 scenarios (4 passed)
138
+ 40 steps (40 passed)
139
+
140
+ And I should not see "foo" # features/step_definitions/webrat_steps.rb:87
141
+
142
+ 1 scenario (1 passed)
143
+ 1 step (1 passed)
144
+
145
+ EOF
146
+ runner_class().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)"]
147
+ end
148
+ end
149
+
150
+ describe :summarize_results do
151
+ def call(*args)
152
+ runner_class().summarize_results(*args)
153
+ end
154
+
155
+ it "sums up results for scenarios and steps separately from each other" do
156
+ results = ["7 scenarios (3 failed, 4 passed)", "33 steps (3 failed, 2 skipped, 28 passed)", "4 scenarios (4 passed)",
157
+ "40 steps (40 passed)", "1 scenario (1 passed)", "1 step (1 passed)"]
158
+ call(results).should == "12 scenarios (3 failed, 9 passed)\n74 steps (3 failed, 2 skipped, 69 passed)"
159
+ end
160
+
161
+ it "adds same results with plurals" do
162
+ results = ["1 scenario (1 passed)", "2 steps (2 passed)",
163
+ "2 scenarios (2 passed)", "7 steps (7 passed)"]
164
+ call(results).should == "3 scenarios (3 passed)\n9 steps (9 passed)"
165
+ end
166
+
167
+ it "adds non-similar results" do
168
+ results = ["1 scenario (1 passed)", "1 step (1 passed)",
169
+ "2 scenarios (1 failed, 1 pending)", "2 steps (1 failed, 1 pending)"]
170
+ call(results).should == "3 scenarios (1 failed, 1 pending, 1 passed)\n3 steps (1 failed, 1 pending, 1 passed)"
171
+ end
172
+
173
+ it "does not pluralize 1" do
174
+ call(["1 scenario (1 passed)", "1 step (1 passed)"]).should == "1 scenario (1 passed)\n1 step (1 passed)"
175
+ end
176
+ end
177
+ end