parallel_tests 0.4.20 → 0.4.21

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/Readme.md CHANGED
@@ -1,4 +1,4 @@
1
- Speedup Test::Unit + RSpec + Cucumber by running parallel on multiple CPUs(or cores).
1
+ Speedup Test::Unit + RSpec + Cucumber by running parallel on multiple CPUs (or cores).
2
2
 
3
3
  Setup for Rails
4
4
  ===============
@@ -59,6 +59,7 @@ OR as plugin
59
59
  ...
60
60
 
61
61
  Test just a subfolder (e.g. use one integration server per subfolder)
62
+
62
63
  rake parallel:test[models]
63
64
  rake parallel:test[something/else]
64
65
 
@@ -76,10 +77,14 @@ Example output
76
77
 
77
78
  Took 29.925333 seconds
78
79
 
79
- Even process runtimes (for specs only)
80
+ Spec Loggers
81
+ ===================
82
+
83
+ Even process runtimes
80
84
  -----------------
81
85
 
82
- Log test runtime to give each process the same test runtime.<br/>
86
+ Log test runtime to give each process the same test runtime.
87
+
83
88
  Add to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
84
89
 
85
90
  RSpec 1.x:
@@ -90,6 +95,36 @@ Add to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
90
95
  --format progress
91
96
  --format ParallelSpecs::SpecRuntimeLogger --out tmp/parallel_profile.log
92
97
 
98
+ SpecSummaryLogger
99
+ --------------------
100
+
101
+ This logger stops the different processes overwriting each other's output.
102
+
103
+ Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
104
+
105
+ RSpec 1.x:
106
+ --format progress
107
+ --format ParallelSpecs::SpecSummaryLogger:tmp/spec_summary.log
108
+ RSpec >= 2.2:
109
+ --format progress
110
+ --format ParallelSpecs::SpecSummaryLogger --out tmp/spec_summary.log
111
+
112
+ SpecFailuresLogger
113
+ -----------------------
114
+
115
+ This logger produces command lines for running any failing examples.
116
+
117
+ E.g.
118
+
119
+ spec /path/to/my_spec.rb -e "should do something"
120
+
121
+ Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
122
+
123
+ RSpec 1.x:
124
+ --format ParallelSpecs::SpecFailuresLogger:tmp/failing_specs.log
125
+ RSpec >= 2.2:
126
+ --format ParallelSpecs::SpecFailuresLogger --out tmp/failing_specs.log
127
+
93
128
  Setup for non-rails
94
129
  ===================
95
130
  sudo gem install parallel_tests
@@ -98,9 +133,11 @@ Setup for non-rails
98
133
  # [Optional] use ENV['TEST_ENV_NUMBER'] inside your tests to select separate db/memcache/etc.
99
134
 
100
135
  [optional] Only run selected files & folders:
136
+
101
137
  parallel_test test/bar test/baz/xxx_text.rb
102
138
 
103
139
  Options are:
140
+
104
141
  -n [PROCESSES] How many processes to use, default: available CPUs
105
142
  -p, --path [PATH] run tests inside this path only
106
143
  --no-sort do not sort files before running them
@@ -114,6 +151,7 @@ Options are:
114
151
  -h, --help Show this.
115
152
 
116
153
  You can run any kind of code with -e / --execute
154
+
117
155
  parallel_test -n 5 -e 'ruby -e "puts %[hello from process #{ENV[:TEST_ENV_NUMBER.to_s].inspect}]"'
118
156
  hello from process "2"
119
157
  hello from process ""
@@ -169,6 +207,7 @@ inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-
169
207
  - [Levent Ali](http://purebreeze.com/)
170
208
  - [Michael Kintzer](https://github.com/rockrep)
171
209
  - [nathansobo](https://github.com/nathansobo)
210
+ - [Joe Yates](http://titusd.co.uk)
172
211
 
173
212
  [Michael Grosser](http://grosser.it)<br/>
174
213
  michael@grosser.it<br/>
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.20
1
+ 0.4.21
@@ -0,0 +1,25 @@
1
+ require 'parallel_specs'
2
+ require File.join(File.dirname(__FILE__), 'spec_logger_base')
3
+
4
+ class ParallelSpecs::SpecFailuresLogger < ParallelSpecs::SpecLoggerBase
5
+ def initialize(options, output=nil)
6
+ super
7
+ @failed_examples = []
8
+ end
9
+
10
+ def example_failed(example, count, failure)
11
+ @failed_examples << example
12
+ end
13
+
14
+ def dump_failure(*args)
15
+ lock_output do
16
+ @failed_examples.each.with_index do | example, i |
17
+ spec_file = example.location.scan(/^[^:]+/)[0]
18
+ spec_file.gsub!(%r(^.*?/spec/), './spec/')
19
+ @output.puts "#{ParallelSpecs.executable} #{spec_file} -e \"#{example.description}\""
20
+ end
21
+ end
22
+ @output.flush
23
+ end
24
+
25
+ end
@@ -0,0 +1,72 @@
1
+ require 'parallel_specs'
2
+
3
+ begin
4
+ require 'rspec/core/formatters/progress_formatter'
5
+ base = RSpec::Core::Formatters::ProgressFormatter
6
+ rescue LoadError
7
+ require 'spec/runner/formatter/progress_bar_formatter'
8
+ base = Spec::Runner::Formatter::BaseTextFormatter
9
+ end
10
+ ParallelSpecs::SpecLoggerBaseBase = base
11
+
12
+ class ParallelSpecs::SpecLoggerBase < ParallelSpecs::SpecLoggerBaseBase
13
+ def initialize(options, output=nil)
14
+ output ||= options # rspec 2 has output as first argument
15
+
16
+ if String === output
17
+ FileUtils.mkdir_p(File.dirname(output))
18
+ File.open(output, 'w'){} # overwrite previous results
19
+ @output = File.open(output, 'a')
20
+ elsif File === output
21
+ output.close # close file opened with 'w'
22
+ @output = File.open(output.path, 'a')
23
+ else
24
+ @output = output
25
+ end
26
+
27
+ @failed_examples = [] # only needed for rspec 2
28
+ end
29
+
30
+ def example_started(*args)
31
+ end
32
+
33
+ def example_passed(example)
34
+ end
35
+
36
+ def example_pending(*args)
37
+ end
38
+
39
+ def example_failed(*args)
40
+ end
41
+
42
+ def start_dump(*args)
43
+ end
44
+
45
+ def dump_summary(*args)
46
+ end
47
+
48
+ def dump_pending(*args)
49
+ end
50
+
51
+ def dump_failure(*args)
52
+ end
53
+
54
+ #stolen from Rspec
55
+ def close
56
+ @output.close if (IO === @output) & (@output != $stdout)
57
+ end
58
+
59
+ # do not let multiple processes get in each others way
60
+ def lock_output
61
+ if File === @output
62
+ begin
63
+ @output.flock File::LOCK_EX
64
+ yield
65
+ ensure
66
+ @output.flock File::LOCK_UN
67
+ end
68
+ else
69
+ yield
70
+ end
71
+ end
72
+ end
@@ -1,31 +1,10 @@
1
1
  require 'parallel_specs'
2
+ require File.join(File.dirname(__FILE__), 'spec_logger_base')
2
3
 
3
- begin
4
- require 'rspec/core/formatters/progress_formatter'
5
- base = RSpec::Core::Formatters::ProgressFormatter
6
- rescue LoadError
7
- require 'spec/runner/formatter/progress_bar_formatter'
8
- base = Spec::Runner::Formatter::BaseTextFormatter
9
- end
10
- ParallelSpecs::SpecRuntimeLoggerBase = base
11
-
12
- class ParallelSpecs::SpecRuntimeLogger < ParallelSpecs::SpecRuntimeLoggerBase
4
+ class ParallelSpecs::SpecRuntimeLogger < ParallelSpecs::SpecLoggerBase
13
5
  def initialize(options, output=nil)
14
- output ||= options # rspec 2 has output as first argument
15
-
16
- if String === output
17
- FileUtils.mkdir_p(File.dirname(output))
18
- File.open(output, 'w'){} # overwrite previous results
19
- @output = File.open(output, 'a')
20
- elsif File === output
21
- output.close # close file opened with 'w'
22
- @output = File.open(output.path, 'a')
23
- else
24
- @output = output
25
- end
26
-
6
+ super
27
7
  @example_times = Hash.new(0)
28
- @failed_examples = [] # only needed for rspec 2
29
8
  end
30
9
 
31
10
  def example_started(*args)
@@ -46,39 +25,4 @@ class ParallelSpecs::SpecRuntimeLogger < ParallelSpecs::SpecRuntimeLoggerBase
46
25
  @output.flush
47
26
  end
48
27
 
49
- # stubs so that rspec doe not crash
50
-
51
- def example_pending(*args)
52
- end
53
-
54
- def example_failed(*args)
55
- end
56
-
57
- def dump_summary(*args)
58
- end
59
-
60
- def dump_pending(*args)
61
- end
62
-
63
- def dump_failure(*args)
64
- end
65
-
66
- #stolen from Rspec
67
- def close
68
- @output.close if (IO === @output) & (@output != $stdout)
69
- end
70
-
71
- # do not let multiple processes get in each others way
72
- def lock_output
73
- if File === @output
74
- begin
75
- @output.flock File::LOCK_EX
76
- yield
77
- ensure
78
- @output.flock File::LOCK_UN
79
- end
80
- else
81
- yield
82
- end
83
- end
84
28
  end
@@ -0,0 +1,47 @@
1
+ require 'parallel_specs'
2
+ require File.join(File.dirname(__FILE__), 'spec_logger_base')
3
+
4
+ class ParallelSpecs::SpecSummaryLogger < 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 "#{ @passed_examples.size } examples passed"
27
+ end
28
+ @output.flush
29
+ end
30
+
31
+ def dump_failure(*args)
32
+ lock_output do
33
+ @output.puts "#{ @failed_examples.size } examples failed:"
34
+ @failed_examples.each.with_index do | failure, i |
35
+ @output.puts "#{ i + 1 })"
36
+ @output.puts failure.header
37
+ @output.puts failure.exception.to_s
38
+ failure.exception.backtrace.each do | caller |
39
+ @output.puts caller
40
+ end
41
+ @output.puts ''
42
+ end
43
+ end
44
+ @output.flush
45
+ end
46
+
47
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{parallel_tests}
8
- s.version = "0.4.20"
8
+ s.version = "0.4.21"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Michael Grosser"]
12
- s.date = %q{2011-06-04}
12
+ s.date = %q{2011-06-12}
13
13
  s.email = %q{grosser.michael@gmail.com}
14
14
  s.executables = ["parallel_cucumber", "parallel_spec", "parallel_test"]
15
15
  s.files = [
@@ -25,7 +25,10 @@ Gem::Specification.new do |s|
25
25
  "lib/parallel_cucumber.rb",
26
26
  "lib/parallel_cucumber/runtime_logger.rb",
27
27
  "lib/parallel_specs.rb",
28
+ "lib/parallel_specs/spec_failures_logger.rb",
29
+ "lib/parallel_specs/spec_logger_base.rb",
28
30
  "lib/parallel_specs/spec_runtime_logger.rb",
31
+ "lib/parallel_specs/spec_summary_logger.rb",
29
32
  "lib/parallel_tests.rb",
30
33
  "lib/parallel_tests/grouper.rb",
31
34
  "lib/parallel_tests/railtie.rb",
@@ -1,4 +1,7 @@
1
1
  require 'spec/spec_helper'
2
+ require 'parallel_specs/spec_runtime_logger'
3
+ require 'parallel_specs/spec_summary_logger'
4
+ require 'parallel_specs/spec_failures_logger'
2
5
 
3
6
  describe ParallelSpecs do
4
7
  test_tests_in_groups(ParallelSpecs, 'spec', '_spec.rb')
@@ -160,4 +163,103 @@ EOF
160
163
  ParallelSpecs.find_results(output).should == ['0 examples, 0 failures, 0 pending','1 examples, 1 failures, 1 pending']
161
164
  end
162
165
  end
166
+
167
+ context "logging" do
168
+
169
+ OutputLogger = Struct.new(:output) do
170
+ attr_reader :flock, :flush
171
+ def puts(s)
172
+ self.output << s
173
+ end
174
+ end
175
+
176
+ before :each do
177
+ @output = OutputLogger.new([])
178
+ @example1 = mock( 'example', :location => '/my/spec/path/to/example:123', :description => 'should do stuff' )
179
+ @example2 = mock( 'example', :location => '/my/spec/path/to/example2:456', :description => 'should do other stuff' )
180
+ @exception1 = mock( :to_s => 'exception', :backtrace => [ '/path/to/error/line:33' ] )
181
+ @failure1 = mock( 'example', :location => '/path/to/example:123', :header => 'header', :exception => @exception1 )
182
+ end
183
+
184
+ describe ParallelSpecs::SpecRuntimeLogger do
185
+ before :each do
186
+ ENV['TEST_ENV_NUMBER'] = '1'
187
+ @logger = ParallelSpecs::SpecRuntimeLogger.new( @output )
188
+ end
189
+
190
+ it "collects runtime information" do
191
+ @logger.example_started
192
+ @logger.example_passed( @example1 )
193
+
194
+ @logger.start_dump
195
+
196
+ @output.output.size.should == 1
197
+ @output.output[0].size.should == 1
198
+ @output.output[0][0].should =~ %r(/path/to/example:([\d\.e\-]+))
199
+ end
200
+ end
201
+
202
+ describe ParallelSpecs::SpecSummaryLogger do
203
+ before :each do
204
+ @logger = ParallelSpecs::SpecSummaryLogger.new( @output )
205
+ end
206
+
207
+ it "should print a summary of failing examples" do
208
+ @logger.example_failed( nil, nil, @failure1 )
209
+
210
+ @logger.dump_failure
211
+
212
+ @output.output.should == ["1 examples failed:", "1)", "header", "exception", "/path/to/error/line:33", ""]
213
+ end
214
+ end
215
+
216
+ describe ParallelSpecs::SpecFailuresLogger do
217
+ before :each do
218
+ @logger = ParallelSpecs::SpecFailuresLogger.new( @output )
219
+ end
220
+
221
+ it "should produce a list of command lines for failing examples" do
222
+ @logger.example_failed( @example1, nil, nil )
223
+ @logger.example_failed( @example2, nil, nil )
224
+
225
+ @logger.dump_failure
226
+
227
+ @output.output.size.should == 2
228
+ @output.output[0].should =~ /r?spec .*? -e "should do stuff"/
229
+ @output.output[1].should =~ /r?spec .*? -e "should do other stuff"/
230
+ end
231
+
232
+ it "should invoke spec for rspec 1" do
233
+ ParallelSpecs.stub!(:bundler_enabled?).and_return true
234
+ ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
235
+ @logger.example_failed( @example1, nil, nil )
236
+
237
+ @logger.dump_failure
238
+
239
+ @output.output[0].should =~ /^bundle exec spec/
240
+ end
241
+
242
+ it "should invoke rspec for rspec 2" do
243
+ ParallelSpecs.stub!(:bundler_enabled?).and_return true
244
+ ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
245
+ @logger.example_failed( @example1, nil, nil )
246
+
247
+ @logger.dump_failure
248
+
249
+ @output.output[0].should =~ /^bundle exec rspec/
250
+ end
251
+
252
+ it "should return relative paths" do
253
+ @logger.example_failed( @example1, nil, nil )
254
+ @logger.example_failed( @example2, nil, nil )
255
+
256
+ @logger.dump_failure
257
+
258
+ @output.output[0].should =~ %r(\./spec/path/to/example)
259
+ @output.output[1].should =~ %r(\./spec/path/to/example2)
260
+ end
261
+
262
+ end
263
+
264
+ end
163
265
  end
@@ -54,10 +54,14 @@ def test_tests_in_groups(klass, folder, suffix)
54
54
  end
55
55
 
56
56
  @log = klass.runtime_log
57
- `mkdir #{File.dirname(@log)}`
57
+ `mkdir -p #{File.dirname(@log)}`
58
58
  `rm -f #{@log}`
59
59
  end
60
60
 
61
+ after :all do
62
+ `rm -f #{klass.runtime_log}`
63
+ end
64
+
61
65
  it "groups when given an array of files" do
62
66
  list_of_files = Dir["#{test_root}/**/*#{suffix}"]
63
67
  found = klass.tests_with_runtime(list_of_files)
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_tests
3
3
  version: !ruby/object:Gem::Version
4
- hash: 39
4
+ hash: 37
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 20
10
- version: 0.4.20
9
+ - 21
10
+ version: 0.4.21
11
11
  platform: ruby
12
12
  authors:
13
13
  - Michael Grosser
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-04 00:00:00 +02:00
18
+ date: 2011-06-12 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -55,7 +55,10 @@ files:
55
55
  - lib/parallel_cucumber.rb
56
56
  - lib/parallel_cucumber/runtime_logger.rb
57
57
  - lib/parallel_specs.rb
58
+ - lib/parallel_specs/spec_failures_logger.rb
59
+ - lib/parallel_specs/spec_logger_base.rb
58
60
  - lib/parallel_specs/spec_runtime_logger.rb
61
+ - lib/parallel_specs/spec_summary_logger.rb
59
62
  - lib/parallel_tests.rb
60
63
  - lib/parallel_tests/grouper.rb
61
64
  - lib/parallel_tests/railtie.rb