parallel_tests 0.13.3 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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