parallel_split_test 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/Readme.md +30 -30
- data/bin/parallel_split_test +11 -16
- data/lib/parallel_split_test/command_line.rb +46 -4
- data/lib/parallel_split_test/runner.rb +4 -12
- data/lib/parallel_split_test/version.rb +1 -1
- data/spec/parallel_split_test_spec.rb +31 -2
- metadata +3 -3
data/Gemfile.lock
CHANGED
data/Readme.md
CHANGED
@@ -10,9 +10,10 @@ Usage
|
|
10
10
|
### 1: prepare your databases
|
11
11
|
To use 1 database per test-process, add this to your `config/database.yml`<br/>
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
```Yaml
|
14
|
+
test:
|
15
|
+
database: yourproject_test<%= ENV['TEST_ENV_NUMBER'] %>
|
16
|
+
```
|
16
17
|
|
17
18
|
- `TEST_ENV_NUMBER` is '' for the first process and 2 for the 2nd, it reuses your normal test database
|
18
19
|
- Optionally install [parallel_tests](https://github.com/grosser/parallel_tests) to get database helper tasks like `rake parallel:prepare`
|
@@ -20,44 +21,43 @@ To use 1 database per test-process, add this to your `config/database.yml`<br/>
|
|
20
21
|
|
21
22
|
### 2: find a slow/big test file
|
22
23
|
|
23
|
-
|
24
|
-
|
24
|
+
```Ruby
|
25
|
+
# spec/xxx_spec.rb
|
26
|
+
require "spec_helper"
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
describe "X" do
|
29
|
+
it {sleep 5}
|
30
|
+
it {sleep 5}
|
31
|
+
it {sleep 5}
|
32
|
+
end
|
33
|
+
```
|
31
34
|
|
32
35
|
### 3: run
|
33
|
-
|
36
|
+
```Bash
|
37
|
+
parallel_split_test spec/xxx_spec.rb [regular test options]
|
38
|
+
```
|
34
39
|
|
35
40
|
Output
|
36
41
|
======
|
37
42
|
|
38
|
-
|
39
|
-
|
40
|
-
Running examples in 2 processes
|
41
|
-
.
|
42
|
-
|
43
|
-
Finished in 5 seconds
|
44
|
-
1 example, 0 failures
|
45
|
-
..
|
43
|
+
```Bash
|
44
|
+
parallel_split_test spec/xx_spec.rb
|
46
45
|
|
47
|
-
|
48
|
-
|
46
|
+
Running examples in 2 processes
|
47
|
+
.
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
Took 10.06 seconds with 2 processes
|
49
|
+
Finished in 5 seconds
|
50
|
+
1 example, 0 failures
|
51
|
+
..
|
54
52
|
|
53
|
+
Finished in 1 seconds
|
54
|
+
2 examples, 0 failures
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
Summary:
|
57
|
+
1 example, 0 failures
|
58
|
+
2 examples, 0 failures
|
59
|
+
Took 10.06 seconds with 2 processes
|
60
|
+
```
|
61
61
|
|
62
62
|
TIPS
|
63
63
|
====
|
data/bin/parallel_split_test
CHANGED
@@ -2,27 +2,22 @@
|
|
2
2
|
require "optparse"
|
3
3
|
$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
if ARGV.include?("-v") or ARGV.include?("--version")
|
6
|
+
require 'parallel_split_test/version'
|
7
|
+
puts ParallelSplitTest::VERSION; exit
|
8
|
+
elsif ARGV.include?("-h") or ARGV.include?("--help") or ARGV.empty?
|
9
|
+
puts <<-TEXT
|
10
|
+
Split a big test file into multiple chunks and run them in parallel, giving ENV['TEST_ENV_NUMBER'] as '', '2', '3', ...
|
9
11
|
|
10
12
|
Usage:
|
11
|
-
parallel_split_test test/baz/xxx_text.rb
|
13
|
+
parallel_split_test test/baz/xxx_text.rb [other rspec options]
|
12
14
|
|
13
15
|
Options are:
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
opts.on("-o", "--test-options STRING", "Run tests with these options") { |test_options| options[:test_options] = test_options }
|
18
|
-
end
|
19
|
-
|
20
|
-
parser.parse!
|
21
|
-
|
22
|
-
if ARGV.empty?
|
23
|
-
puts parser
|
16
|
+
-v, --version Display the program version.
|
17
|
+
-h, --help Display this help message.
|
18
|
+
TEXT
|
24
19
|
exit
|
25
20
|
end
|
26
21
|
|
27
22
|
require 'parallel_split_test/runner'
|
28
|
-
exit ParallelSplitTest::Runner.run(ARGV,
|
23
|
+
exit ParallelSplitTest::Runner.run(ARGV, $stderr, $stdout)
|
@@ -6,24 +6,66 @@ require 'parallel_split_test/core_ext/rspec_example'
|
|
6
6
|
|
7
7
|
module ParallelSplitTest
|
8
8
|
class CommandLine < RSpec::Core::CommandLine
|
9
|
+
def initialize(args)
|
10
|
+
@args = args
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
9
14
|
def run(err, out)
|
10
|
-
|
11
|
-
|
12
|
-
out = OutputRecorder.new(out)
|
13
|
-
setup_copied_from_rspec(err, out)
|
15
|
+
processes = ParallelSplitTest.choose_number_of_processes
|
16
|
+
out.puts "Running examples in #{processes} processes"
|
14
17
|
|
18
|
+
results = Parallel.in_processes(processes) do |process_number|
|
15
19
|
ParallelSplitTest.example_counter = 0
|
16
20
|
ParallelSplitTest.process_number = process_number
|
21
|
+
set_test_env_number(process_number)
|
22
|
+
modify_out_file_in_args(process_number) if out_file
|
17
23
|
|
24
|
+
out = OutputRecorder.new(out)
|
25
|
+
setup_copied_from_rspec(err, out)
|
18
26
|
[run_group_of_tests, out.recorded]
|
19
27
|
end
|
20
28
|
|
29
|
+
combine_out_files if out_file
|
30
|
+
|
21
31
|
reprint_result_lines(out, results.map(&:last))
|
22
32
|
results.map(&:first).max # combine exit status
|
23
33
|
end
|
24
34
|
|
25
35
|
private
|
26
36
|
|
37
|
+
# modify + reparse args to unify output
|
38
|
+
def modify_out_file_in_args(process_number)
|
39
|
+
@args[out_file_position] = "#{out_file}.#{process_number}"
|
40
|
+
@options = RSpec::Core::ConfigurationOptions.new(@args)
|
41
|
+
@options.parse_options
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_test_env_number(process_number)
|
45
|
+
ENV['TEST_ENV_NUMBER'] = (process_number == 0 ? '' : (process_number + 1).to_s)
|
46
|
+
end
|
47
|
+
|
48
|
+
def out_file
|
49
|
+
@out_file ||= @args[out_file_position] if out_file_position
|
50
|
+
end
|
51
|
+
|
52
|
+
def out_file_position
|
53
|
+
@out_file_position ||= begin
|
54
|
+
if out_position = @args.index { |i| ["-o", "--out"].include?(i) }
|
55
|
+
out_position + 1
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def combine_out_files
|
61
|
+
File.open(out_file, "w") do |f|
|
62
|
+
Dir["#{out_file}.*"].each do |file|
|
63
|
+
f.write File.read(file)
|
64
|
+
File.delete(file)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
27
69
|
def reprint_result_lines(out, printed_outputs)
|
28
70
|
out.puts
|
29
71
|
out.puts "Summary:"
|
@@ -4,21 +4,13 @@ require 'shellwords'
|
|
4
4
|
# a cleaned up version of the RSpec runner, e.g. no drb support
|
5
5
|
module ParallelSplitTest
|
6
6
|
class Runner < RSpec::Core::Runner
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# @overwrite
|
8
|
+
# stripped down version of run without --drb support / option parsing
|
9
|
+
def self.run(args, err=$stderr, out=$stdout)
|
10
10
|
trap_interrupt
|
11
11
|
|
12
|
-
args += Shellwords.shellwords(options[:test_options]) if options[:test_options] # TODO smarter parsing ...
|
13
|
-
|
14
|
-
options = RSpec::Core::ConfigurationOptions.new(args)
|
15
|
-
options.parse_options
|
16
|
-
|
17
|
-
ParallelSplitTest.choose_number_of_processes
|
18
|
-
out.puts "Running examples in #{ParallelSplitTest.processes} processes"
|
19
|
-
|
20
12
|
report_execution_time(out) do
|
21
|
-
ParallelSplitTest::CommandLine.new(
|
13
|
+
ParallelSplitTest::CommandLine.new(args).run(err, out)
|
22
14
|
end
|
23
15
|
ensure
|
24
16
|
RSpec.reset
|
@@ -223,7 +223,7 @@ describe ParallelSplitTest do
|
|
223
223
|
result.should include("1 example, 0 failures\n1 example, 0 failures")
|
224
224
|
end
|
225
225
|
|
226
|
-
it "can use
|
226
|
+
it "can use rspec options" do
|
227
227
|
write "xxx_spec.rb", <<-RUBY
|
228
228
|
describe "xxx" do
|
229
229
|
it "yyy" do
|
@@ -231,9 +231,38 @@ describe ParallelSplitTest do
|
|
231
231
|
end
|
232
232
|
RUBY
|
233
233
|
|
234
|
-
result = parallel_split_test "xxx_spec.rb --
|
234
|
+
result = parallel_split_test "xxx_spec.rb --format html"
|
235
235
|
result.should include "</body>"
|
236
236
|
end
|
237
|
+
|
238
|
+
it "writes a unified --out" do
|
239
|
+
write "xxx_spec.rb", <<-RUBY
|
240
|
+
describe "xxx" do
|
241
|
+
it "yyy" do
|
242
|
+
end
|
243
|
+
|
244
|
+
it "zzz" do
|
245
|
+
end
|
246
|
+
end
|
247
|
+
RUBY
|
248
|
+
|
249
|
+
result = parallel_split_test "xxx_spec.rb --format d --out xxx"
|
250
|
+
|
251
|
+
# output does not show up in stdout
|
252
|
+
result.should_not include "xxx"
|
253
|
+
result.should_not include "yyy"
|
254
|
+
|
255
|
+
# basic output is still there
|
256
|
+
result.should include "Running examples in"
|
257
|
+
|
258
|
+
# recorded output is combination of both
|
259
|
+
out = File.read("xxx")
|
260
|
+
out.should include "yyy"
|
261
|
+
out.should include "zzz"
|
262
|
+
|
263
|
+
# parts are cleaned up
|
264
|
+
Dir["xxx.*"].should == []
|
265
|
+
end
|
237
266
|
end
|
238
267
|
end
|
239
268
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel_split_test
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -83,7 +83,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
83
|
version: '0'
|
84
84
|
segments:
|
85
85
|
- 0
|
86
|
-
hash:
|
86
|
+
hash: 4514306617232661236
|
87
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
88
|
none: false
|
89
89
|
requirements:
|
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
version: '0'
|
93
93
|
segments:
|
94
94
|
- 0
|
95
|
-
hash:
|
95
|
+
hash: 4514306617232661236
|
96
96
|
requirements: []
|
97
97
|
rubyforge_project:
|
98
98
|
rubygems_version: 1.8.25
|