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.
- data/Gemfile +1 -0
- data/Gemfile.lock +8 -2
- data/Rakefile +5 -1
- data/Readme.md +5 -2
- data/bin/parallel_spinach +5 -0
- data/lib/parallel_tests.rb +40 -38
- data/lib/parallel_tests/cli.rb +2 -2
- data/lib/parallel_tests/cucumber/failures_logger.rb +2 -2
- data/lib/parallel_tests/cucumber/runner.rb +5 -88
- data/lib/parallel_tests/{cucumber → gherkin}/io.rb +1 -1
- data/lib/parallel_tests/{cucumber/gherkin_listener.rb → gherkin/listener.rb} +2 -2
- data/lib/parallel_tests/gherkin/runner.rb +102 -0
- data/lib/parallel_tests/{cucumber → gherkin}/runtime_logger.rb +2 -2
- data/lib/parallel_tests/grouper.rb +41 -41
- data/lib/parallel_tests/rspec/failures_logger.rb +1 -1
- data/lib/parallel_tests/rspec/runner.rb +50 -48
- data/lib/parallel_tests/spinach/runner.rb +19 -0
- data/lib/parallel_tests/tasks.rb +7 -3
- data/lib/parallel_tests/test/runner.rb +125 -123
- data/lib/parallel_tests/test/runtime_logger.rb +57 -53
- data/lib/parallel_tests/version.rb +1 -1
- data/parallel_tests.gemspec +2 -2
- data/spec/integration_spec.rb +61 -0
- data/spec/parallel_tests/cucumber/failure_logger_spec.rb +1 -1
- data/spec/parallel_tests/cucumber/runner_spec.rb +5 -172
- data/spec/parallel_tests/{cucumber/gherkin_listener_spec.rb → gherkin/listener_spec.rb} +3 -3
- data/spec/parallel_tests/gherkin/runner_behaviour.rb +177 -0
- data/spec/parallel_tests/rspec/{failure_logger_spec.rb → failures_logger_spec.rb} +0 -0
- data/spec/parallel_tests/spinach/runner_spec.rb +12 -0
- data/spec/parallel_tests/test/runtime_logger_spec.rb +1 -1
- data/spec/parallel_tests_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- metadata +16 -10
@@ -6,73 +6,77 @@ module ParallelTests
|
|
6
6
|
class RuntimeLogger
|
7
7
|
@@has_started = false
|
8
8
|
|
9
|
-
|
10
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
if !@@has_started # make empty log file
|
14
|
+
File.open(logfile, 'w'){}
|
15
|
+
@@has_started = true
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
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
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
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
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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
|
-
|
75
|
-
|
77
|
+
def logfile
|
78
|
+
ParallelTests::Test::Runner.runtime_log
|
79
|
+
end
|
76
80
|
end
|
77
81
|
end
|
78
82
|
end
|
data/parallel_tests.gemspec
CHANGED
@@ -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
|
data/spec/integration_spec.rb
CHANGED
@@ -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,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
|
-
|
8
|
-
|
9
|
-
|
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/
|
1
|
+
require 'parallel_tests/gherkin/listener'
|
2
2
|
|
3
|
-
describe ParallelTests::
|
3
|
+
describe ParallelTests::Gherkin::Listener do
|
4
4
|
describe :collect do
|
5
5
|
before(:each) do
|
6
|
-
@listener = ParallelTests::
|
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
|