parallel_split_test 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ script: "bundle exec rake"
2
+ rvm:
3
+ - ree
4
+ - 1.9.2
5
+ - 1.9.3
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+ gemspec
3
+
4
+ group :development do
5
+ gem 'rake'
6
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,28 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ parallel_split_test (0.1.0)
5
+ parallel (>= 0.5.12)
6
+ rspec (>= 2)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ diff-lcs (1.1.3)
12
+ parallel (0.5.12)
13
+ rake (0.9.2)
14
+ rspec (2.8.0)
15
+ rspec-core (~> 2.8.0)
16
+ rspec-expectations (~> 2.8.0)
17
+ rspec-mocks (~> 2.8.0)
18
+ rspec-core (2.8.0)
19
+ rspec-expectations (2.8.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.8.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ parallel_split_test!
28
+ rake
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ task :default do
4
+ sh "rspec spec/"
5
+ end
6
+
7
+ rule /^version:bump:.*/ do |t|
8
+ file = 'lib/parallel_split_test/version.rb'
9
+ sh "git status | grep 'nothing to commit'" # ensure we are not dirty
10
+ index = ['major', 'minor','patch'].index(t.name.split(':').last)
11
+ version_file = File.read(file)
12
+ old_version, *version_parts = version_file.match(/(\d+)\.(\d+)\.(\d+)/).to_a
13
+ version_parts[index] = version_parts[index].to_i + 1
14
+ new_version = version_parts * '.'
15
+ File.open(file,'w'){|f| f.write(version_file.sub(old_version, new_version)) }
16
+
17
+ sh "bundle && git add #{file} Gemfile.lock && git commit -m 'bump version to #{new_version}'"
18
+ end
data/Readme.md ADDED
@@ -0,0 +1,41 @@
1
+ Split a big test file into multiple chunks and run them in parallel
2
+
3
+ Install
4
+ =======
5
+ sudo gem install parallel_split_test
6
+ Or
7
+
8
+ rails plugin install git://github.com/grosser/parallel_split_test.git
9
+
10
+ Usage
11
+ =====
12
+ # spec/xxx_spec.rb
13
+ require "spec_helper"
14
+
15
+ describe "X" do
16
+ it {sleep 5}
17
+ end
18
+
19
+ describe "Y" do
20
+ it {sleep 5}
21
+ end
22
+
23
+ describe "Z" do
24
+ it {sleep 5}
25
+ end
26
+
27
+ time parallel_split_test spec/xxx_spec.rb [regular rspec options]
28
+
29
+ TODO
30
+ ====
31
+ - combine exit status (1 + 0 == 1)
32
+ - support a single group with multiple sub-groups
33
+ - Test::Unit support
34
+ - Cucumber support
35
+
36
+ Author
37
+ ======
38
+ [Michael Grosser](http://grosser.it)<br/>
39
+ michael@grosser.it<br/>
40
+ License: MIT<br/>
41
+ [![Build Status](https://secure.travis-ci.org/grosser/parallel_split_test.png)](http://travis-ci.org/grosser/parallel_split_test)
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env ruby
2
+ require "optparse"
3
+ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
+ require "parallel_split_test"
5
+
6
+ parser = OptionParser.new do |opts|
7
+ opts.banner = <<BANNER
8
+ Split a big test file into multiple chunks and run them in parallel, giving ENV['TEST_ENV_NUMBER'] ('', '2', '3', ...)
9
+
10
+ Usage:
11
+ parallel_split_test test/baz/xxx_text.rb
12
+
13
+ Options are:
14
+ BANNER
15
+ opts.on("-v", "--version", "Show Version"){ require 'parallel_split_test/version'; puts ParallelSplitTest::VERSION; exit}
16
+ opts.on("-h", "--help", "Show this.") { puts opts; exit }
17
+ end
18
+
19
+ parser.parse!
20
+
21
+ if ARGV.empty?
22
+ puts parser
23
+ exit
24
+ end
25
+
26
+ require "rspec"
27
+ require "parallel"
28
+
29
+ require 'parallel_split_test/runner'
30
+ ParallelSplitTest::Runner.run(ARGV)
@@ -0,0 +1,2 @@
1
+ module ParallelSplitTest
2
+ end
@@ -0,0 +1,53 @@
1
+ require 'parallel'
2
+ require 'rspec/core/command_line'
3
+
4
+ module ParallelSplitTest
5
+ class CommandLine < RSpec::Core::CommandLine
6
+ def run(err, out)
7
+ setup_copied_from_rspec(err, out)
8
+
9
+ processes = Parallel.processor_count
10
+
11
+ Parallel.in_processes(processes) do |process_number|
12
+ ENV['TEST_ENV_NUMBER'] = (process_number == 0 ? '' : (process_number + 1).to_s)
13
+ run_group_of_tests(processes, process_number)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def run_group_of_tests(processes, process_number)
20
+ example_count = @world.example_count / processes
21
+
22
+ @configuration.reporter.report(example_count, seed) do |reporter|
23
+ begin
24
+ @configuration.run_hook(:before, :suite)
25
+ groups = groups_for_this_process(@world.example_groups.ordered, process_number, processes)
26
+ groups.map {|g| g.run(reporter)}.all? ? 0 : @configuration.failure_exit_code
27
+ ensure
28
+ @configuration.run_hook(:after, :suite)
29
+ end
30
+ end
31
+ end
32
+
33
+ def seed
34
+ @configuration.randomize? ? @configuration.seed : nil
35
+ end
36
+
37
+ def groups_for_this_process(groups, number, count)
38
+ selected = []
39
+ groups.each_with_index do |group, i|
40
+ selected << group if i % count == number
41
+ end
42
+ selected
43
+ end
44
+
45
+ def setup_copied_from_rspec(err, out)
46
+ @configuration.error_stream = err
47
+ @configuration.output_stream ||= out
48
+ @options.configure(@configuration)
49
+ @configuration.load_spec_files
50
+ @world.announce_filters
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,17 @@
1
+ require 'rspec/core/runner'
2
+ require 'rspec/core/configuration_options'
3
+ require 'parallel_split_test/command_line'
4
+
5
+ # a cleaned up version of the RSpec runner, e.g. no drb support
6
+ module ParallelSplitTest
7
+ class Runner < RSpec::Core::Runner
8
+ def self.run(args, err=$stderr, out=$stdout)
9
+ trap_interrupt
10
+ options = RSpec::Core::ConfigurationOptions.new(args)
11
+ options.parse_options
12
+ ParallelSplitTest::CommandLine.new(options).run(err, out)
13
+ ensure
14
+ RSpec.reset
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,3 @@
1
+ module ParallelSplitTest
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,15 @@
1
+ $LOAD_PATH.unshift File.expand_path('../lib', __FILE__)
2
+ name = "parallel_split_test"
3
+ require "#{name}/version"
4
+
5
+ Gem::Specification.new name, ParallelSplitTest::VERSION do |s|
6
+ s.summary = "Split a big test file into multiple chunks and run them in parallel"
7
+ s.authors = ["Michael Grosser"]
8
+ s.email = "michael@grosser.it"
9
+ s.homepage = "http://github.com/grosser/#{name}"
10
+ s.files = `git ls-files`.split("\n")
11
+ s.executables = ["parallel_split_test"]
12
+ s.add_dependency "rspec", ">=2"
13
+ s.add_dependency "parallel", ">=0.5.12"
14
+ s.license = "MIT"
15
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe ParallelSplitTest do
4
+ it "has a VERSION" do
5
+ ParallelSplitTest::VERSION.should =~ /^[\.\da-z]+$/
6
+ end
7
+
8
+ describe "cli" do
9
+ def run(command, options={})
10
+ result = `#{command} 2>&1`
11
+ message = (options[:fail] ? "SUCCESS BUT SHOULD FAIL" : "FAIL")
12
+ raise "[#{message}] #{result} [#{command}]" if $?.success? == !!options[:fail]
13
+ result
14
+ end
15
+
16
+ def write(path, content)
17
+ run "mkdir -p #{File.dirname(path)}" unless File.exist?(File.dirname(path))
18
+ File.open(path, 'w'){|f| f.write content }
19
+ path
20
+ end
21
+
22
+ def parallel_split_test(x)
23
+ run "../../bin/parallel_split_test #{x}"
24
+ end
25
+
26
+ def time
27
+ start = Time.now.to_f
28
+ yield
29
+ Time.now.to_f - start
30
+ end
31
+
32
+ let(:root) { File.expand_path('../../', __FILE__) }
33
+
34
+ before do
35
+ run "rm -rf spec/tmp ; mkdir spec/tmp"
36
+ Dir.chdir "spec/tmp"
37
+ end
38
+
39
+ after do
40
+ Dir.chdir root
41
+ end
42
+
43
+ describe "printing version" do
44
+ it "prints version on -v" do
45
+ parallel_split_test("-v").strip.should =~ /^[\.\da-z]+$/
46
+ end
47
+
48
+ it "prints version on --version" do
49
+ parallel_split_test("--version").strip.should =~ /^[\.\da-z]+$/
50
+ end
51
+ end
52
+
53
+ describe "printing help" do
54
+ it "prints help on -h" do
55
+ parallel_split_test("-h").should include("Usage")
56
+ end
57
+
58
+ it "prints help on --help" do
59
+ parallel_split_test("-h").should include("Usage")
60
+ end
61
+
62
+ it "prints help on no arguments" do
63
+ parallel_split_test("").should include("Usage")
64
+ end
65
+ end
66
+
67
+ describe "running tests" do
68
+ it "runs in different processes" do
69
+ write "xxx_spec.rb", <<-RUBY
70
+ describe "X" do
71
+ it "a" do
72
+ puts "it-ran-a-in-\#{ENV['TEST_ENV_NUMBER'].to_i}-"
73
+ end
74
+ end
75
+
76
+ describe "Y" do
77
+ it "b" do
78
+ puts "it-ran-b-in-\#{ENV['TEST_ENV_NUMBER'].to_i}-"
79
+ end
80
+ end
81
+ RUBY
82
+ result = parallel_split_test "xxx_spec.rb"
83
+
84
+ processes = ["a","b"].map do |process|
85
+ rex = /it-ran-#{process}-in-(\d)-/
86
+ result.should =~ rex
87
+ result.match(rex)[1]
88
+ end
89
+
90
+ processes.should == ['0','2']
91
+ end
92
+
93
+ it "runs faster" do
94
+ write "xxx_spec.rb", <<-RUBY
95
+ describe "X" do
96
+ it { sleep 1 }
97
+ end
98
+
99
+ describe "Y" do
100
+ it { sleep 1 }
101
+ end
102
+ RUBY
103
+
104
+ time{ parallel_split_test "xxx_spec.rb" }.should < 2
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,3 @@
1
+ $LOAD_PATH.unshift 'lib'
2
+ require 'parallel_split_test'
3
+ require 'parallel_split_test/version'
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: parallel_split_test
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Michael Grosser
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-02-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: &84152290 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '2'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *84152290
25
+ - !ruby/object:Gem::Dependency
26
+ name: parallel
27
+ requirement: &84152040 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: 0.5.12
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *84152040
36
+ description:
37
+ email: michael@grosser.it
38
+ executables:
39
+ - parallel_split_test
40
+ extensions: []
41
+ extra_rdoc_files: []
42
+ files:
43
+ - .travis.yml
44
+ - Gemfile
45
+ - Gemfile.lock
46
+ - Rakefile
47
+ - Readme.md
48
+ - bin/parallel_split_test
49
+ - lib/parallel_split_test.rb
50
+ - lib/parallel_split_test/command_line.rb
51
+ - lib/parallel_split_test/runner.rb
52
+ - lib/parallel_split_test/version.rb
53
+ - parallel_split_test.gemspec
54
+ - spec/parallel_split_test_spec.rb
55
+ - spec/spec_helper.rb
56
+ homepage: http://github.com/grosser/parallel_split_test
57
+ licenses:
58
+ - MIT
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ segments:
70
+ - 0
71
+ hash: -266472017
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ segments:
79
+ - 0
80
+ hash: -266472017
81
+ requirements: []
82
+ rubyforge_project:
83
+ rubygems_version: 1.8.10
84
+ signing_key:
85
+ specification_version: 3
86
+ summary: Split a big test file into multiple chunks and run them in parallel
87
+ test_files: []