parallel_tests 0.6.7 → 0.6.8

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,5 +1,5 @@
1
1
  Speedup Test::Unit + RSpec + Cucumber by running parallel on multiple CPUs (or cores).<br/>
2
- ParallelTests splits tests into even groups and runs each group in a single process with its own database.
2
+ ParallelTests splits tests into even groups(by number of tests or runtime) and runs each group in a single process with its own database.
3
3
 
4
4
  Setup for Rails
5
5
  ===============
@@ -87,7 +87,7 @@ Spec Loggers
87
87
  Even process runtimes
88
88
  -----------------
89
89
 
90
- Log test runtime to give each process the same test runtime.
90
+ Log test runtime to give each process the same runtime.
91
91
 
92
92
  Add to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
93
93
 
@@ -102,7 +102,7 @@ Add to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
102
102
  SpecSummaryLogger
103
103
  --------------------
104
104
 
105
- This logger stops the different processes overwriting each other's output.
105
+ This logger logs the test output without the different processes overwriting each other.
106
106
 
107
107
  Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
108
108
 
@@ -116,7 +116,7 @@ Add the following to your `spec/parallel_spec.opts` (or `spec/spec.opts`) :
116
116
  SpecFailuresLogger
117
117
  -----------------------
118
118
 
119
- This logger produces command lines for running any failing examples.
119
+ This logger produces pasteable command-line snippets for each failed example.
120
120
 
121
121
  E.g.
122
122
 
@@ -177,6 +177,7 @@ TIPS
177
177
  - [RSpec] if `script/spec` is missing parallel:spec uses just `spec` (which solves some issues with double-loaded environment.rb)
178
178
  - [RSpec] 'script/spec_server' or [spork](http://github.com/timcharper/spork/tree/master) do not work in parallel
179
179
  - [RSpec] `./script/generate rspec` if you are running rspec from gems (this plugin uses script/spec which may fail if rspec files are outdated)
180
+ - [RSpec] remove --loadby from you spec/*.opts
180
181
  - [Bundler] if you have a `Gemfile` then `bundle exec` will be used to run tests
181
182
  - [Capybara setup](https://github.com/grosser/parallel_tests/wiki)
182
183
  - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki)
@@ -219,4 +220,5 @@ inspired by [pivotal labs](http://pivotallabs.com/users/miked/blog/articles/849-
219
220
 
220
221
  [Michael Grosser](http://grosser.it)<br/>
221
222
  michael@grosser.it<br/>
222
- Hereby placed under public domain, do what you want, just do not hold me accountable...
223
+ Hereby placed under public domain, do what you want, just do not hold me accountable...<br/>
224
+ [![Flattr](http://api.flattr.com/button/flattr-badge-large.png)](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 CHANGED
@@ -1 +1 @@
1
- 0.6.7
1
+ 0.6.8
data/bin/parallel_test CHANGED
@@ -21,6 +21,10 @@ BANNER
21
21
  opts.on("--no-sort", "do not sort files before running them"){ |no_sort| options[:no_sort] = no_sort }
22
22
  opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run"){ |multiply| options[:multiply] = multiply }
23
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
24
28
  opts.on("-e", '--exec [COMMAND]', "execute this code parallel and with ENV['TEST_ENV_NUM']"){|path| options[:execute] = path }
25
29
  opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options"){|arg| options[:test_options] = arg }
26
30
  opts.on("-t", "--type [TYPE]", "which type of tests to run? test, spec or features"){|type| options[:type] = type }
@@ -30,6 +34,8 @@ BANNER
30
34
  opts.on("-h", "--help", "Show this.") { puts opts; exit }
31
35
  end.parse!
32
36
 
37
+ raise "--no-sort and --single-process are not supported" if options[:no_sort] and options[:single_process]
38
+
33
39
  # get files to run from arguments
34
40
  options[:files] = ARGV if ARGV.size > 0
35
41
 
@@ -63,7 +69,7 @@ else
63
69
  tests_folder = task
64
70
  tests_folder = File.join(options[:root], tests_folder) unless options[:root].to_s.empty?
65
71
 
66
- groups = klass.tests_in_groups(options[:files] || tests_folder, num_processes, :no_sort => options[:no_sort], :pattern => options[:pattern])
72
+ groups = klass.tests_in_groups(options[:files] || tests_folder, num_processes, options)
67
73
  num_processes = groups.size
68
74
 
69
75
  #adjust processes to groups
@@ -1,31 +1,50 @@
1
1
  class ParallelTests
2
2
  class Grouper
3
3
  def self.in_groups(items, num_groups)
4
- [].tap do |groups|
5
- while ! items.empty?
6
- (0...num_groups).map do |group_number|
7
- groups[group_number] ||= []
8
- groups[group_number] << items.shift
9
- end
4
+ groups = Array.new(num_groups){ [] }
5
+
6
+ until items.empty?
7
+ num_groups.times do |group_number|
8
+ groups[group_number] << items.shift
10
9
  end
11
- end.map(&:sort)
10
+ end
11
+
12
+ groups.map!(&:sort!)
12
13
  end
13
14
 
14
- def self.in_even_groups_by_size(items_with_sizes, num_groups)
15
- items_with_size = smallest_first(items_with_sizes)
15
+ def self.in_even_groups_by_size(items_with_sizes, num_groups, options={})
16
16
  groups = Array.new(num_groups){{:items => [], :size => 0}}
17
- items_with_size.each do |item, size|
18
- # always add to smallest group
19
- smallest = groups.sort_by{|g| g[:size] }.first
20
- smallest[:items] << item
21
- smallest[:size] += size
17
+
18
+ # add all files that should run in a single process to one group
19
+ (options[:single_process]||[]).each do |pattern|
20
+ matched, items_with_sizes = items_with_sizes.partition{|item, size| item =~ pattern }
21
+ puts matched.inspect
22
+ smallest = smallest_group(groups)
23
+ matched.each{|item,size| add_to_group(smallest, item, size) }
24
+ end
25
+
26
+ # add all other files
27
+ smallest_first(items_with_sizes).each do |item, size|
28
+ smallest = smallest_group(groups)
29
+ add_to_group(smallest, item, size)
22
30
  end
23
31
 
24
- groups.map{|g| g[:items].sort }
32
+ groups.map!{|g| g[:items].sort }
25
33
  end
26
34
 
27
35
  def self.smallest_first(files)
28
36
  files.sort_by{|item, size| size }.reverse
29
37
  end
38
+
39
+ private
40
+
41
+ def self.smallest_group(groups)
42
+ groups.min_by{|g| g[:size] }
43
+ end
44
+
45
+ def self.add_to_group(group, item, size)
46
+ group[:items] << item
47
+ group[:size] += size
48
+ end
30
49
  end
31
50
  end
@@ -31,13 +31,12 @@ class ParallelTests
31
31
  Grouper.in_groups(tests, num_groups)
32
32
  else
33
33
  tests = with_runtime_info(tests)
34
- Grouper.in_even_groups_by_size(tests, num_groups)
34
+ Grouper.in_even_groups_by_size(tests, num_groups, options)
35
35
  end
36
36
  end
37
37
 
38
38
  def self.run_tests(test_files, process_number, options)
39
39
  require_list = test_files.map { |filename| %{"#{File.expand_path filename}"} }.join(",")
40
- test_options = "- #{options[:test_options]}" unless RUBY_VERSION > '1.9.2' # test options passing is broken on 1.9.3 see issue #64
41
40
  cmd = "ruby -Itest -e '[#{require_list}].each {|f| require f }' -- #{options[:test_options]}"
42
41
  execute_command(cmd, process_number, options)
43
42
  end
@@ -4,14 +4,14 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{parallel_tests}
8
- s.version = "0.6.7"
7
+ s.name = "parallel_tests"
8
+ s.version = "0.6.8"
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-10-05}
13
- s.email = %q{grosser.michael@gmail.com}
14
- s.executables = ["parallel_cucumber", "parallel_test", "parallel_spec"]
12
+ s.date = "2011-11-02"
13
+ s.email = "grosser.michael@gmail.com"
14
+ s.executables = ["parallel_cucumber", "parallel_spec", "parallel_test"]
15
15
  s.files = [
16
16
  "Gemfile",
17
17
  "Gemfile.lock",
@@ -40,10 +40,10 @@ Gem::Specification.new do |s|
40
40
  "spec/parallel_tests_spec.rb",
41
41
  "spec/spec_helper.rb"
42
42
  ]
43
- s.homepage = %q{http://github.com/grosser/parallel_tests}
43
+ s.homepage = "http://github.com/grosser/parallel_tests"
44
44
  s.require_paths = ["lib"]
45
- s.rubygems_version = %q{1.6.2}
46
- s.summary = %q{Run tests / specs / features in parallel}
45
+ s.rubygems_version = "1.8.10"
46
+ s.summary = "Run tests / specs / features in parallel"
47
47
 
48
48
  if s.respond_to? :specification_version then
49
49
  s.specification_version = 3
@@ -49,6 +49,13 @@ describe 'CLI' do
49
49
  $?.success?.should == true
50
50
  end
51
51
 
52
+ it "does not run any tests if there are none" do
53
+ write 'spec/xxx.rb', 'xxx'
54
+ result = run_tests
55
+ result.should include('No examples found')
56
+ result.should include('Took')
57
+ end
58
+
52
59
  it "fails when tests fail" do
53
60
  write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}'
54
61
  write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){1.should == 2}}'
@@ -71,6 +71,12 @@ describe ParallelTests do
71
71
  ParallelTests::Grouper.should_receive(:smallest_first).and_return([])
72
72
  ParallelTests.tests_in_groups [], 1
73
73
  end
74
+
75
+ it "groups by single_process pattern and then via size" do
76
+ ParallelTests.should_receive(:with_runtime_info).and_return([['aaa',5],['aaa2',5],['bbb',2],['ccc',1],['ddd',1]])
77
+ result = ParallelTests.tests_in_groups [], 3, :single_process => [/^a.a/]
78
+ result.should == [["aaa", "aaa2"], ["bbb"], ["ccc", "ddd"]]
79
+ end
74
80
  end
75
81
 
76
82
  describe :find_results do
@@ -94,7 +100,7 @@ EOF
94
100
  ParallelTests.find_results(output).should == ['10 tests, 20 assertions, 0 failures, 0 errors','14 tests, 20 assertions, 0 failures, 0 errors']
95
101
  end
96
102
 
97
- it "is robust against scrambeled output" do
103
+ it "is robust against scrambled output" do
98
104
  output = <<EOF
99
105
  Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
100
106
  Started
metadata CHANGED
@@ -1,48 +1,36 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: parallel_tests
3
- version: !ruby/object:Gem::Version
4
- hash: 9
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.8
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 6
9
- - 7
10
- version: 0.6.7
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Michael Grosser
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-10-05 00:00:00 +02:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
22
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2011-11-02 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: parallel
16
+ requirement: &76244280 !ruby/object:Gem::Requirement
23
17
  none: false
24
- requirements:
25
- - - ">="
26
- - !ruby/object:Gem::Version
27
- hash: 3
28
- segments:
29
- - 0
30
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
31
22
  type: :runtime
32
- name: parallel
33
- version_requirements: *id001
34
23
  prerelease: false
24
+ version_requirements: *76244280
35
25
  description:
36
26
  email: grosser.michael@gmail.com
37
- executables:
27
+ executables:
38
28
  - parallel_cucumber
39
- - parallel_test
40
29
  - parallel_spec
30
+ - parallel_test
41
31
  extensions: []
42
-
43
32
  extra_rdoc_files: []
44
-
45
- files:
33
+ files:
46
34
  - Gemfile
47
35
  - Gemfile.lock
48
36
  - Rakefile
@@ -69,39 +57,31 @@ files:
69
57
  - spec/parallel_specs_spec.rb
70
58
  - spec/parallel_tests_spec.rb
71
59
  - spec/spec_helper.rb
72
- has_rdoc: true
73
60
  homepage: http://github.com/grosser/parallel_tests
74
61
  licenses: []
75
-
76
62
  post_install_message:
77
63
  rdoc_options: []
78
-
79
- require_paths:
64
+ require_paths:
80
65
  - lib
81
- required_ruby_version: !ruby/object:Gem::Requirement
66
+ required_ruby_version: !ruby/object:Gem::Requirement
82
67
  none: false
83
- requirements:
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- hash: 3
87
- segments:
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ segments:
88
73
  - 0
89
- version: "0"
90
- required_rubygems_version: !ruby/object:Gem::Requirement
74
+ hash: -400446063
75
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
76
  none: false
92
- requirements:
93
- - - ">="
94
- - !ruby/object:Gem::Version
95
- hash: 3
96
- segments:
97
- - 0
98
- version: "0"
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
99
81
  requirements: []
100
-
101
82
  rubyforge_project:
102
- rubygems_version: 1.6.2
83
+ rubygems_version: 1.8.10
103
84
  signing_key:
104
85
  specification_version: 3
105
86
  summary: Run tests / specs / features in parallel
106
87
  test_files: []
107
-