friendlyfashion-parallel_tests 0.9.0
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/.gitignore +2 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +44 -0
- data/Rakefile +6 -0
- data/Readme.md +232 -0
- data/ReadmeRails2.md +48 -0
- data/bin/parallel_cucumber +2 -0
- data/bin/parallel_rspec +2 -0
- data/bin/parallel_test +6 -0
- data/lib/parallel_tests.rb +30 -0
- data/lib/parallel_tests/cli.rb +159 -0
- data/lib/parallel_tests/cucumber/gherkin_listener.rb +60 -0
- data/lib/parallel_tests/cucumber/runner.rb +90 -0
- data/lib/parallel_tests/cucumber/runtime_logger.rb +58 -0
- data/lib/parallel_tests/grouper.rb +53 -0
- data/lib/parallel_tests/railtie.rb +8 -0
- data/lib/parallel_tests/rspec/failures_logger.rb +44 -0
- data/lib/parallel_tests/rspec/logger_base.rb +52 -0
- data/lib/parallel_tests/rspec/runner.rb +59 -0
- data/lib/parallel_tests/rspec/runtime_logger.rb +34 -0
- data/lib/parallel_tests/rspec/summary_logger.rb +19 -0
- data/lib/parallel_tests/tasks.rb +134 -0
- data/lib/parallel_tests/test/runner.rb +134 -0
- data/lib/parallel_tests/test/runtime_logger.rb +92 -0
- data/lib/parallel_tests/version.rb +3 -0
- data/parallel_tests.gemspec +14 -0
- data/spec/integration_spec.rb +244 -0
- data/spec/parallel_tests/cli_spec.rb +36 -0
- data/spec/parallel_tests/cucumber/gherkin_listener_spec.rb +48 -0
- data/spec/parallel_tests/cucumber/runner_spec.rb +173 -0
- data/spec/parallel_tests/grouper_spec.rb +52 -0
- data/spec/parallel_tests/rspec/failure_logger_spec.rb +82 -0
- data/spec/parallel_tests/rspec/runner_spec.rb +178 -0
- data/spec/parallel_tests/rspec/runtime_logger_spec.rb +76 -0
- data/spec/parallel_tests/rspec/summary_logger_spec.rb +37 -0
- data/spec/parallel_tests/tasks_spec.rb +151 -0
- data/spec/parallel_tests/test/runner_spec.rb +273 -0
- data/spec/parallel_tests/test/runtime_logger_spec.rb +84 -0
- data/spec/parallel_tests_spec.rb +73 -0
- data/spec/spec_helper.rb +151 -0
- metadata +109 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ParallelTests::Test::RuntimeLogger do
|
4
|
+
describe :writing do
|
5
|
+
around do |example|
|
6
|
+
use_temporary_directory_for do
|
7
|
+
FileUtils.mkdir_p(File.dirname(log))
|
8
|
+
example.call
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:log) { ParallelTests::Test::Runner.runtime_log }
|
13
|
+
|
14
|
+
it "overwrites the runtime_log file on first log invocation" do
|
15
|
+
class FakeTest
|
16
|
+
end
|
17
|
+
test = FakeTest.new
|
18
|
+
time = Time.now
|
19
|
+
File.open(log, 'w'){ |f| f.puts("FooBar") }
|
20
|
+
ParallelTests::Test::RuntimeLogger.send(:class_variable_set,:@@has_started, false)
|
21
|
+
ParallelTests::Test::RuntimeLogger.log(test, time, Time.at(time.to_f+2.00))
|
22
|
+
result = File.read(log)
|
23
|
+
result.should_not include('FooBar')
|
24
|
+
result.should include('test/fake_test.rb:2.00')
|
25
|
+
end
|
26
|
+
|
27
|
+
it "appends to the runtime_log file after first log invocation" do
|
28
|
+
class FakeTest
|
29
|
+
end
|
30
|
+
test = FakeTest.new
|
31
|
+
class OtherFakeTest
|
32
|
+
end
|
33
|
+
other_test = OtherFakeTest.new
|
34
|
+
|
35
|
+
time = Time.now
|
36
|
+
File.open(log, 'w'){ |f| f.puts("FooBar") }
|
37
|
+
ParallelTests::Test::RuntimeLogger.send(:class_variable_set,:@@has_started, false)
|
38
|
+
ParallelTests::Test::RuntimeLogger.log(test, time, Time.at(time.to_f+2.00))
|
39
|
+
ParallelTests::Test::RuntimeLogger.log(other_test, time, Time.at(time.to_f+2.00))
|
40
|
+
result = File.read(log)
|
41
|
+
result.should_not include('FooBar')
|
42
|
+
result.should include('test/fake_test.rb:2.00')
|
43
|
+
result.should include('test/other_fake_test.rb:2.00')
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe :formatting do
|
48
|
+
def call(*args)
|
49
|
+
ParallelTests::Test::RuntimeLogger.message(*args)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "formats results for simple test names" do
|
53
|
+
class FakeTest
|
54
|
+
end
|
55
|
+
test = FakeTest.new
|
56
|
+
time = Time.now
|
57
|
+
call(test, time, Time.at(time.to_f+2.00)).should == 'test/fake_test.rb:2.00'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "formats results for complex test names" do
|
61
|
+
class AVeryComplex
|
62
|
+
class FakeTest
|
63
|
+
end
|
64
|
+
end
|
65
|
+
test = AVeryComplex::FakeTest.new
|
66
|
+
time = Time.now
|
67
|
+
call(test, time, Time.at(time.to_f+2.00)).should == 'test/a_very_complex/fake_test.rb:2.00'
|
68
|
+
end
|
69
|
+
|
70
|
+
it "guesses subdirectory structure for rails test classes" do
|
71
|
+
module Rails
|
72
|
+
end
|
73
|
+
class ActionController
|
74
|
+
class TestCase
|
75
|
+
end
|
76
|
+
end
|
77
|
+
class FakeControllerTest < ActionController::TestCase
|
78
|
+
end
|
79
|
+
test = FakeControllerTest.new
|
80
|
+
time = Time.now
|
81
|
+
call(test, time, Time.at(time.to_f+2.00)).should == 'test/functional/fake_controller_test.rb:2.00'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe ParallelTests do
|
4
|
+
describe ".determine_number_of_processes" do
|
5
|
+
before do
|
6
|
+
ENV.delete('PARALLEL_TEST_PROCESSORS')
|
7
|
+
Parallel.stub(:processor_count).and_return 20
|
8
|
+
end
|
9
|
+
|
10
|
+
def call(count)
|
11
|
+
ParallelTests.determine_number_of_processes(count)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "uses the given count if set" do
|
15
|
+
call('5').should == 5
|
16
|
+
end
|
17
|
+
|
18
|
+
it "uses the processor count from Parallel" do
|
19
|
+
call(nil).should == 20
|
20
|
+
end
|
21
|
+
|
22
|
+
it "uses the processor count from ENV before Parallel" do
|
23
|
+
ENV['PARALLEL_TEST_PROCESSORS'] = '22'
|
24
|
+
call(nil).should == 22
|
25
|
+
end
|
26
|
+
|
27
|
+
it "does not use blank count" do
|
28
|
+
call(' ').should == 20
|
29
|
+
end
|
30
|
+
|
31
|
+
it "does not use blank env" do
|
32
|
+
ENV['PARALLEL_TEST_PROCESSORS'] = ' '
|
33
|
+
call(nil).should == 20
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe :bundler_enabled? do
|
38
|
+
before do
|
39
|
+
Object.stub!(:const_defined?).with(:Bundler).and_return false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should return false" do
|
43
|
+
use_temporary_directory_for do
|
44
|
+
ParallelTests.send(:bundler_enabled?).should == false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should return true when there is a constant called Bundler" do
|
49
|
+
use_temporary_directory_for do
|
50
|
+
Object.stub!(:const_defined?).with(:Bundler).and_return true
|
51
|
+
ParallelTests.send(:bundler_enabled?).should == true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should be true when there is a Gemfile" do
|
56
|
+
use_temporary_directory_for do
|
57
|
+
FileUtils.touch("Gemfile")
|
58
|
+
ParallelTests.send(:bundler_enabled?).should == true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should be true when there is a Gemfile in the parent directory" do
|
63
|
+
use_temporary_directory_for do
|
64
|
+
FileUtils.touch(File.join("..", "Gemfile"))
|
65
|
+
ParallelTests.send(:bundler_enabled?).should == true
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
it "has a version" do
|
71
|
+
ParallelTests::VERSION.should =~ /^\d+\.\d+\.\d+/
|
72
|
+
end
|
73
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
$LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
|
2
|
+
|
3
|
+
FAKE_RAILS_ROOT = './tmp/pspecs/fixtures'
|
4
|
+
|
5
|
+
require 'tempfile'
|
6
|
+
require 'parallel_tests'
|
7
|
+
require 'parallel_tests/test/runner'
|
8
|
+
require 'parallel_tests/test/runtime_logger'
|
9
|
+
|
10
|
+
require 'parallel_tests/rspec/runner'
|
11
|
+
require 'parallel_tests/rspec/runtime_logger'
|
12
|
+
require 'parallel_tests/rspec/summary_logger'
|
13
|
+
|
14
|
+
require 'parallel_tests/cucumber/runner'
|
15
|
+
|
16
|
+
OutputLogger = Struct.new(:output) do
|
17
|
+
attr_reader :flock, :flush
|
18
|
+
def puts(s=nil)
|
19
|
+
self.output << s.to_s
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def mocked_process
|
24
|
+
open('|cat /dev/null')
|
25
|
+
end
|
26
|
+
|
27
|
+
def size_of(group)
|
28
|
+
group.inject(0) { |sum, test| sum += File.stat(test).size }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Uses /tmp/parallel_tests/application as the cwd so we can create and remove
|
32
|
+
# files as we want to. After execution it changes cwd back to the original one.
|
33
|
+
def use_temporary_directory_for
|
34
|
+
require 'fileutils'
|
35
|
+
|
36
|
+
dir = File.join("/tmp", "parallel_tests")
|
37
|
+
new_dir = File.join(dir, "application")
|
38
|
+
|
39
|
+
begin
|
40
|
+
# just in case the temporary dir already exists
|
41
|
+
FileUtils.rm_rf(dir) if File.exists?(dir)
|
42
|
+
|
43
|
+
# create the temporary directory
|
44
|
+
FileUtils.mkdir_p(new_dir)
|
45
|
+
|
46
|
+
# chdir changes cwd back to the original one after it is done
|
47
|
+
Dir.chdir(new_dir) do
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
ensure
|
51
|
+
FileUtils.rm_rf(dir) if File.exists?(dir)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_tests_in_groups(klass, folder, suffix)
|
56
|
+
test_root = "#{FAKE_RAILS_ROOT}/#{folder}"
|
57
|
+
|
58
|
+
describe :tests_in_groups do
|
59
|
+
before :all do
|
60
|
+
system "rm -rf #{FAKE_RAILS_ROOT}; mkdir -p #{test_root}/temp"
|
61
|
+
|
62
|
+
@files = [0,1,2,3,4,5,6,7].map do |i|
|
63
|
+
size = 99
|
64
|
+
file = "#{test_root}/temp/x#{i}#{suffix}"
|
65
|
+
File.open(file, 'w') { |f| f.puts 'x' * size }
|
66
|
+
file
|
67
|
+
end
|
68
|
+
|
69
|
+
@log = klass.runtime_log
|
70
|
+
`mkdir -p #{File.dirname(@log)}`
|
71
|
+
`rm -f #{@log}`
|
72
|
+
end
|
73
|
+
|
74
|
+
after :all do
|
75
|
+
`rm -f #{klass.runtime_log}`
|
76
|
+
end
|
77
|
+
|
78
|
+
def setup_runtime_log
|
79
|
+
File.open(@log,'w') do |f|
|
80
|
+
@files[1..-1].each{|file| f.puts "#{file}:#{@files.index(file)}"}
|
81
|
+
f.puts "#{@files[0]}:10"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "groups when given an array of files" do
|
86
|
+
list_of_files = Dir["#{test_root}/**/*#{suffix}"]
|
87
|
+
found = klass.with_runtime_info(list_of_files)
|
88
|
+
found.should =~ list_of_files.map{ |file| [file, File.stat(file).size]}
|
89
|
+
end
|
90
|
+
|
91
|
+
it "finds all tests" do
|
92
|
+
found = klass.tests_in_groups([test_root], 1)
|
93
|
+
all = [ Dir["#{test_root}/**/*#{suffix}"] ]
|
94
|
+
(found.flatten - all.flatten).should == []
|
95
|
+
end
|
96
|
+
|
97
|
+
it "partitions them into groups by equal size" do
|
98
|
+
groups = klass.tests_in_groups([test_root], 2)
|
99
|
+
groups.map{|g| size_of(g)}.should == [400, 400]
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'should partition correctly with a group size of 4' do
|
103
|
+
groups = klass.tests_in_groups([test_root], 4)
|
104
|
+
groups.map{|g| size_of(g)}.should == [200, 200, 200, 200]
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should partition correctly with an uneven group size' do
|
108
|
+
groups = klass.tests_in_groups([test_root], 3)
|
109
|
+
groups.map{|g| size_of(g)}.should =~ [300, 300, 200]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "partitions by runtime when runtime-data is available" do
|
113
|
+
klass.stub!(:puts)
|
114
|
+
setup_runtime_log
|
115
|
+
|
116
|
+
groups = klass.tests_in_groups([test_root], 2)
|
117
|
+
groups.size.should == 2
|
118
|
+
# 10 + 1 + 3 + 5 = 19
|
119
|
+
groups[0].should == [@files[0],@files[1],@files[3],@files[5]]
|
120
|
+
# 2 + 4 + 6 + 7 = 19
|
121
|
+
groups[1].should == [@files[2],@files[4],@files[6],@files[7]]
|
122
|
+
end
|
123
|
+
|
124
|
+
it "alpha-sorts partitions when runtime-data is available" do
|
125
|
+
klass.stub!(:puts)
|
126
|
+
setup_runtime_log
|
127
|
+
|
128
|
+
groups = klass.tests_in_groups([test_root], 2)
|
129
|
+
groups.size.should == 2
|
130
|
+
|
131
|
+
groups[0].should == groups[0].sort
|
132
|
+
groups[1].should == groups[1].sort
|
133
|
+
end
|
134
|
+
|
135
|
+
it "partitions by round-robin when not sorting" do
|
136
|
+
files = ["file1.rb", "file2.rb", "file3.rb", "file4.rb"]
|
137
|
+
klass.should_receive(:find_tests).and_return(files)
|
138
|
+
groups = klass.tests_in_groups(files, 2, :group_by => :found).sort
|
139
|
+
groups[0].should == ["file1.rb", "file3.rb"]
|
140
|
+
groups[1].should == ["file2.rb", "file4.rb"]
|
141
|
+
end
|
142
|
+
|
143
|
+
it "alpha-sorts partitions when not sorting by runtime" do
|
144
|
+
files = %w[q w e r t y u i o p a s d f g h j k l z x c v b n m]
|
145
|
+
klass.should_receive(:find_tests).and_return(files)
|
146
|
+
groups = klass.tests_in_groups(files, 2, :group_by => :found).sort
|
147
|
+
groups[0].should == groups[0].sort
|
148
|
+
groups[1].should == groups[1].sort
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: friendlyfashion-parallel_tests
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Laurynas Butkus
|
9
|
+
- Tomas Varaneckas
|
10
|
+
- Justas Janauskas
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2013-02-24 00:00:00.000000000 Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: parallel
|
18
|
+
requirement: !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ! '>='
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: '0'
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: !ruby/object:Gem::Requirement
|
27
|
+
none: false
|
28
|
+
requirements:
|
29
|
+
- - ! '>='
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '0'
|
32
|
+
description:
|
33
|
+
email:
|
34
|
+
- laurynas.butkus@gmail.com
|
35
|
+
- tomas.varaneckas@gmail.com
|
36
|
+
- jjanauskas@gmail.com
|
37
|
+
executables:
|
38
|
+
- parallel_cucumber
|
39
|
+
- parallel_rspec
|
40
|
+
- parallel_test
|
41
|
+
extensions: []
|
42
|
+
extra_rdoc_files: []
|
43
|
+
files:
|
44
|
+
- .gitignore
|
45
|
+
- Gemfile
|
46
|
+
- Gemfile.lock
|
47
|
+
- Rakefile
|
48
|
+
- Readme.md
|
49
|
+
- ReadmeRails2.md
|
50
|
+
- bin/parallel_cucumber
|
51
|
+
- bin/parallel_rspec
|
52
|
+
- bin/parallel_test
|
53
|
+
- lib/parallel_tests.rb
|
54
|
+
- lib/parallel_tests/cli.rb
|
55
|
+
- lib/parallel_tests/cucumber/gherkin_listener.rb
|
56
|
+
- lib/parallel_tests/cucumber/runner.rb
|
57
|
+
- lib/parallel_tests/cucumber/runtime_logger.rb
|
58
|
+
- lib/parallel_tests/grouper.rb
|
59
|
+
- lib/parallel_tests/railtie.rb
|
60
|
+
- lib/parallel_tests/rspec/failures_logger.rb
|
61
|
+
- lib/parallel_tests/rspec/logger_base.rb
|
62
|
+
- lib/parallel_tests/rspec/runner.rb
|
63
|
+
- lib/parallel_tests/rspec/runtime_logger.rb
|
64
|
+
- lib/parallel_tests/rspec/summary_logger.rb
|
65
|
+
- lib/parallel_tests/tasks.rb
|
66
|
+
- lib/parallel_tests/test/runner.rb
|
67
|
+
- lib/parallel_tests/test/runtime_logger.rb
|
68
|
+
- lib/parallel_tests/version.rb
|
69
|
+
- parallel_tests.gemspec
|
70
|
+
- spec/integration_spec.rb
|
71
|
+
- spec/parallel_tests/cli_spec.rb
|
72
|
+
- spec/parallel_tests/cucumber/gherkin_listener_spec.rb
|
73
|
+
- spec/parallel_tests/cucumber/runner_spec.rb
|
74
|
+
- spec/parallel_tests/grouper_spec.rb
|
75
|
+
- spec/parallel_tests/rspec/failure_logger_spec.rb
|
76
|
+
- spec/parallel_tests/rspec/runner_spec.rb
|
77
|
+
- spec/parallel_tests/rspec/runtime_logger_spec.rb
|
78
|
+
- spec/parallel_tests/rspec/summary_logger_spec.rb
|
79
|
+
- spec/parallel_tests/tasks_spec.rb
|
80
|
+
- spec/parallel_tests/test/runner_spec.rb
|
81
|
+
- spec/parallel_tests/test/runtime_logger_spec.rb
|
82
|
+
- spec/parallel_tests_spec.rb
|
83
|
+
- spec/spec_helper.rb
|
84
|
+
homepage: http://github.com/friendlyfashion/parallel_tests
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ! '>='
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubyforge_project:
|
105
|
+
rubygems_version: 1.8.24
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: Run Test::Unit / RSpec / Cucumber in parallel
|
109
|
+
test_files: []
|