parallel_tests 0.6.10 → 0.6.11

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