phene-parallel_tests 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,212 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelTests do
4
+ test_tests_in_groups(ParallelTests, 'test', '_test.rb')
5
+
6
+ describe :parse_rake_args do
7
+ it "should return the count" do
8
+ args = {:count => 2}
9
+ ParallelTests.parse_rake_args(args).should == [2, '', ""]
10
+ end
11
+
12
+ it "should default to the prefix" do
13
+ args = {:count => "models"}
14
+ ParallelTests.parse_rake_args(args).should == [Parallel.processor_count, "models", ""]
15
+ end
16
+
17
+ it "should return the count and pattern" do
18
+ args = {:count => 2, :pattern => "models"}
19
+ ParallelTests.parse_rake_args(args).should == [2, "models", ""]
20
+ end
21
+
22
+ it "should return the count, pattern, and options" do
23
+ args = {:count => 2, :pattern => "plain", :options => "-p default" }
24
+ ParallelTests.parse_rake_args(args).should == [2, "plain", "-p default"]
25
+ end
26
+ end
27
+
28
+ describe :run_tests do
29
+ it "uses TEST_ENV_NUMBER=blank when called for process 0" do
30
+ ParallelTests.should_receive(:open).with{|x,y|x=~/TEST_ENV_NUMBER= /}.and_return mocked_process
31
+ ParallelTests.run_tests(['xxx'],0,{})
32
+ end
33
+
34
+ it "uses TEST_ENV_NUMBER=2 when called for process 1" do
35
+ ParallelTests.should_receive(:open).with{|x,y| x=~/TEST_ENV_NUMBER=2/}.and_return mocked_process
36
+ ParallelTests.run_tests(['xxx'],1,{})
37
+ end
38
+
39
+ it "uses options" do
40
+ ParallelTests.should_receive(:open).with{|x,y| x=~ %r{ruby -Itest .* - -v}}.and_return mocked_process
41
+ ParallelTests.run_tests(['xxx'],1,:test_options => '-v')
42
+ end
43
+
44
+ it "returns the output" do
45
+ io = open('spec/spec_helper.rb')
46
+ ParallelTests.stub!(:print)
47
+ ParallelTests.should_receive(:open).and_return io
48
+ ParallelTests.run_tests(['xxx'],1,{})[:stdout].should =~ /\$LOAD_PATH << File/
49
+ end
50
+ end
51
+
52
+ describe :test_in_groups do
53
+ it "does not sort when passed false do_sort option" do
54
+ ParallelTests.should_not_receive(:smallest_first)
55
+ ParallelTests.tests_in_groups [], 1, :no_sort => true
56
+ end
57
+
58
+ it "does sort when not passed do_sort option" do
59
+ ParallelTests.stub!(:tests_with_runtime).and_return([])
60
+ ParallelTests::Grouper.should_receive(:smallest_first).and_return([])
61
+ ParallelTests.tests_in_groups [], 1
62
+ end
63
+ end
64
+
65
+ describe :find_results do
66
+ it "finds multiple results in test output" do
67
+ output = <<EOF
68
+ Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
69
+ Started
70
+ ..............
71
+ Finished in 0.145069 seconds.
72
+
73
+ 10 tests, 20 assertions, 0 failures, 0 errors
74
+ Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
75
+ Started
76
+ ..............
77
+ Finished in 0.145069 seconds.
78
+
79
+ 14 tests, 20 assertions, 0 failures, 0 errors
80
+
81
+ EOF
82
+
83
+ ParallelTests.find_results(output).should == ['10 tests, 20 assertions, 0 failures, 0 errors','14 tests, 20 assertions, 0 failures, 0 errors']
84
+ end
85
+
86
+ it "is robust against scrambeled output" do
87
+ output = <<EOF
88
+ Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
89
+ Started
90
+ ..............
91
+ Finished in 0.145069 seconds.
92
+
93
+ 10 tests, 20 assertions, 0 failures, 0 errors
94
+ Loaded suite /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/rake-0.8.4/lib/rake/rake_test_loader
95
+ Started
96
+ ..............
97
+ Finished in 0.145069 seconds.
98
+
99
+ 14 te.dsts, 20 assertions, 0 failures, 0 errors
100
+ EOF
101
+
102
+ ParallelTests.find_results(output).should == ['10 tests, 20 assertions, 0 failures, 0 errors','14 tedsts, 20 assertions, 0 failures, 0 errors']
103
+ end
104
+ end
105
+
106
+ describe :bundler_enabled? do
107
+ before do
108
+ Object.stub!(:const_defined?).with(:Bundler).and_return false
109
+ end
110
+
111
+ it "should return false" do
112
+ use_temporary_directory_for do
113
+ ParallelTests.send(:bundler_enabled?).should == false
114
+ end
115
+ end
116
+
117
+ it "should return true when there is a constant called Bundler" do
118
+ use_temporary_directory_for do
119
+ Object.stub!(:const_defined?).with(:Bundler).and_return true
120
+ ParallelTests.send(:bundler_enabled?).should == true
121
+ end
122
+ end
123
+
124
+ it "should be true when there is a Gemfile" do
125
+ use_temporary_directory_for do
126
+ FileUtils.touch("Gemfile")
127
+ ParallelTests.send(:bundler_enabled?).should == true
128
+ end
129
+ end
130
+
131
+ it "should be true when there is a Gemfile in the parent directory" do
132
+ use_temporary_directory_for do
133
+ FileUtils.touch(File.join("..", "Gemfile"))
134
+ ParallelTests.send(:bundler_enabled?).should == true
135
+ end
136
+ end
137
+ end
138
+
139
+ describe :find_tests do
140
+ it "returns if root is an array" do
141
+ ParallelTests.send(:find_tests, [1]).should == [1]
142
+ end
143
+
144
+ it "finds all test files" do
145
+ begin
146
+ root = "/tmp/test-find_tests-#{rand(999)}"
147
+ `mkdir #{root}`
148
+ `mkdir #{root}/a`
149
+ `mkdir #{root}/b`
150
+ `touch #{root}/x_test.rb`
151
+ `touch #{root}/a/x_test.rb`
152
+ `touch #{root}/a/test.rb`
153
+ `touch #{root}/b/y_test.rb`
154
+ `touch #{root}/b/test.rb`
155
+ `ln -s #{root}/b #{root}/c`
156
+ `ln -s #{root}/b #{root}/a/`
157
+ ParallelTests.send(:find_tests, root).sort.should == [
158
+ "#{root}/a/b/y_test.rb",
159
+ "#{root}/a/x_test.rb",
160
+ "#{root}/b/y_test.rb",
161
+ "#{root}/c/y_test.rb",
162
+ "#{root}/x_test.rb"
163
+ ]
164
+ ensure
165
+ `rm -rf #{root}`
166
+ end
167
+ end
168
+
169
+ it "finds files by pattern" do
170
+ begin
171
+ root = "/tmp/test-find_tests-#{rand(999)}"
172
+ `mkdir #{root}`
173
+ `mkdir #{root}/a`
174
+ `touch #{root}/a/x_test.rb`
175
+ `touch #{root}/a/y_test.rb`
176
+ `touch #{root}/a/z_test.rb`
177
+ ParallelTests.send(:find_tests, root, :pattern => '^a/(y|z)_test').sort.should == [
178
+ "#{root}/a/y_test.rb",
179
+ "#{root}/a/z_test.rb",
180
+ ]
181
+ ensure
182
+ `rm -rf #{root}`
183
+ end
184
+ end
185
+ end
186
+
187
+ describe :summarize_results do
188
+ it "adds results" do
189
+ ParallelTests.summarize_results(['1 foo 3 bar','2 foo 5 bar']).should == '8 bars, 3 foos'
190
+ end
191
+
192
+ it "adds results with braces" do
193
+ ParallelTests.summarize_results(['1 foo(s) 3 bar(s)','2 foo 5 bar']).should == '8 bars, 3 foos'
194
+ end
195
+
196
+ it "adds same results with plurals" do
197
+ ParallelTests.summarize_results(['1 foo 3 bar','2 foos 5 bar']).should == '8 bars, 3 foos'
198
+ end
199
+
200
+ it "adds non-similar results" do
201
+ ParallelTests.summarize_results(['1 xxx 2 yyy','1 xxx 2 zzz']).should == '2 xxxs, 2 yyys, 2 zzzs'
202
+ end
203
+
204
+ it "does not pluralize 1" do
205
+ ParallelTests.summarize_results(['1 xxx 2 yyy']).should == '1 xxx, 2 yyys'
206
+ end
207
+ end
208
+
209
+ it "has a version" do
210
+ ParallelTests::VERSION.should =~ /^\d+\.\d+\.\d+$/
211
+ end
212
+ end
@@ -0,0 +1,115 @@
1
+ # ---- requirements
2
+ $LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
3
+ require 'rubygems'
4
+
5
+ FAKE_RAILS_ROOT = '/tmp/pspecs/fixtures'
6
+
7
+ require 'parallel_specs'
8
+ require 'parallel_cucumber'
9
+
10
+ def mocked_process
11
+ open('|cat /dev/null')
12
+ end
13
+
14
+ def size_of(group)
15
+ group.inject(0) { |sum, test| sum += File.stat(test).size }
16
+ end
17
+
18
+ # Uses /tmp/parallel_tests/application as the cwd so we can create and remove
19
+ # files as we want to. After execution it changes cwd back to the original one.
20
+ def use_temporary_directory_for
21
+ require 'fileutils'
22
+
23
+ dir = File.join("/tmp", "parallel_tests")
24
+ new_dir = File.join(dir, "application")
25
+
26
+ begin
27
+ # just in case the temporary dir already exists
28
+ FileUtils.rm_rf(dir) if File.exists?(dir)
29
+
30
+ # create the temporary directory
31
+ FileUtils.mkdir_p(new_dir)
32
+
33
+ # chdir changes cwd back to the original one after it is done
34
+ Dir.chdir(new_dir) do
35
+ yield
36
+ end
37
+ ensure
38
+ FileUtils.rm_rf(dir) if File.exists?(dir)
39
+ end
40
+ end
41
+
42
+ def test_tests_in_groups(klass, folder, suffix)
43
+ test_root = "#{FAKE_RAILS_ROOT}/#{folder}"
44
+
45
+ describe :tests_in_groups do
46
+ before :all do
47
+ system "rm -rf #{FAKE_RAILS_ROOT}; mkdir -p #{test_root}/temp"
48
+
49
+ @files = [0,1,2,3,4,5,6,7].map do |i|
50
+ size = 99
51
+ file = "#{test_root}/temp/x#{i}#{suffix}"
52
+ File.open(file, 'w') { |f| f.puts 'x' * size }
53
+ file
54
+ end
55
+
56
+ @log = klass.runtime_log
57
+ `mkdir -p #{File.dirname(@log)}`
58
+ `rm -f #{@log}`
59
+ end
60
+
61
+ after :all do
62
+ `rm -f #{klass.runtime_log}`
63
+ end
64
+
65
+ it "groups when given an array of files" do
66
+ list_of_files = Dir["#{test_root}/**/*#{suffix}"]
67
+ found = klass.with_runtime_info(list_of_files)
68
+ found.should =~ list_of_files.map{ |file| [file, File.stat(file).size]}
69
+ end
70
+
71
+ it "finds all tests" do
72
+ found = klass.tests_in_groups(test_root, 1)
73
+ all = [ Dir["#{test_root}/**/*#{suffix}"] ]
74
+ (found.flatten - all.flatten).should == []
75
+ end
76
+
77
+ it "partitions them into groups by equal size" do
78
+ groups = klass.tests_in_groups(test_root, 2)
79
+ groups.map{|g| size_of(g)}.should == [400, 400]
80
+ end
81
+
82
+ it 'should partition correctly with a group size of 4' do
83
+ groups = klass.tests_in_groups(test_root, 4)
84
+ groups.map{|g| size_of(g)}.should == [200, 200, 200, 200]
85
+ end
86
+
87
+ it 'should partition correctly with an uneven group size' do
88
+ groups = klass.tests_in_groups(test_root, 3)
89
+ groups.map{|g| size_of(g)}.should =~ [300, 300, 200]
90
+ end
91
+
92
+ it "partitions by runtime when runtime-data is available" do
93
+ klass.stub!(:puts)
94
+ File.open(@log,'w') do |f|
95
+ @files[1..-1].each{|file| f.puts "#{file}:#{@files.index(file)}"}
96
+ f.puts "#{@files[0]}:10"
97
+ end
98
+
99
+ groups = klass.tests_in_groups(test_root, 2)
100
+ groups.size.should == 2
101
+ # 10 + 5 + 3 + 1 = 19
102
+ groups[0].should == [@files[0],@files[5],@files[3],@files[1]]
103
+ # 7 + 6 + 4 + 2 = 19
104
+ groups[1].should == [@files[7],@files[6],@files[4],@files[2]]
105
+ end
106
+
107
+ it "partitions by round-robin when not sorting" do
108
+ files = ["file1.rb", "file2.rb", "file3.rb", "file4.rb"]
109
+ klass.should_receive(:find_tests).and_return(files)
110
+ groups = klass.tests_in_groups(files, 2, :no_sort => true)
111
+ groups[0].should == ["file1.rb", "file3.rb"]
112
+ groups[1].should == ["file2.rb", "file4.rb"]
113
+ end
114
+ end
115
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: phene-parallel_tests
3
+ version: !ruby/object:Gem::Version
4
+ hash: 3
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 6
9
+ - 2
10
+ version: 0.6.2
11
+ platform: ruby
12
+ authors:
13
+ - Michael Grosser
14
+ - Geoffrey Hichborn
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2011-08-14 00:00:00 Z
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: parallel
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 3
30
+ segments:
31
+ - 0
32
+ version: "0"
33
+ type: :runtime
34
+ version_requirements: *id001
35
+ description:
36
+ email: grosser.michael@gmail.com
37
+ executables:
38
+ - parallel_cucumber
39
+ - parallel_test
40
+ - parallel_spec
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - Gemfile
47
+ - Gemfile.lock
48
+ - Rakefile
49
+ - Readme.md
50
+ - VERSION
51
+ - bin/parallel_cucumber
52
+ - bin/parallel_spec
53
+ - bin/parallel_test
54
+ - lib/parallel_cucumber.rb
55
+ - lib/parallel_cucumber/runtime_logger.rb
56
+ - lib/parallel_specs.rb
57
+ - lib/parallel_specs/spec_failures_logger.rb
58
+ - lib/parallel_specs/spec_logger_base.rb
59
+ - lib/parallel_specs/spec_runtime_logger.rb
60
+ - lib/parallel_specs/spec_summary_logger.rb
61
+ - lib/parallel_tests.rb
62
+ - lib/parallel_tests/grouper.rb
63
+ - lib/parallel_tests/railtie.rb
64
+ - lib/parallel_tests/tasks.rb
65
+ - lib/tasks/parallel_tests.rake
66
+ - parallel_tests.gemspec
67
+ - spec/integration_spec.rb
68
+ - spec/parallel_cucumber_spec.rb
69
+ - spec/parallel_specs_spec.rb
70
+ - spec/parallel_tests_spec.rb
71
+ - spec/spec_helper.rb
72
+ homepage: http://github.com/grosser/parallel_tests
73
+ licenses: []
74
+
75
+ post_install_message:
76
+ rdoc_options: []
77
+
78
+ require_paths:
79
+ - lib
80
+ required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirements: []
99
+
100
+ rubyforge_project:
101
+ rubygems_version: 1.8.10
102
+ signing_key:
103
+ specification_version: 3
104
+ summary: Run tests / specs / features in parallel
105
+ test_files: []
106
+