zeus-parallel_tests 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.rubocop.yml +12 -0
- data/Appraisals +19 -0
- data/README.md +3 -2
- data/Rakefile +2 -13
- data/bin/zeus-parallel_tests +8 -10
- data/circle.yml +39 -0
- data/gemfiles/rails_3_zeus_0.13.gemfile +8 -0
- data/gemfiles/rails_3_zeus_0.15.gemfile +8 -0
- data/gemfiles/rails_4_zeus_0.13.gemfile +8 -0
- data/gemfiles/rails_4_zeus_0.15.gemfile +8 -0
- data/lib/zeus/parallel_tests.rb +1 -1
- data/lib/zeus/parallel_tests/rails.rb +21 -13
- data/lib/zeus/parallel_tests/version.rb +1 -1
- data/lib/zeus/parallel_tests/worker.rb +44 -45
- data/spec/dummy/Guardfile +4 -4
- data/spec/dummy/config/application.rb +2 -9
- data/spec/dummy/config/boot.rb +1 -1
- data/spec/dummy/config/environments/development.rb +0 -8
- data/spec/dummy/config/environments/production.rb +0 -6
- data/spec/dummy/config/environments/test.rb +1 -4
- data/spec/dummy/custom_plan.rb +1 -0
- data/spec/dummy/features/support/env.rb +1 -2
- data/spec/dummy/lib/tasks/cucumber.rake +43 -44
- data/spec/dummy/spec/spec_helper.rb +4 -4
- data/spec/dummy/spec/unit_test_a_spec.rb +3 -3
- data/spec/dummy/spec/unit_test_b_spec.rb +3 -3
- data/spec/lib/zeus/parallel_tests/worker_spec.rb +28 -30
- data/spec/parallel_spec.rb +56 -0
- data/spec/spec_helper.rb +2 -10
- data/spec/zeus_parallel_tests_spec.rb +16 -0
- data/zeus-parallel_tests.gemspec +23 -14
- metadata +120 -19
- data/.travis.yml +0 -5
- data/spec/dummy/Gemfile +0 -31
- data/spec/slow/parallel_rspec_spec.rb +0 -56
- data/spec/slow/zeus-parallel_tests_spec.rb +0 -29
data/spec/dummy/config/boot.rb
CHANGED
@@ -21,12 +21,4 @@ Dummy::Application.configure do
|
|
21
21
|
|
22
22
|
# Only use best-standards-support built into browsers
|
23
23
|
config.action_dispatch.best_standards_support = :builtin
|
24
|
-
|
25
|
-
# Raise exception on mass assignment protection for Active Record models
|
26
|
-
config.active_record.mass_assignment_sanitizer = :strict
|
27
|
-
|
28
|
-
# Log the query plan for queries taking more than this (works
|
29
|
-
# with SQLite, MySQL, and PostgreSQL)
|
30
|
-
config.active_record.auto_explain_threshold_in_seconds = 0.5
|
31
|
-
|
32
24
|
end
|
@@ -11,7 +11,6 @@ Dummy::Application.configure do
|
|
11
11
|
# Disable Rails's static asset server (Apache or nginx will already do this)
|
12
12
|
config.serve_static_assets = false
|
13
13
|
|
14
|
-
|
15
14
|
# Specifies the header that your server uses for sending files
|
16
15
|
# config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
|
17
16
|
# config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
|
@@ -34,7 +33,6 @@ Dummy::Application.configure do
|
|
34
33
|
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
35
34
|
# config.action_controller.asset_host = "http://assets.example.com"
|
36
35
|
|
37
|
-
|
38
36
|
# Disable delivery errors, bad email addresses will be ignored
|
39
37
|
# config.action_mailer.raise_delivery_errors = false
|
40
38
|
|
@@ -47,8 +45,4 @@ Dummy::Application.configure do
|
|
47
45
|
|
48
46
|
# Send deprecation notices to registered listeners
|
49
47
|
config.active_support.deprecation = :notify
|
50
|
-
|
51
|
-
# Log the query plan for queries taking more than this (works
|
52
|
-
# with SQLite, MySQL, and PostgreSQL)
|
53
|
-
# config.active_record.auto_explain_threshold_in_seconds = 0.5
|
54
48
|
end
|
@@ -9,7 +9,7 @@ Dummy::Application.configure do
|
|
9
9
|
|
10
10
|
# Configure static asset server for tests with Cache-Control for performance
|
11
11
|
config.serve_static_assets = true
|
12
|
-
config.static_cache_control =
|
12
|
+
config.static_cache_control = 'public, max-age=3600'
|
13
13
|
|
14
14
|
# Log error messages when you accidentally call methods on nil
|
15
15
|
config.whiny_nils = true
|
@@ -29,9 +29,6 @@ Dummy::Application.configure do
|
|
29
29
|
# ActionMailer::Base.deliveries array.
|
30
30
|
config.action_mailer.delivery_method = :test
|
31
31
|
|
32
|
-
# Raise exception on mass assignment protection for Active Record models
|
33
|
-
config.active_record.mass_assignment_sanitizer = :strict
|
34
|
-
|
35
32
|
# Print deprecation notices to the stderr
|
36
33
|
config.active_support.deprecation = :stderr
|
37
34
|
end
|
data/spec/dummy/custom_plan.rb
CHANGED
@@ -33,7 +33,7 @@ ActionController::Base.allow_rescue = false
|
|
33
33
|
begin
|
34
34
|
DatabaseCleaner.strategy = :transaction
|
35
35
|
rescue NameError
|
36
|
-
raise
|
36
|
+
raise 'You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it.'
|
37
37
|
end
|
38
38
|
|
39
39
|
# You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios.
|
@@ -55,4 +55,3 @@ end
|
|
55
55
|
# The :transaction strategy is faster, but might give you threading problems.
|
56
56
|
# See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature
|
57
57
|
Cucumber::Rails::Database.javascript_strategy = :truncation
|
58
|
-
|
@@ -4,62 +4,61 @@
|
|
4
4
|
# instead of editing this one. Cucumber will automatically load all features/**/*.rb
|
5
5
|
# files.
|
6
6
|
|
7
|
+
unless ARGV.any? { |a| a =~ /^gems/ } # Don't load anything when running the gems:* tasks
|
7
8
|
|
8
|
-
|
9
|
+
vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first
|
10
|
+
$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil?
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
begin
|
13
|
+
require 'cucumber/rake/task'
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
+
namespace :cucumber do
|
16
|
+
Cucumber::Rake::Task.new({ ok: 'test:prepare' }, 'Run features that should pass') do |t|
|
17
|
+
t.binary = vendored_cucumber_bin # If nil, the gem's binary is used.
|
18
|
+
t.fork = true # You may get faster startup if you set this to false
|
19
|
+
t.profile = 'default'
|
20
|
+
end
|
15
21
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
Cucumber::Rake::Task.new({:wip => 'test:prepare'}, 'Run features that are being worked on') do |t|
|
24
|
-
t.binary = vendored_cucumber_bin
|
25
|
-
t.fork = true # You may get faster startup if you set this to false
|
26
|
-
t.profile = 'wip'
|
27
|
-
end
|
22
|
+
Cucumber::Rake::Task.new({ wip: 'test:prepare' }, 'Run features that are being worked on') do |t|
|
23
|
+
t.binary = vendored_cucumber_bin
|
24
|
+
t.fork = true # You may get faster startup if you set this to false
|
25
|
+
t.profile = 'wip'
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
Cucumber::Rake::Task.new({ rerun: 'test:prepare' }, 'Record failing features and run only them if any exist') do |t|
|
29
|
+
t.binary = vendored_cucumber_bin
|
30
|
+
t.fork = true # You may get faster startup if you set this to false
|
31
|
+
t.profile = 'rerun'
|
32
|
+
end
|
34
33
|
|
35
|
-
|
36
|
-
|
34
|
+
desc 'Run all features'
|
35
|
+
task all: [:ok, :wip]
|
37
36
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
task :statsetup do
|
38
|
+
require 'rails/code_statistics'
|
39
|
+
::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features')
|
40
|
+
::CodeStatistics::TEST_TYPES << 'Cucumber features' if File.exist?('features')
|
41
|
+
end
|
42
42
|
end
|
43
|
-
|
44
|
-
|
45
|
-
task :cucumber => 'cucumber:ok'
|
43
|
+
desc 'Alias for cucumber:ok'
|
44
|
+
task cucumber: 'cucumber:ok'
|
46
45
|
|
47
|
-
|
46
|
+
task default: :cucumber
|
48
47
|
|
49
|
-
|
50
|
-
|
51
|
-
|
48
|
+
task features: :cucumber do
|
49
|
+
STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***"
|
50
|
+
end
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
# In case we don't have the generic Rails test:prepare hook, append a no-op task that we can depend upon.
|
53
|
+
task 'test:prepare' do
|
54
|
+
end
|
56
55
|
|
57
|
-
|
58
|
-
rescue LoadError
|
59
|
-
|
60
|
-
|
61
|
-
|
56
|
+
task stats: 'cucumber:statsetup'
|
57
|
+
rescue LoadError
|
58
|
+
desc 'cucumber rake task not available (cucumber not installed)'
|
59
|
+
task :cucumber do
|
60
|
+
abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin'
|
61
|
+
end
|
62
62
|
end
|
63
|
-
end
|
64
63
|
|
65
64
|
end
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# This file is copied to spec/ when you run 'rails generate rspec:install'
|
2
|
-
ENV[
|
3
|
-
require File.expand_path(
|
2
|
+
ENV['RAILS_ENV'] ||= 'test'
|
3
|
+
require File.expand_path('../../config/environment', __FILE__)
|
4
4
|
require 'rspec/rails'
|
5
5
|
|
6
6
|
# Requires supporting ruby files with custom matchers and macros, etc,
|
7
7
|
# in spec/support/ and its subdirectories.
|
8
|
-
Dir[Rails.root.join(
|
8
|
+
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
|
9
9
|
|
10
10
|
RSpec.configure do |config|
|
11
11
|
# ## Mock Framework
|
@@ -33,5 +33,5 @@ RSpec.configure do |config|
|
|
33
33
|
# order dependency and want to debug it, you can fix the order by providing
|
34
34
|
# the seed, which is printed after each run.
|
35
35
|
# --seed 1234
|
36
|
-
config.order =
|
36
|
+
config.order = 'random'
|
37
37
|
end
|
@@ -1,61 +1,59 @@
|
|
1
|
-
require
|
2
|
-
|
3
|
-
require_relative "../../../../lib/zeus/parallel_tests/worker"
|
1
|
+
require './lib/zeus/parallel_tests/worker'
|
4
2
|
|
5
3
|
describe Zeus::ParallelTests::Worker do
|
6
|
-
describe
|
7
|
-
let(:cli_argv) { [
|
8
|
-
let(:cli_env) { {
|
9
|
-
let(:worker) { double(
|
10
|
-
before { Zeus::ParallelTests::Worker.
|
4
|
+
describe '.run' do
|
5
|
+
let(:cli_argv) { ['rspec', 'spec/models/model_spec.rb'] }
|
6
|
+
let(:cli_env) { { 'TEST_ENV_NUMBER' => '3' } }
|
7
|
+
let(:worker) { double('worker', spawn: 0) }
|
8
|
+
before { allow(Zeus::ParallelTests::Worker).to receive_messages(new: worker) }
|
11
9
|
subject { Zeus::ParallelTests::Worker.run(cli_argv, cli_env) }
|
12
10
|
|
13
|
-
it
|
14
|
-
Zeus::ParallelTests::Worker.
|
15
|
-
.with(
|
11
|
+
it 'creates instance of worker' do
|
12
|
+
expect(Zeus::ParallelTests::Worker).to receive(:new)
|
13
|
+
.with('rspec', cli_env, ['spec/models/model_spec.rb'])
|
16
14
|
.and_return(worker)
|
17
15
|
subject
|
18
16
|
end
|
19
17
|
|
20
|
-
it
|
18
|
+
it 'does not modify original env and argv' do
|
21
19
|
subject
|
22
|
-
expect(cli_argv).to eq([
|
23
|
-
expect(cli_env).to eq(
|
20
|
+
expect(cli_argv).to eq(['rspec', 'spec/models/model_spec.rb'])
|
21
|
+
expect(cli_env).to eq('TEST_ENV_NUMBER' => '3')
|
24
22
|
end
|
25
23
|
|
26
|
-
it
|
24
|
+
it 'returns exit code' do
|
27
25
|
expect(subject).to eq(0)
|
28
26
|
end
|
29
27
|
end
|
30
28
|
|
31
|
-
describe
|
29
|
+
describe '#spawn' do
|
32
30
|
subject { worker.spawn }
|
33
|
-
let(:worker) { Zeus::ParallelTests::Worker.new(
|
34
|
-
let(:cli_env) { {
|
35
|
-
let(:argv_file) { double(
|
31
|
+
let(:worker) { Zeus::ParallelTests::Worker.new('rspec', cli_env, ['spec/file_spec.rb']) }
|
32
|
+
let(:cli_env) { { 'TEST_ENV_NUMBER' => 2, 'PARALLEL_TEST_GROUPS' => 4 } }
|
33
|
+
let(:argv_file) { double('argv_file', path: 'argv_file_path', unlink: true, puts: nil, close: nil) }
|
36
34
|
before do
|
37
|
-
Tempfile.
|
38
|
-
worker.
|
35
|
+
allow(Tempfile).to receive_messages(new: argv_file)
|
36
|
+
allow(worker).to receive_messages(system: true)
|
39
37
|
end
|
40
38
|
|
41
|
-
it
|
42
|
-
argv_file.
|
39
|
+
it 'writes args to file' do
|
40
|
+
expect(argv_file).to receive(:puts).with('spec/file_spec.rb')
|
43
41
|
subject
|
44
42
|
end
|
45
43
|
|
46
|
-
it
|
47
|
-
worker.
|
44
|
+
it 'spawns worker and passes TEST_ENV_NUMBER, PARALLEL_TEST_GROUPS and argv file path' do
|
45
|
+
expect(worker).to receive(:system).with('zeus parallel_rspec_worker 2 4 argv_file_path')
|
48
46
|
subject
|
49
47
|
end
|
50
48
|
|
51
|
-
it
|
52
|
-
argv_file.
|
49
|
+
it 'removes argv_file after run' do
|
50
|
+
expect(argv_file).to receive(:unlink)
|
53
51
|
subject
|
54
52
|
end
|
55
53
|
|
56
|
-
it
|
57
|
-
system
|
58
|
-
worker.
|
54
|
+
it 'returns exit code' do
|
55
|
+
system 'true'
|
56
|
+
expect(worker).to receive(:system) { allow($CHILD_STATUS).to receive_messages(to_i: 1) }
|
59
57
|
expect(subject).to eq(1)
|
60
58
|
end
|
61
59
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'zeus/parallel_tests/version'
|
4
|
+
require 'open3'
|
5
|
+
require 'English'
|
6
|
+
|
7
|
+
describe 'zeus parallel spec' do
|
8
|
+
def launch_server
|
9
|
+
pid = fork do
|
10
|
+
Dir.chdir 'spec/dummy/' do
|
11
|
+
exec 'bundle exec zeus start > /dev/null'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
sleep 3
|
15
|
+
pid
|
16
|
+
end
|
17
|
+
|
18
|
+
before(:all) do
|
19
|
+
# Copy current Appraisal gemfile to dummy app.
|
20
|
+
gemfile = File.read(ENV['BUNDLE_GEMFILE']).gsub(':path => "../"', ':path => "../../"')
|
21
|
+
File.open('spec/dummy/Gemfile', 'w+') { |f| f.write gemfile }
|
22
|
+
gemfile_lock = File.read("#{ENV['BUNDLE_GEMFILE']}.lock").gsub('remote: ../', 'remote: ../../')
|
23
|
+
File.open('spec/dummy/Gemfile.lock', 'w+') { |f| f.write gemfile_lock }
|
24
|
+
|
25
|
+
# Launch Zeus.
|
26
|
+
@server_pid = launch_server.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'connects to server' do
|
30
|
+
Dir.chdir 'spec/dummy/' do
|
31
|
+
system('bundle', 'exec', 'zeus', 'r', 'true')
|
32
|
+
expect($CHILD_STATUS.success?).to be true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'runs rspec specs in two processes' do
|
37
|
+
Dir.chdir 'spec/dummy' do
|
38
|
+
Open3.popen2e('bundle', 'exec', 'zeus', 'parallel_rspec', '-n', '2', 'spec') do |_, output|
|
39
|
+
expect(output.to_a.map(&:chomp)).to include('2 processes for 2 specs, ~ 1 specs per process')
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'runs cucumbers in two processes' do
|
45
|
+
Dir.chdir 'spec/dummy' do
|
46
|
+
Open3.popen2e('bundle', 'exec', 'zeus', 'parallel_cucumber', '-n', '2', 'features') do |_, output|
|
47
|
+
expect(output.to_a.map(&:chomp)).to include('2 processes for 2 features, ~ 1 features per process')
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
after(:all) do
|
53
|
+
system('kill', '-9', @server_pid)
|
54
|
+
system('rm', '-f', 'spec/dummy/Gemfile', 'spec/dummy/Gemfile.lock', 'spec/dummy/.zeus.sock')
|
55
|
+
end
|
56
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,14 +1,6 @@
|
|
1
|
-
|
2
|
-
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
-
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
-
# loaded once.
|
5
|
-
#
|
6
|
-
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
-
RSpec.configure do |config|
|
8
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
-
config.run_all_when_everything_filtered = true
|
10
|
-
config.filter_run :focus
|
1
|
+
require 'rspec'
|
11
2
|
|
3
|
+
RSpec.configure do |config|
|
12
4
|
# Run specs in random order to surface order dependencies. If you find an
|
13
5
|
# order dependency and want to debug it, you can fix the order by providing
|
14
6
|
# the seed, which is printed after each run.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
describe 'Configuration file generation' do
|
2
|
+
let(:project_dir) { File.expand_path(Dir.mktmpdir) }
|
3
|
+
let(:bin) { File.expand_path('../../bin/zeus-parallel_tests', __FILE__) }
|
4
|
+
|
5
|
+
subject { system(bin, 'init', chdir: project_dir) }
|
6
|
+
|
7
|
+
after { FileUtils.rm_rf project_dir }
|
8
|
+
|
9
|
+
it 'creates zeus configuration projects directory' do
|
10
|
+
subject
|
11
|
+
|
12
|
+
['zeus.json', 'custom_plan.rb'].each do |f|
|
13
|
+
expect(File.exist?(File.join(project_dir, f))).to be_truthy
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/zeus-parallel_tests.gemspec
CHANGED
@@ -4,24 +4,33 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
require 'zeus/parallel_tests/version'
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
7
|
+
spec.name = 'zeus-parallel_tests'
|
8
8
|
spec.version = Zeus::ParallelTests::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
9
|
+
spec.authors = ['Artur Roszczyk']
|
10
|
+
spec.email = ['artur.roszczyk@gmail.com']
|
11
|
+
spec.description = 'Integration for zeus and parallel_tests'
|
12
|
+
spec.summary = ''
|
13
|
+
spec.homepage = ''
|
14
|
+
spec.license = 'MIT'
|
15
15
|
|
16
|
-
spec.files = `git ls-files`.split(
|
16
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
19
|
+
spec.require_paths = ['lib']
|
20
20
|
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_dependency
|
21
|
+
spec.add_dependency 'zeus', '>= 0.13.0'
|
22
|
+
spec.add_dependency 'parallel_tests', '>= 0.11.3'
|
23
23
|
|
24
|
-
spec.add_development_dependency
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
24
|
+
spec.add_development_dependency 'appraisal'
|
25
|
+
spec.add_development_dependency 'bundler'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rubocop'
|
28
|
+
spec.add_development_dependency 'rspec', '>= 3.0'
|
29
|
+
|
30
|
+
# Gems used by dummy app in testing.
|
31
|
+
spec.add_development_dependency 'cucumber-rails'
|
32
|
+
spec.add_development_dependency 'database_cleaner'
|
33
|
+
spec.add_development_dependency 'guard-rspec'
|
34
|
+
spec.add_development_dependency 'rspec-rails'
|
35
|
+
spec.add_development_dependency 'sqlite3'
|
27
36
|
end
|