parallelized_specs 0.0.1
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 +10 -0
- data/Gemfile.lock +30 -0
- data/Rakefile +21 -0
- data/Readme.md +240 -0
- data/VERSION +1 -0
- data/bin/parallel_spec +2 -0
- data/bin/parallel_test +97 -0
- data/lib/parallel_specs/spec_error_count_logger.rb +30 -0
- data/lib/parallel_specs/spec_error_logger.rb +45 -0
- data/lib/parallel_specs/spec_failures_logger.rb +43 -0
- data/lib/parallel_specs/spec_logger_base.rb +56 -0
- data/lib/parallel_specs/spec_runtime_logger.rb +34 -0
- data/lib/parallel_specs/spec_start_finish_logger.rb +38 -0
- data/lib/parallel_specs/spec_summary_logger.rb +19 -0
- data/lib/parallel_specs.rb +52 -0
- data/lib/parallel_tests/grouper.rb +49 -0
- data/lib/parallel_tests/railtie.rb +10 -0
- data/lib/parallel_tests/runtime_logger.rb +78 -0
- data/lib/parallel_tests/tasks.rb +80 -0
- data/lib/parallel_tests.rb +163 -0
- data/lib/tasks/parallel_tests.rake +1 -0
- data/parallelized_specs.gemspec +64 -0
- data/spec/integration_spec.rb +133 -0
- data/spec/parallel_specs/spec_failure_logger_spec.rb +82 -0
- data/spec/parallel_specs/spec_runtime_logger_spec.rb +76 -0
- data/spec/parallel_specs/spec_summary_logger_spec.rb +33 -0
- data/spec/parallel_specs_spec.rb +165 -0
- data/spec/parallel_tests/runtime_logger_spec.rb +74 -0
- data/spec/parallel_tests_spec.rb +229 -0
- data/spec/spec_helper.rb +149 -0
- metadata +109 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
diff-lcs (1.1.2)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.6.3)
|
7
|
+
bundler (~> 1.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
parallel (0.5.1)
|
11
|
+
rake (0.8.7)
|
12
|
+
rspec (2.6.0)
|
13
|
+
rspec-core (~> 2.6.0)
|
14
|
+
rspec-expectations (~> 2.6.0)
|
15
|
+
rspec-mocks (~> 2.6.0)
|
16
|
+
rspec-core (2.6.4)
|
17
|
+
rspec-expectations (2.6.0)
|
18
|
+
diff-lcs (~> 1.1.2)
|
19
|
+
rspec-mocks (2.6.0)
|
20
|
+
test-unit (2.4.4)
|
21
|
+
|
22
|
+
PLATFORMS
|
23
|
+
ruby
|
24
|
+
|
25
|
+
DEPENDENCIES
|
26
|
+
jeweler
|
27
|
+
parallel
|
28
|
+
rake
|
29
|
+
rspec (>= 2.4)
|
30
|
+
test-unit
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
task :default => :spec
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
4
|
+
t.rspec_opts = '--backtrace --color'
|
5
|
+
end
|
6
|
+
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
Jeweler::Tasks.new do |gem|
|
10
|
+
gem.name = "parallelized_specs"
|
11
|
+
gem.summary = "Run rspec tests in parallel"
|
12
|
+
gem.email = "jake@instructure.com"
|
13
|
+
gem.homepage = "http://github.com/jake/#{gem.name}"
|
14
|
+
gem.authors = "Jake Sorce, Bryan Madsen"
|
15
|
+
gem.version = "0.0.1"
|
16
|
+
end
|
17
|
+
|
18
|
+
Jeweler::GemcutterTasks.new
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
data/Readme.md
ADDED
@@ -0,0 +1,240 @@
|
|
1
|
+
Speedup Test::RSpec by running parallel on multiple CPUs (or cores).<br/>
|
2
|
+
ParallelizedSpecs splits tests into even groups(by number of tests or runtime) and runs each group in a single process with its own database.
|
3
|
+
|
4
|
+
Setup for Rails
|
5
|
+
===============
|
6
|
+
## Install
|
7
|
+
### Rails 3
|
8
|
+
If you use RSpec: ensure you got >= 2.4
|
9
|
+
|
10
|
+
As gem
|
11
|
+
|
12
|
+
# add to Gemfile
|
13
|
+
gem "parallel_tests", :group => :development
|
14
|
+
|
15
|
+
OR as plugin
|
16
|
+
|
17
|
+
rails plugin install git://github.com/grosser/parallel_tests.git
|
18
|
+
|
19
|
+
# add to Gemfile
|
20
|
+
gem "parallel", :group => :development
|
21
|
+
|
22
|
+
|
23
|
+
### Rails 2
|
24
|
+
|
25
|
+
As gem
|
26
|
+
|
27
|
+
gem install parallel_tests
|
28
|
+
|
29
|
+
# add to config/environments/development.rb
|
30
|
+
config.gem "parallel_tests"
|
31
|
+
|
32
|
+
# add to Rakefile
|
33
|
+
begin; require 'parallel_tests/tasks'; rescue LoadError; end
|
34
|
+
|
35
|
+
OR as plugin
|
36
|
+
|
37
|
+
gem install parallel
|
38
|
+
|
39
|
+
# add to config/environments/development.rb
|
40
|
+
config.gem "parallel"
|
41
|
+
|
42
|
+
./script/plugin install git://github.com/grosser/parallel_tests.git
|
43
|
+
|
44
|
+
## Setup
|
45
|
+
ParallelTests uses 1 database per test-process, 2 processes will use `*_test` and `*_test2`.
|
46
|
+
|
47
|
+
|
48
|
+
### 1: Add to `config/database.yml`
|
49
|
+
test:
|
50
|
+
database: xxx_test<%= ENV['TEST_ENV_NUMBER'] %>
|
51
|
+
|
52
|
+
### 2: Create additional database(s)
|
53
|
+
rake parallel:create
|
54
|
+
|
55
|
+
### 3: Copy development schema (repeat after migrations)
|
56
|
+
rake parallel:prepare
|
57
|
+
|
58
|
+
### 4: Run!
|
59
|
+
rake parallel:test # Test::Unit
|
60
|
+
rake parallel:spec # RSpec
|
61
|
+
rake parallel:features # Cucumber
|
62
|
+
|
63
|
+
rake parallel:test[1] --> force 1 CPU --> 86 seconds
|
64
|
+
rake parallel:test --> got 2 CPUs? --> 47 seconds
|
65
|
+
rake parallel:test --> got 4 CPUs? --> 26 seconds
|
66
|
+
...
|
67
|
+
|
68
|
+
Test by pattern (e.g. use one integration server per subfolder / see if you broke any 'user'-related tests)
|
69
|
+
|
70
|
+
rake parallel:test[^unit] # everything in test/unit folder (every test file matching /^unit/)
|
71
|
+
rake parallel:test[user] # run users_controller + user_helper + user tests
|
72
|
+
rake parallel:test['user|product'] # run user and product related tests
|
73
|
+
|
74
|
+
|
75
|
+
Example output
|
76
|
+
--------------
|
77
|
+
2 processes for 210 specs, ~ 105 specs per process
|
78
|
+
... test output ...
|
79
|
+
|
80
|
+
843 examples, 0 failures, 1 pending
|
81
|
+
|
82
|
+
Took 29.925333 seconds
|
83
|
+
|
84
|
+
Loggers
|
85
|
+
===================
|
86
|
+
|
87
|
+
Even process runtimes
|
88
|
+
-----------------
|
89
|
+
|
90
|
+
Log test runtime to give each process the same runtime.
|
91
|
+
|
92
|
+
Rspec: Add to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
|
93
|
+
|
94
|
+
RSpec 1.x:
|
95
|
+
--format progress
|
96
|
+
--require parallel_specs/spec_runtime_logger
|
97
|
+
--format ParallelSpecs::SpecRuntimeLogger:tmp/parallel_profile.log
|
98
|
+
RSpec >= 2.4:
|
99
|
+
If installed as plugin: -I vendor/plugins/parallel_tests/lib
|
100
|
+
--format progress
|
101
|
+
--format ParallelSpecs::SpecRuntimeLogger --out tmp/parallel_profile.log
|
102
|
+
|
103
|
+
Test::Unit: Add to your `test_helper.rb`:
|
104
|
+
require 'parallel_tests/runtime_logger'
|
105
|
+
|
106
|
+
|
107
|
+
SpecSummaryLogger
|
108
|
+
--------------------
|
109
|
+
|
110
|
+
This logger logs the test output without the different processes overwriting each other.
|
111
|
+
|
112
|
+
Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
|
113
|
+
|
114
|
+
RSpec 1.x:
|
115
|
+
--format progress
|
116
|
+
--require parallel_specs/spec_summary_logger
|
117
|
+
--format ParallelSpecs::SpecSummaryLogger:tmp/spec_summary.log
|
118
|
+
RSpec >= 2.2:
|
119
|
+
If installed as plugin: -I vendor/plugins/parallel_tests/lib
|
120
|
+
--format progress
|
121
|
+
--format ParallelSpecs::SpecSummaryLogger --out tmp/spec_summary.log
|
122
|
+
|
123
|
+
SpecFailuresLogger
|
124
|
+
-----------------------
|
125
|
+
|
126
|
+
This logger produces pasteable command-line snippets for each failed example.
|
127
|
+
|
128
|
+
E.g.
|
129
|
+
|
130
|
+
rspec /path/to/my_spec.rb:123 # should do something
|
131
|
+
|
132
|
+
Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
|
133
|
+
|
134
|
+
RSpec 1.x:
|
135
|
+
--format progress
|
136
|
+
--require parallel_specs/spec_failures_logger
|
137
|
+
--format ParallelSpecs::SpecFailuresLogger:tmp/failing_specs.log
|
138
|
+
RSpec >= 2.4:
|
139
|
+
If installed as plugin: -I vendor/plugins/parallel_tests/lib
|
140
|
+
--format progress
|
141
|
+
--format ParallelSpecs::SpecFailuresLogger --out tmp/failing_specs.log
|
142
|
+
|
143
|
+
Setup for non-rails
|
144
|
+
===================
|
145
|
+
sudo gem install parallel_tests
|
146
|
+
# go to your project dir
|
147
|
+
parallel_test OR parallel_spec OR parallel_cucumber
|
148
|
+
# [Optional] use ENV['TEST_ENV_NUMBER'] inside your tests to select separate db/memcache/etc.
|
149
|
+
|
150
|
+
[optional] Only run selected files & folders:
|
151
|
+
|
152
|
+
parallel_test test/bar test/baz/xxx_text.rb
|
153
|
+
|
154
|
+
Options are:
|
155
|
+
|
156
|
+
-n [PROCESSES] How many processes to use, default: available CPUs
|
157
|
+
-p, --path [PATH] run tests inside this path only
|
158
|
+
--no-sort do not sort files before running them
|
159
|
+
-m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run
|
160
|
+
-r, --root [PATH] execute test commands from this path
|
161
|
+
-e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUM']
|
162
|
+
-o, --test-options '[OPTIONS]' execute test commands with those options
|
163
|
+
-t, --type [TYPE] which type of tests to run? test, spec or features
|
164
|
+
--non-parallel execute same commands but do not in parallel, needs --exec
|
165
|
+
-v, --version Show Version
|
166
|
+
-h, --help Show this.
|
167
|
+
|
168
|
+
You can run any kind of code with -e / --execute
|
169
|
+
|
170
|
+
parallel_test -n 5 -e 'ruby -e "puts %[hello from process #{ENV[:TEST_ENV_NUMBER.to_s].inspect}]"'
|
171
|
+
hello from process "2"
|
172
|
+
hello from process ""
|
173
|
+
hello from process "3"
|
174
|
+
hello from process "5"
|
175
|
+
hello from process "4"
|
176
|
+
|
177
|
+
<table>
|
178
|
+
<tr><td></td><td>1 Process</td><td>2 Processes</td><td>4 Processes</td></tr>
|
179
|
+
<tr><td>RSpec spec-suite</td><td>18s</td><td>14s</td><td>10s</td></tr>
|
180
|
+
<tr><td>Rails-ActionPack</td><td>88s</td><td>53s</td><td>44s</td></tr>
|
181
|
+
</table>
|
182
|
+
|
183
|
+
TIPS
|
184
|
+
====
|
185
|
+
- [Capybara + Selenium] add to env.rb: `Capybara.server_port = 8888 + ENV['TEST_ENV_NUMBER'].to_i`
|
186
|
+
- [RSpec] add a `spec/parallel_spec.opts` to use different options, e.g. no --drb (default: `spec/spec.opts`)
|
187
|
+
- [RSpec] if something looks fishy try to delete `script/spec`
|
188
|
+
- [RSpec] if `script/spec` is missing parallel:spec uses just `spec` (which solves some issues with double-loaded environment.rb)
|
189
|
+
- [RSpec] 'script/spec_server' or [spork](http://github.com/timcharper/spork/tree/master) do not work in parallel
|
190
|
+
- [RSpec] `./script/generate rspec` if you are running rspec from gems (this plugin uses script/spec which may fail if rspec files are outdated)
|
191
|
+
- [RSpec] remove --loadby from you spec/*.opts
|
192
|
+
- [Bundler] if you have a `Gemfile` then `bundle exec` will be used to run tests
|
193
|
+
- [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
|
194
|
+
- [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
|
195
|
+
- [Capistrano setup](https://github.com/grosser/parallel_tests/wiki/Remotely-with-capistrano) let your tests run on a big box instead of your laptop
|
196
|
+
- [SQL schema format] use :ruby schema format to get faster parallel:prepare`
|
197
|
+
- [ActiveRecord] if you do not have `db:abort_if_pending_migrations` add this to your Rakefile: `task('db:abort_if_pending_migrations'){}`
|
198
|
+
- `export PARALLEL_TEST_PROCESSORS=X` in your environment and parallel_tests will use this number of processors by default
|
199
|
+
- with zsh this would be `rake "parallel:prepare[3]"`
|
200
|
+
|
201
|
+
TODO
|
202
|
+
====
|
203
|
+
- make jRuby compatible [basics](http://yehudakatz.com/2009/07/01/new-rails-isolation-testing/)
|
204
|
+
- make windows compatible
|
205
|
+
|
206
|
+
Authors
|
207
|
+
====
|
208
|
+
inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-parallelize-your-rspec-suite)
|
209
|
+
|
210
|
+
### [Contributors](http://github.com/grosser/parallel_tests/contributors)
|
211
|
+
- [Charles Finkel](http://charlesfinkel.com/)
|
212
|
+
- [Indrek Juhkam](http://urgas.eu)
|
213
|
+
- [Jason Morrison](http://jayunit.net)
|
214
|
+
- [jinzhu](http://github.com/jinzhu)
|
215
|
+
- [Joakim Kolsjö](http://www.rubyblocks.se)
|
216
|
+
- [Kevin Scaldeferri](http://kevin.scaldeferri.com/blog/)
|
217
|
+
- [Kpumuk](http://kpumuk.info/)
|
218
|
+
- [Maksim Horbul](http://github.com/mhorbul)
|
219
|
+
- [Pivotal Labs](http://www.pivotallabs.com)
|
220
|
+
- [Rohan Deshpande](http://github.com/rdeshpande)
|
221
|
+
- [Tchandy](http://thiagopradi.net/)
|
222
|
+
- [Terence Lee](http://hone.heroku.com/)
|
223
|
+
- [Will Bryant](http://willbryant.net/)
|
224
|
+
- [Fred Wu](http://fredwu.me)
|
225
|
+
- [xxx](https://github.com/xxx)
|
226
|
+
- [Levent Ali](http://purebreeze.com/)
|
227
|
+
- [Michael Kintzer](https://github.com/rockrep)
|
228
|
+
- [nathansobo](https://github.com/nathansobo)
|
229
|
+
- [Joe Yates](http://titusd.co.uk)
|
230
|
+
- [asmega](http://www.ph-lee.com)
|
231
|
+
- [Doug Barth](https://github.com/dougbarth)
|
232
|
+
- [Geoffrey Hichborn](https://github.com/phene)
|
233
|
+
- [Trae Robrock](https://github.com/trobrock)
|
234
|
+
- [Lawrence Wang](https://github.com/levity)
|
235
|
+
- [Sean Walbran](https://github.com/seanwalbran)
|
236
|
+
|
237
|
+
[Michael Grosser](http://grosser.it)<br/>
|
238
|
+
michael@grosser.it<br/>
|
239
|
+
Hereby placed under public domain, do what you want, just do not hold me accountable...<br/>
|
240
|
+
[](https://flattr.com/submit/auto?user_id=grosser&url=https://github.com/grosser/parallel_tests&title=parallel_tests&language=en_GB&tags=github&category=software)
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
data/bin/parallel_spec
ADDED
data/bin/parallel_test
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'rubygems'
|
3
|
+
require 'optparse'
|
4
|
+
require 'parallel'
|
5
|
+
raise "please ' gem install parallel '" if Gem::Version.new(Parallel::VERSION) < Gem::Version.new('0.4.2')
|
6
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
7
|
+
require "parallel_tests"
|
8
|
+
|
9
|
+
options = {}
|
10
|
+
OptionParser.new do |opts|
|
11
|
+
opts.banner = <<BANNER
|
12
|
+
Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('', '2', '3', ...)
|
13
|
+
|
14
|
+
[optional] Only run selected files & folders:
|
15
|
+
parallel_test test/bar test/baz/xxx_text.rb
|
16
|
+
|
17
|
+
Options are:
|
18
|
+
BANNER
|
19
|
+
opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs"){|n| options[:count] = n }
|
20
|
+
opts.on("-p", '--pattern [PATTERN]', "run tests matching this pattern"){|pattern| options[:pattern] = pattern }
|
21
|
+
opts.on("--no-sort", "do not sort files before running them"){ |no_sort| options[:no_sort] = no_sort }
|
22
|
+
opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run"){ |multiply| options[:multiply] = multiply }
|
23
|
+
opts.on("-r", '--root [PATH]', "execute test commands from this path"){|path| options[:root] = path }
|
24
|
+
opts.on("-s [PATTERN]", "--single [PATTERN]", "Run all matching files in only one process") do |pattern|
|
25
|
+
options[:single_process] ||= []
|
26
|
+
options[:single_process] << /#{pattern}/
|
27
|
+
end
|
28
|
+
opts.on("-e", '--exec [COMMAND]', "execute this code parallel and with ENV['TEST_ENV_NUM']"){|path| options[:execute] = path }
|
29
|
+
opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options"){|arg| options[:test_options] = arg }
|
30
|
+
opts.on("-t", "--type [TYPE]", "which type of tests to run? test, spec or features"){|type| options[:type] = type }
|
31
|
+
opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec"){ options[:non_parallel] = true }
|
32
|
+
opts.on("--chunk-timeout [TIMEOUT]", "timeout before re-printing the output of a child-process"){|timeout| options[:chunk_timeout] = timeout.to_f }
|
33
|
+
opts.on('-v', '--version', 'Show Version'){ puts ParallelTests::VERSION; exit}
|
34
|
+
opts.on("-h", "--help", "Show this.") { puts opts; exit }
|
35
|
+
end.parse!
|
36
|
+
|
37
|
+
raise "--no-sort and --single-process are not supported" if options[:no_sort] and options[:single_process]
|
38
|
+
|
39
|
+
# get files to run from arguments
|
40
|
+
options[:files] = ARGV if ARGV.size > 0
|
41
|
+
|
42
|
+
num_processes = options[:count] || Parallel.processor_count
|
43
|
+
num_processes = num_processes * (options[:multiply] || 1)
|
44
|
+
|
45
|
+
if options[:execute]
|
46
|
+
runs = (0...num_processes).to_a
|
47
|
+
results = if options[:non_parallel]
|
48
|
+
runs.map do |i|
|
49
|
+
ParallelTests.execute_command(options[:execute], i, options)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
Parallel.map(runs, :in_processes => num_processes) do |i|
|
53
|
+
ParallelTests.execute_command(options[:execute], i, options)
|
54
|
+
end
|
55
|
+
end.flatten
|
56
|
+
abort if results.any?{|r| r[:exit_status] != 0 }
|
57
|
+
else
|
58
|
+
lib, name, task = {
|
59
|
+
'test' => ["tests", "test", "test"],
|
60
|
+
'spec' => ["specs", "spec", "spec"],
|
61
|
+
'features' => ["cucumber", "feature", "features"]
|
62
|
+
}[options[:type]||'test']
|
63
|
+
|
64
|
+
require "parallel_#{lib}"
|
65
|
+
klass = eval("Parallel#{lib.capitalize}")
|
66
|
+
|
67
|
+
start = Time.now
|
68
|
+
|
69
|
+
tests_folder = task
|
70
|
+
tests_folder = File.join(options[:root], tests_folder) unless options[:root].to_s.empty?
|
71
|
+
|
72
|
+
groups = klass.tests_in_groups(options[:files] || tests_folder, num_processes, options)
|
73
|
+
num_processes = groups.size
|
74
|
+
|
75
|
+
#adjust processes to groups
|
76
|
+
abort "no #{name}s found!" if groups.size == 0
|
77
|
+
|
78
|
+
num_tests = groups.inject(0){|sum,item| sum + item.size }
|
79
|
+
puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{num_tests / groups.size} #{name}s per process"
|
80
|
+
|
81
|
+
test_results = Parallel.map(groups, :in_processes => num_processes) do |group|
|
82
|
+
klass.run_tests(group, groups.index(group), options)
|
83
|
+
end
|
84
|
+
|
85
|
+
#parse and print results
|
86
|
+
results = klass.find_results(test_results.map{|result| result[:stdout] }*"")
|
87
|
+
puts ""
|
88
|
+
puts klass.summarize_results(results)
|
89
|
+
|
90
|
+
#report total time taken
|
91
|
+
puts ""
|
92
|
+
puts "Took #{Time.now - start} seconds"
|
93
|
+
|
94
|
+
#exit with correct status code so rake parallel:test && echo 123 works
|
95
|
+
failed = test_results.any?{|result| result[:exit_status] != 0 }
|
96
|
+
abort "#{name.capitalize}s Failed" if failed
|
97
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'parallel_specs'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_logger_base')
|
3
|
+
|
4
|
+
class ParallelSpecs::SpecErrorCountLogger < ParallelSpecs::SpecLoggerBase
|
5
|
+
def initialize(options, output=nil)
|
6
|
+
super
|
7
|
+
@passed_examples = []
|
8
|
+
@pending_examples = []
|
9
|
+
@failed_examples = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def example_passed(example)
|
13
|
+
@passed_examples << example
|
14
|
+
end
|
15
|
+
|
16
|
+
def example_pending(*args)
|
17
|
+
@pending_examples << args
|
18
|
+
end
|
19
|
+
|
20
|
+
def example_failed(example, count, failure)
|
21
|
+
@failed_examples << failure
|
22
|
+
end
|
23
|
+
|
24
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
25
|
+
lock_output do
|
26
|
+
@output.puts "#{ @failed_examples.size }"
|
27
|
+
end
|
28
|
+
@output.flush
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'parallel_specs'
|
2
|
+
require File.join(File.dirname(__FILE__), 'spec_logger_base')
|
3
|
+
|
4
|
+
class ParallelSpecs::SpecErrorLogger < ParallelSpecs::SpecLoggerBase
|
5
|
+
def initialize(options, output=nil)
|
6
|
+
super
|
7
|
+
@passed_examples = []
|
8
|
+
@pending_examples = []
|
9
|
+
@failed_examples = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def example_passed(example)
|
13
|
+
@passed_examples << example
|
14
|
+
end
|
15
|
+
|
16
|
+
def example_pending(*args)
|
17
|
+
@pending_examples << args
|
18
|
+
end
|
19
|
+
|
20
|
+
def example_failed(example, count, failure)
|
21
|
+
@failed_examples << failure
|
22
|
+
end
|
23
|
+
|
24
|
+
def dump_summary(duration, example_count, failure_count, pending_count)
|
25
|
+
lock_output do
|
26
|
+
env_test_number = ENV['TEST_ENV_NUMBER']
|
27
|
+
env_test_number = 1 if ENV['TEST_ENV_NUMBER'].blank?
|
28
|
+
@output.puts ""
|
29
|
+
@output.puts ""
|
30
|
+
@output.puts "FOR TEST EXECUTOR #{env_test_number}: #{@failed_examples.size} failed, #{@passed_examples.size} passed:"
|
31
|
+
@failed_examples.each.with_index do | failure, i |
|
32
|
+
@output.puts ""
|
33
|
+
@output.puts "#{ i + 1 })"
|
34
|
+
@output.puts failure.header
|
35
|
+
unless failure.exception.nil?
|
36
|
+
@output.puts failure.exception.to_s
|
37
|
+
failure.exception.backtrace.each do | caller |
|
38
|
+
@output.puts caller
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
@output.flush
|
44
|
+
end
|
45
|
+
end
|