zeus-parallel_tests 0.2.4 → 0.3.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.
- 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
|