parallel_tests 0.6.10 → 0.6.11

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
@@ -121,7 +121,7 @@ This logger produces pasteable command-line snippets for each failed example.
121
121
 
122
122
  E.g.
123
123
 
124
- spec /path/to/my_spec.rb -e "should do something"
124
+ rspec /path/to/my_spec.rb:123 # should do something
125
125
 
126
126
  Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
127
127
 
@@ -185,6 +185,8 @@ TIPS
185
185
  - [Bundler] if you have a `Gemfile` then `bundle exec` will be used to run tests
186
186
  - [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
187
187
  - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
188
+ - [Capistrano setup](https://github.com/grosser/parallel_tests/wiki/Remotely-with-capistrano) let your tests run on a big box instead of your laptop
189
+ - [Test::Unit runtime logger](https://gist.github.com/1333414) some basic plumbing done (needs some love and a pull-request)
188
190
  - [SQL schema format] use :ruby schema format to get faster parallel:prepare`
189
191
  - `export PARALLEL_TEST_PROCESSORS=X` in your environment and parallel_tests will use this number of processors by default
190
192
  - with zsh this would be `rake "parallel:prepare[3]"`
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.10
1
+ 0.6.11
@@ -1,24 +1,43 @@
1
1
  require 'parallel_specs/spec_logger_base'
2
2
 
3
3
  class ParallelSpecs::SpecFailuresLogger < ParallelSpecs::SpecLoggerBase
4
- def initialize(options, output=nil)
5
- super
6
- @failed_examples = []
4
+ # RSpec 1: does not keep track of failures, so we do
5
+ def example_failed(example, *args)
6
+ if RSPEC_1
7
+ @failed_examples ||= []
8
+ @failed_examples << example
9
+ else
10
+ super
11
+ end
7
12
  end
8
13
 
9
- def example_failed(example, count, failure)
10
- @failed_examples << example
14
+ # RSpec 1: dumps 1 failed spec
15
+ def dump_failure(*args)
11
16
  end
12
17
 
13
- def dump_failure(*args)
18
+ # RSpec 2: dumps all failed specs
19
+ def dump_failures(*args)
20
+ end
21
+
22
+ def dump_summary(*args)
14
23
  lock_output do
15
- @failed_examples.each.with_index do | example, i |
16
- spec_file = example.location.scan(/^[^:]+/)[0]
17
- spec_file.gsub!(%r(^.*?/spec/), './spec/')
18
- @output.puts "#{ParallelSpecs.executable} #{spec_file} -e \"#{example.description}\""
24
+ if RSPEC_1
25
+ dump_commands_to_rerun_failed_examples_rspec_1
26
+ else
27
+ dump_commands_to_rerun_failed_examples
19
28
  end
20
29
  end
21
30
  @output.flush
22
31
  end
23
32
 
33
+ private
34
+
35
+ def dump_commands_to_rerun_failed_examples_rspec_1
36
+ (@failed_examples||[]).each do |example|
37
+ file, line = example.location.to_s.split(':')
38
+ next unless file and line
39
+ file.gsub!(%r(^.*?/spec/), './spec/')
40
+ @output.puts "#{ParallelSpecs.executable} #{file}:#{line} # #{example.description}"
41
+ end
42
+ end
24
43
  end
@@ -1,54 +1,30 @@
1
1
  require 'parallel_specs'
2
2
 
3
3
  begin
4
- require 'rspec/core/formatters/progress_formatter'
5
- base = RSpec::Core::Formatters::ProgressFormatter
4
+ require 'rspec/core/formatters/base_text_formatter'
5
+ base = RSpec::Core::Formatters::BaseTextFormatter
6
6
  rescue LoadError
7
- require 'spec/runner/formatter/progress_bar_formatter'
7
+ require 'spec/runner/formatter/base_text_formatter'
8
8
  base = Spec::Runner::Formatter::BaseTextFormatter
9
9
  end
10
10
  ParallelSpecs::SpecLoggerBaseBase = base
11
11
 
12
12
  class ParallelSpecs::SpecLoggerBase < ParallelSpecs::SpecLoggerBaseBase
13
- def initialize(options, output=nil)
14
- output ||= options # rspec 2 has output as first argument
13
+ RSPEC_1 = defined? Spec::Runner
15
14
 
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
15
+ def initialize(*args)
16
+ super
38
17
 
39
- def example_failed(*args)
40
- end
18
+ @output ||= args[1] || args[0] # rspec 1 has output as second argument
41
19
 
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)
20
+ if String === @output # a path ?
21
+ FileUtils.mkdir_p(File.dirname(@output))
22
+ File.open(@output, 'w'){} # overwrite previous results
23
+ @output = File.open(@output, 'a')
24
+ elsif File === @output # close and restart in append mode
25
+ @output.close
26
+ @output = File.open(@output.path, 'a')
27
+ end
52
28
  end
53
29
 
54
30
  #stolen from Rspec
@@ -1,7 +1,7 @@
1
1
  require 'parallel_specs/spec_logger_base'
2
2
 
3
3
  class ParallelSpecs::SpecRuntimeLogger < ParallelSpecs::SpecLoggerBase
4
- def initialize(options, output=nil)
4
+ def initialize(*args)
5
5
  super
6
6
  @example_times = Hash.new(0)
7
7
  end
@@ -15,6 +15,10 @@ class ParallelSpecs::SpecRuntimeLogger < ParallelSpecs::SpecLoggerBase
15
15
  @example_times[file] += Time.now - @time
16
16
  end
17
17
 
18
+ def dump_summary(*args);end
19
+ def dump_failures(*args);end
20
+ def dump_failure(*args);end
21
+
18
22
  def start_dump(*args)
19
23
  return unless ENV['TEST_ENV_NUMBER'] #only record when running in parallel
20
24
  # TODO: Figure out why sometimes time can be less than 0
@@ -1,46 +1,19 @@
1
- require 'parallel_specs/spec_logger_base'
1
+ require 'parallel_specs/spec_failures_logger'
2
2
 
3
3
  class ParallelSpecs::SpecSummaryLogger < ParallelSpecs::SpecLoggerBase
4
- def initialize(options, output=nil)
5
- super
6
- @passed_examples = []
7
- @pending_examples = []
8
- @failed_examples = []
9
- end
10
-
11
- def example_passed(example)
12
- @passed_examples << example
13
- end
14
-
15
- def example_pending(*args)
16
- @pending_examples << args
17
- end
18
-
19
- def example_failed(example, count, failure)
20
- @failed_examples << failure
21
- end
22
-
23
- def dump_summary(duration, example_count, failure_count, pending_count)
4
+ # RSpec 1: dumps 1 failed spec
5
+ def dump_failure(*args)
24
6
  lock_output do
25
- @output.puts "#{ @passed_examples.size } examples passed"
7
+ super
26
8
  end
27
9
  @output.flush
28
10
  end
29
11
 
30
- def dump_failure(*args)
12
+ # RSpec 2: dumps all failed specs
13
+ def dump_failures(*args)
31
14
  lock_output do
32
- @output.puts "#{ @failed_examples.size } examples failed:"
33
- @failed_examples.each.with_index do | failure, i |
34
- @output.puts "#{ i + 1 })"
35
- @output.puts failure.header
36
- @output.puts failure.exception.to_s
37
- failure.exception.backtrace.each do | caller |
38
- @output.puts caller
39
- end
40
- @output.puts ''
41
- end
15
+ super
42
16
  end
43
17
  @output.flush
44
18
  end
45
-
46
19
  end
@@ -139,6 +139,7 @@ class ParallelTests
139
139
  times = Hash.new(1)
140
140
  lines.each do |line|
141
141
  test, time = line.split(":")
142
+ next unless test and time
142
143
  times[File.expand_path(test)] = time.to_f
143
144
  end
144
145
  tests.sort.map{|test| [test, times[test]] }
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "parallel_tests"
8
- s.version = "0.6.10"
8
+ s.version = "0.6.11"
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 = "2011-11-08"
12
+ s.date = "2011-11-18"
13
13
  s.email = "grosser.michael@gmail.com"
14
14
  s.executables = ["parallel_cucumber", "parallel_spec", "parallel_test"]
15
15
  s.files = [
@@ -36,7 +36,9 @@ Gem::Specification.new do |s|
36
36
  "parallel_tests.gemspec",
37
37
  "spec/integration_spec.rb",
38
38
  "spec/parallel_cucumber_spec.rb",
39
+ "spec/parallel_specs/spec_failure_logger_spec.rb",
39
40
  "spec/parallel_specs/spec_runtime_logger_spec.rb",
41
+ "spec/parallel_specs/spec_summary_logger_spec.rb",
40
42
  "spec/parallel_specs_spec.rb",
41
43
  "spec/parallel_tests_spec.rb",
42
44
  "spec/spec_helper.rb"
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelSpecs::SpecFailuresLogger do
4
+ def silence_warnings
5
+ old_verbose, $VERBOSE = $VERBOSE, nil
6
+ yield
7
+ ensure
8
+ $VERBOSE = old_verbose
9
+ end
10
+
11
+ before do
12
+ @output = OutputLogger.new([])
13
+ @example1 = mock( 'example', :location => "#{Dir.pwd}/spec/path/to/example:123", :full_description => 'should do stuff', :description => 'd' )
14
+ @example2 = mock( 'example', :location => "#{Dir.pwd}/spec/path/to/example2:456", :full_description => 'should do other stuff', :description => 'd')
15
+ @exception1 = mock( :to_s => 'exception', :backtrace => [ '/path/to/error/line:33' ] )
16
+ @failure1 = mock( 'example', :location => "#{Dir.pwd}/example:123", :header => 'header', :exception => @exception1 )
17
+ @logger = ParallelSpecs::SpecFailuresLogger.new( @output )
18
+ end
19
+
20
+ after do
21
+ silence_warnings{ ParallelSpecs::SpecLoggerBase::RSPEC_1 = false }
22
+ end
23
+
24
+ def clean_output
25
+ @output.output.join("\n").gsub(/\e\[\d+m/,'')
26
+ end
27
+
28
+ it "should produce a list of command lines for failing examples" do
29
+ @logger.example_failed @example1
30
+ @logger.example_failed @example2
31
+
32
+ @logger.dump_failures
33
+ @logger.dump_summary(1,2,3,4)
34
+
35
+ clean_output.should =~ /^rspec .*? should do stuff/
36
+ clean_output.should =~ /^rspec .*? should do other stuff/
37
+ end
38
+
39
+ it "should invoke spec for rspec 1" do
40
+ silence_warnings{ ParallelSpecs::SpecLoggerBase::RSPEC_1 = true }
41
+ ParallelSpecs.stub!(:bundler_enabled?).and_return true
42
+ ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
43
+ @logger.example_failed @example1
44
+
45
+ @logger.dump_failures
46
+ @logger.dump_summary(1,2,3,4)
47
+
48
+ clean_output.should =~ /^bundle exec spec/
49
+ end
50
+
51
+ it "should invoke rspec for rspec 2" do
52
+ ParallelSpecs.stub!(:bundler_enabled?).and_return true
53
+ ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
54
+ @logger.example_failed @example1
55
+
56
+ @logger.dump_failures
57
+ @logger.dump_summary(1,2,3,4)
58
+
59
+ clean_output.should =~ /^rspec/
60
+ end
61
+
62
+ it "should return relative paths" do
63
+ @logger.example_failed @example1
64
+ @logger.example_failed @example2
65
+
66
+ @logger.dump_failures
67
+ @logger.dump_summary(1,2,3,4)
68
+
69
+ clean_output.should =~ %r(\./spec/path/to/example:123)
70
+ clean_output.should =~ %r(\./spec/path/to/example2:456)
71
+ end
72
+
73
+
74
+ # should not longer be a problem since its using native rspec methods
75
+ xit "should not log examples without location" do
76
+ example = mock('example', :location => 'bla', :full_description => 'before :all')
77
+ @logger.example_failed example
78
+ @logger.dump_failures
79
+ @logger.dump_summary(1,2,3,4)
80
+ clean_output.should == ''
81
+ end
82
+ end
@@ -19,8 +19,10 @@ describe ParallelSpecs::SpecRuntimeLogger do
19
19
  else
20
20
  ParallelSpecs::SpecRuntimeLogger.new(f)
21
21
  end
22
- logger.example_started
23
- logger.example_passed(mock(:location => "#{Dir.pwd}/spec/foo.rb:123"))
22
+
23
+ example = (mock(:location => "#{Dir.pwd}/spec/foo.rb:123"))
24
+ logger.example_started example
25
+ logger.example_passed example
24
26
  logger.start_dump
25
27
 
26
28
  #f.close
@@ -29,7 +31,7 @@ describe ParallelSpecs::SpecRuntimeLogger do
29
31
  end
30
32
 
31
33
  it "logs runtime with relative paths" do
32
- log_for_a_file.should =~ %r{^spec/foo.rb:0.\d+$}m
34
+ log_for_a_file.should =~ %r{^spec/foo.rb:[-\.e\d]+$}m
33
35
  end
34
36
 
35
37
  it "does not log if we do not run in parallel" do
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelSpecs::SpecSummaryLogger do
4
+ let(:output){ OutputLogger.new([]) }
5
+ let(:logger){ ParallelSpecs::SpecSummaryLogger.new(output) }
6
+
7
+ # TODO somehow generate a real example with an exception to test this
8
+ xit "prints failing examples" do
9
+ logger.example_failed XXX
10
+ logger.example_failed XXX
11
+ logger.dump_failures
12
+ output.output.should == [
13
+ "bundle exec rspec ./spec/path/to/example.rb:123 # should do stuff",
14
+ "bundle exec rspec ./spec/path/to/example.rb:125 # should not do stuff"
15
+ ]
16
+ end
17
+
18
+ it "does not print anything for passing examples" do
19
+ logger.example_passed mock(:location => "/my/spec/foo.rb:123")
20
+ logger.dump_failures
21
+ output.output.should == []
22
+ logger.dump_summary(1,2,3,4)
23
+ output.output.should == ["\nFinished in 1 seconds\n", "\e[31m2 examples, 3 failures, 4 pending\e[0m"]
24
+ end
25
+
26
+ it "does not print anything for pending examples" do
27
+ logger.example_pending mock(:location => "/my/spec/foo.rb:123")
28
+ logger.dump_failures
29
+ output.output.should == []
30
+ logger.dump_summary(1,2,3,4)
31
+ output.output.should == ["\nFinished in 1 seconds\n", "\e[31m2 examples, 3 failures, 4 pending\e[0m"]
32
+ end
33
+ end
@@ -162,85 +162,4 @@ EOF
162
162
  ParallelSpecs.find_results(output).should == ['0 examples, 0 failures, 0 pending','1 examples, 1 failures, 1 pending']
163
163
  end
164
164
  end
165
-
166
- context "logging" do
167
-
168
- OutputLogger = Struct.new(:output) do
169
- attr_reader :flock, :flush
170
- def puts(s)
171
- self.output << s
172
- end
173
- end
174
-
175
- before :each do
176
- @output = OutputLogger.new([])
177
- @example1 = mock( 'example', :location => '/my/spec/path/to/example:123', :description => 'should do stuff' )
178
- @example2 = mock( 'example', :location => '/my/spec/path/to/example2:456', :description => 'should do other stuff' )
179
- @exception1 = mock( :to_s => 'exception', :backtrace => [ '/path/to/error/line:33' ] )
180
- @failure1 = mock( 'example', :location => '/path/to/example:123', :header => 'header', :exception => @exception1 )
181
- end
182
-
183
- describe ParallelSpecs::SpecSummaryLogger do
184
- before :each do
185
- @logger = ParallelSpecs::SpecSummaryLogger.new( @output )
186
- end
187
-
188
- it "should print a summary of failing examples" do
189
- @logger.example_failed( nil, nil, @failure1 )
190
-
191
- @logger.dump_failure
192
-
193
- @output.output.should == ["1 examples failed:", "1)", "header", "exception", "/path/to/error/line:33", ""]
194
- end
195
- end
196
-
197
- describe ParallelSpecs::SpecFailuresLogger do
198
- before :each do
199
- @logger = ParallelSpecs::SpecFailuresLogger.new( @output )
200
- end
201
-
202
- it "should produce a list of command lines for failing examples" do
203
- @logger.example_failed( @example1, nil, nil )
204
- @logger.example_failed( @example2, nil, nil )
205
-
206
- @logger.dump_failure
207
-
208
- @output.output.size.should == 2
209
- @output.output[0].should =~ /r?spec .*? -e "should do stuff"/
210
- @output.output[1].should =~ /r?spec .*? -e "should do other stuff"/
211
- end
212
-
213
- it "should invoke spec for rspec 1" do
214
- ParallelSpecs.stub!(:bundler_enabled?).and_return true
215
- ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-1.0.2"
216
- @logger.example_failed( @example1, nil, nil )
217
-
218
- @logger.dump_failure
219
-
220
- @output.output[0].should =~ /^bundle exec spec/
221
- end
222
-
223
- it "should invoke rspec for rspec 2" do
224
- ParallelSpecs.stub!(:bundler_enabled?).and_return true
225
- ParallelSpecs.stub!(:run).with("bundle show rspec").and_return "/foo/bar/rspec-2.0.2"
226
- @logger.example_failed( @example1, nil, nil )
227
-
228
- @logger.dump_failure
229
-
230
- @output.output[0].should =~ /^bundle exec rspec/
231
- end
232
-
233
- it "should return relative paths" do
234
- @logger.example_failed( @example1, nil, nil )
235
- @logger.example_failed( @example2, nil, nil )
236
-
237
- @logger.dump_failure
238
-
239
- @output.output[0].should =~ %r(\./spec/path/to/example)
240
- @output.output[1].should =~ %r(\./spec/path/to/example2)
241
- end
242
-
243
- end
244
-
245
- end
246
165
  end
@@ -7,8 +7,16 @@ FAKE_RAILS_ROOT = '/tmp/pspecs/fixtures'
7
7
  require 'tempfile'
8
8
  require 'parallel_specs'
9
9
  require 'parallel_specs/spec_runtime_logger'
10
+ require 'parallel_specs/spec_summary_logger'
10
11
  require 'parallel_cucumber'
11
12
 
13
+ OutputLogger = Struct.new(:output) do
14
+ attr_reader :flock, :flush
15
+ def puts(s=nil)
16
+ self.output << s.to_s
17
+ end
18
+ end
19
+
12
20
  def mocked_process
13
21
  open('|cat /dev/null')
14
22
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel_tests
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.10
4
+ version: 0.6.11
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-08 00:00:00.000000000 Z
12
+ date: 2011-11-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: parallel
16
- requirement: &78420700 !ruby/object:Gem::Requirement
16
+ requirement: &84425390 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *78420700
24
+ version_requirements: *84425390
25
25
  description:
26
26
  email: grosser.michael@gmail.com
27
27
  executables:
@@ -54,7 +54,9 @@ files:
54
54
  - parallel_tests.gemspec
55
55
  - spec/integration_spec.rb
56
56
  - spec/parallel_cucumber_spec.rb
57
+ - spec/parallel_specs/spec_failure_logger_spec.rb
57
58
  - spec/parallel_specs/spec_runtime_logger_spec.rb
59
+ - spec/parallel_specs/spec_summary_logger_spec.rb
58
60
  - spec/parallel_specs_spec.rb
59
61
  - spec/parallel_tests_spec.rb
60
62
  - spec/spec_helper.rb
@@ -72,7 +74,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
72
74
  version: '0'
73
75
  segments:
74
76
  - 0
75
- hash: -622498067
77
+ hash: -300537841
76
78
  required_rubygems_version: !ruby/object:Gem::Requirement
77
79
  none: false
78
80
  requirements: