From 4826f079db415814f7b88437f3a5b77f8f84d152 Mon Sep 17 00:00:00 2001 From: Brian Nystrom and Kyle Annen Date: Mon, 4 Feb 2019 10:26:14 -0600 Subject: [PATCH 001/177] add exclude pattern support --- Readme.md | 1 + lib/parallel_tests/cli.rb | 1 + lib/parallel_tests/test/runner.rb | 15 ++++++++++++--- spec/fixtures/rails51/Gemfile.lock | 4 ++-- spec/fixtures/rails52/Gemfile.lock | 4 ++-- spec/integration_spec.rb | 10 ++++++++++ spec/parallel_tests/cli_spec.rb | 4 ++++ 7 files changed, 32 insertions(+), 7 deletions(-) diff --git a/Readme.md b/Readme.md index 1c1f6e0bf..34befbf13 100644 --- a/Readme.md +++ b/Readme.md @@ -195,6 +195,7 @@ Options are: -n [PROCESSES] How many processes to use, default: available CPUs -p, --pattern [PATTERN] run tests matching this regex pattern + --exclude-pattern [PATTERN] exclude tests matching this regex pattern --group-by [TYPE] group tests by: found - order of finding files steps - number of cucumber/spinach steps diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index bb506e15b..a7bda5917 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -164,6 +164,7 @@ def parse_options!(argv) BANNER opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs") { |n| options[:count] = n } opts.on("-p", "--pattern [PATTERN]", "run tests matching this regex pattern") { |pattern| options[:pattern] = /#{pattern}/ } + opts.on("--exclude-pattern", "--exclude-pattern [PATTERN]", "exclude tests matching this regex pattern") { |pattern| options[:exclude_pattern] = /#{pattern}/ } opts.on("--group-by [TYPE]", <<-TEXT.gsub(/^ /, '') group tests by: found - order of finding files diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index e7b379e10..bd355b487 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -209,14 +209,23 @@ def sort_by_filesize(tests) end def find_tests(tests, options = {}) - (tests || []).map do |file_or_folder| + files_list = (tests || []).map do |file_or_folder| if File.directory?(file_or_folder) files = files_in_folder(file_or_folder, options) - files.grep(options[:suffix]||test_suffix).grep(options[:pattern]||//) + files.grep(options[:suffix] || test_suffix) + .grep(options[:pattern] || //) else file_or_folder end - end.flatten.uniq + end + + flat_files_list = files_list.uniq.flat_map { |i| i } + + if regex = options[:exclude_pattern] + flat_files_list.reject! { |file| file =~ regex } + end + + flat_files_list end def files_in_folder(folder, options={}) diff --git a/spec/fixtures/rails51/Gemfile.lock b/spec/fixtures/rails51/Gemfile.lock index c8346cd3e..fd386b0bf 100644 --- a/spec/fixtures/rails51/Gemfile.lock +++ b/spec/fixtures/rails51/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.26.0) + parallel_tests (2.27.1) parallel GEM @@ -65,7 +65,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) - parallel (1.12.1) + parallel (1.13.0) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) diff --git a/spec/fixtures/rails52/Gemfile.lock b/spec/fixtures/rails52/Gemfile.lock index b204541b5..c1035324d 100644 --- a/spec/fixtures/rails52/Gemfile.lock +++ b/spec/fixtures/rails52/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.26.0) + parallel_tests (2.27.1) parallel GEM @@ -72,7 +72,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) - parallel (1.12.1) + parallel (1.13.0) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 7ffc7de4f..2c6366632 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -287,6 +287,16 @@ def test_unicode expect(result).to include('ZZZ') end + it "excludes test by given pattern and relative paths" do + write "spec/x_spec.rb", "puts 'XXX'" + write "spec/acceptance/y_spec.rb", "puts 'YYY'" + write "spec/integration/z_spec.rb", "puts 'ZZZ'" + result = run_tests "spec", :add => "--exclude-pattern 'spec/(integration|acceptance)'", :type => "rspec" + expect(result).to include('XXX') + expect(result).not_to include('YYY') + expect(result).not_to include('ZZZ') + end + it "can wait_for_other_processes_to_finish" do skip if RUBY_PLATFORM == "java" # just too slow ... write "test/a_test.rb", "require 'parallel_tests'; sleep 0.5 ; ParallelTests.wait_for_other_processes_to_finish; puts 'OutputA'" diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index aa14023c0..1d6583275 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -21,6 +21,10 @@ def call(*args) expect(call(["--exec", "echo"])).to eq(execute: "echo") end + it "parses excludes pattern" do + expect(call(["test", "--exclude-pattern", "spec/"])).to eq(defaults.merge(:exclude_pattern => /spec\//)) + end + it "parses regular count" do expect(call(["test", "-n3"])).to eq(defaults.merge(:count => 3)) end From cab2c8d1e77e00c8da7bf0b121b71edd13877a94 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 7 Feb 2019 10:31:00 -0800 Subject: [PATCH 002/177] cleanup pattern matching --- lib/parallel_tests/test/runner.rb | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index bd355b487..525e3745b 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -209,23 +209,20 @@ def sort_by_filesize(tests) end def find_tests(tests, options = {}) - files_list = (tests || []).map do |file_or_folder| + suffix_pattern = options[:suffix] || test_suffix + include_pattern = options[:pattern] || // + exclude_pattern = options[:exclude_pattern] + + (tests || []).flat_map do |file_or_folder| if File.directory?(file_or_folder) files = files_in_folder(file_or_folder, options) - files.grep(options[:suffix] || test_suffix) - .grep(options[:pattern] || //) + files = files.grep(suffix_pattern).grep(include_pattern) + files -= files.grep(exclude_pattern) if exclude_pattern + files else file_or_folder end - end - - flat_files_list = files_list.uniq.flat_map { |i| i } - - if regex = options[:exclude_pattern] - flat_files_list.reject! { |file| file =~ regex } - end - - flat_files_list + end.uniq end def files_in_folder(folder, options={}) From 27aad9fa9e3a43a185fbee98f44e6944f6610c1a Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 7 Feb 2019 10:45:49 -0800 Subject: [PATCH 003/177] v2.28.0 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b4cc64357..104f2ad1a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.27.1) + parallel_tests (2.28.0) parallel GEM @@ -35,7 +35,7 @@ GEM minitest (5.5.1) multi_json (1.13.1) multi_test (0.1.2) - parallel (1.12.1) + parallel (1.13.0) power_assert (0.4.1) rake (12.0.0) rspec (3.5.0) diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index f63d65641..7fa14456d 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.27.1' + VERSION = Version = '2.28.0' end From f8d4c0b43c216345ae1e07f143647c99bbe3e182 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 29 Apr 2019 09:21:10 -0700 Subject: [PATCH 004/177] remove todo --- Readme.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Readme.md b/Readme.md index 34befbf13..b825d263f 100644 --- a/Readme.md +++ b/Readme.md @@ -283,11 +283,6 @@ TIPS Contribute your own gotchas to the [Wiki](https://github.com/grosser/parallel_tests/wiki) or even better open a PR :) -TODO -==== - - fix tests vs cucumber >= 1.2 `unknown option --format` - - add unit tests for cucumber runtime formatter - Authors ==== inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rspec-suite) From f4bcfc62841b6b565914b2ddf9f95080d016664e Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 4 May 2019 11:55:33 -0700 Subject: [PATCH 005/177] update travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index a7df00f9c..0fe929ff8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,7 @@ rvm: - 2.3 - 2.4 - 2.5 + - 2.6 - ruby-head - jruby-head branches: @@ -17,3 +18,4 @@ matrix: - rvm: jruby-head fast_finish: true bundler_args: "--jobs 4" +before_install: ruby -e "Dir['{,spec/**/}Gemfile.lock'].each { |f| File.write(f, File.read(f).split('BUNDLED WITH').first)}" From 179ae09a72aadfaf302097552784d9681b0c2dde Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 4 May 2019 12:09:28 -0700 Subject: [PATCH 006/177] add additional verbosity options --- Readme.md | 6 ++- lib/parallel_tests/cli.rb | 8 ++-- lib/parallel_tests/test/runner.rb | 12 +++++- spec/integration_spec.rb | 25 +++++++++++-- spec/parallel_tests/cli_spec.rb | 61 ++++++++++++++++++------------- 5 files changed, 76 insertions(+), 36 deletions(-) diff --git a/Readme.md b/Readme.md index b825d263f..16b9520fb 100644 --- a/Readme.md +++ b/Readme.md @@ -224,8 +224,10 @@ Options are: --runtime-log [PATH] Location of previously recorded test runtimes --allowed-missing Allowed percentage of missing runtimes (default = 50) --unknown-runtime [FLOAT] Use given number as unknown runtime (otherwise use average time) - --verbose Print more output - --quiet Do not print anything, apart from test output + --verbose Print debug output + --verbose-process-command Print the command that will be executed by each process before it begins + --verbose-rerun-command After a process fails, print the command executed by that process + --quiet Print only test output -v, --version Show Version -h, --help Show this. diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index a7bda5917..ae8584be5 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -124,7 +124,7 @@ def report_failure_rerun_commmand(test_results, options) failing_sets = test_results.reject { |r| r[:exit_status] == 0 } return if failing_sets.none? - if options[:verbose] + if options[:verbose] || options[:verbose_rerun_command] puts "\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\n" failing_sets.each do |failing_set| command = failing_set[:command] @@ -219,8 +219,10 @@ def parse_options!(argv) opts.on("--allowed-missing [INT]", Integer, "Allowed percentage of missing runtimes (default = 50)") { |percent| options[:allowed_missing_percent] = percent } opts.on("--unknown-runtime [FLOAT]", Float, "Use given number as unknown runtime (otherwise use average time)") { |time| options[:unknown_runtime] = time } opts.on("--first-is-1", "Use \"1\" as TEST_ENV_NUMBER to not reuse the default test environment") { options[:first_is_1] = true } - opts.on("--verbose", "Print more output (mutually exclusive with quiet)") { options[:verbose] = true } - opts.on("--quiet", "Print tests output only (mutually exclusive with verbose)") { options[:quiet] = true } + opts.on("--verbose", "Print debug output") { options[:verbose] = true } + opts.on("--verbose-process-command", "Displays only the command that will be executed by each process") { options[:verbose_process_command] = true } + opts.on("--verbose-rerun-command", "When there are failures, displays the command executed by each process that failed") { options[:verbose_rerun_command] = true } + opts.on("--quiet", "Print only tests output") { options[:quiet] = true } opts.on("-v", "--version", "Show Version") { puts ParallelTests::VERSION; exit } opts.on("-h", "--help", "Show this.") { puts opts; exit } end.parse!(argv) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 525e3745b..dcba51288 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -78,7 +78,7 @@ def execute_command(cmd, process_number, num_processes, options) cmd = "nice #{cmd}" if options[:nice] cmd = "#{cmd} 2>&1" if options[:combine_stderr] - puts cmd if options[:verbose] && !options[:serialize_stdout] + puts cmd if report_process_command?(options) && !options[:serialize_stdout] execute_command_and_capture_output(env, cmd, options) end @@ -94,7 +94,9 @@ def execute_command_and_capture_output(env, cmd, options) exitstatus = $?.exitstatus seed = output[/seed (\d+)/,1] - output = [cmd, output].join("\n") if options[:verbose] && options[:serialize_stdout] + if report_process_command?(options) && options[:serialize_stdout] + output = [cmd, output].join("\n") + end {:stdout => output, :exit_status => exitstatus, :command => cmd, :seed => seed} end @@ -235,6 +237,12 @@ def files_in_folder(folder, options={}) end Dir[File.join(folder, pattern)].uniq end + + private + + def report_process_command?(options) + options[:verbose] || options[:verbose_process_command] + end end end end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 2c6366632..3fc3aecd2 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -60,6 +60,9 @@ def self.it_fails_without_any_files(type) end end + let(:printed_commands) { "specs per process\nbundle exec rspec" } + let(:printed_rerun) { "run the group again:\n\nbundle exec rspec" } + it "runs tests in parallel" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){puts "TEST2"}}' @@ -111,14 +114,30 @@ def test_unicode expect(result).to include('Took') end - it "shows command with --verbose" do + it "shows command and rerun with --verbose" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' - write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(1)}}' - result = run_tests "spec --verbose", :type => 'rspec' + write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' + result = run_tests "spec --verbose", :type => 'rspec', :fail => true + expect(result).to include printed_commands + expect(result).to include printed_rerun expect(result).to include "bundle exec rspec spec/xxx_spec.rb" expect(result).to include "bundle exec rspec spec/xxx2_spec.rb" end + it "shows only rerun with --verbose-rerun-command" do + write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' + result = run_tests "spec --verbose-rerun-command", :type => 'rspec', :fail => true + expect(result).to include printed_rerun + expect(result).to_not include printed_commands + end + + it "shows only process with --verbose-process-command" do + write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' + result = run_tests "spec --verbose-process-command", :type => 'rspec', :fail => true + expect(result).to_not include printed_rerun + expect(result).to include printed_commands + end + it "fails when tests fail" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 1d6583275..1a373aa03 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -50,6 +50,18 @@ def call(*args) expect(call(["test", "--verbose"])).to eq(defaults.merge(:verbose => true)) end + it "parses --verbose-process-command" do + expect(call(['test', '--verbose-process-command'])).to eq( + defaults.merge(verbose_process_command: true) + ) + end + + it "parses --verbose-rerun-command" do + expect(call(['test', '--verbose-rerun-command'])).to eq( + defaults.merge(verbose_rerun_command: true) + ) + end + it "parses --quiet" do expect(call(["test", "--quiet"])).to eq(defaults.merge(:quiet => true)) end @@ -155,6 +167,8 @@ def call(*args) end describe ".report_failure_rerun_commmand" do + let(:single_failed_command) { [{exit_status: 1, command: 'foo', seed: nil, output: 'blah'}] } + it "prints nothing if there are no failures" do expect($stdout).not_to receive(:puts) @@ -166,37 +180,35 @@ def call(*args) ) end - shared_examples :not_verbose_rerun do |options| + def self.it_prints_nothing_about_rerun_commands(options) it 'prints nothing about rerun commands' do - expect { - subject.send(:report_failure_rerun_commmand, - [ - {exit_status: 1, command: 'foo', seed: nil, output: 'blah'} - ], - options - ) - }.to_not output(/Use the following command to run the group again/).to_stdout + expect { + subject.send(:report_failure_rerun_commmand, single_failed_command, options) + }.to_not output(/Use the following command to run the group again/).to_stdout end end describe "failure" do - context 'with empty options hash' do - include_examples :not_verbose_rerun, {} + context 'without options' do + it_prints_nothing_about_rerun_commands({}) + end + + context 'with verbose disabled' do + it_prints_nothing_about_rerun_commands(verbose: false) end - context 'with option !verbose' do - include_examples :not_verbose_rerun, {verbose: false} + context "with verbose rerun" do + it "prints command if there is a failure" do + expect { + subject.send(:report_failure_rerun_commmand, single_failed_command, verbose_rerun_command: true) + }.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout + end end - context 'with option verbose' do + context 'with verbose' do it "prints a message and the command if there is a failure" do expect { - subject.send(:report_failure_rerun_commmand, - [ - {exit_status: 1, command: 'foo', seed: nil, output: 'blah'} - ], - {verbose: true} - ) + subject.send(:report_failure_rerun_commmand, single_failed_command, verbose: true) }.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout end @@ -233,13 +245,10 @@ def call(*args) subject.instance_variable_set(:@runner, ParallelTests::Test::Runner) expect(ParallelTests::Test::Runner).to receive(:command_with_seed).with(command, seed). and_return("my seeded command result --seed #{seed}") + single_failed_command[0].merge!(seed: seed, command: command) + expect { - subject.send(:report_failure_rerun_commmand, - [ - {exit_status: 1, command: command, seed: 555, output: 'blah'}, - ], - {verbose: true} - ) + subject.send(:report_failure_rerun_commmand, single_failed_command, verbose: true) }.to output(/my seeded command result --seed 555/).to_stdout end end From 26b4b93e03b75311c7388dc115122fc8986544fa Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 4 May 2019 14:02:38 -0700 Subject: [PATCH 007/177] thx for the PR --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 16b9520fb..421dd4897 100644 --- a/Readme.md +++ b/Readme.md @@ -372,6 +372,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Justin Doody](https://github.com/justindoody) - [Sandeep Singh](https://github.com/sandeepnagra) - [Calaway](https://github.com/calaway) + - [alboyadjian](https://github.com/alboyadjian) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 9bf7d525bd4a6d9865e3664d95dd670c6ab76b73 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 4 May 2019 14:02:49 -0700 Subject: [PATCH 008/177] v2.29.0 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 104f2ad1a..3f0630d05 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.28.0) + parallel_tests (2.29.0) parallel GEM @@ -35,7 +35,7 @@ GEM minitest (5.5.1) multi_json (1.13.1) multi_test (0.1.2) - parallel (1.13.0) + parallel (1.17.0) power_assert (0.4.1) rake (12.0.0) rspec (3.5.0) diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 7fa14456d..5358c7c75 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.28.0' + VERSION = Version = '2.29.0' end From acad0196228daeda1c302763bd28178e755d803f Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 13 Jun 2019 07:59:11 -0700 Subject: [PATCH 009/177] require the lib we are using --- lib/parallel_tests/tasks.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 2fa8db2e9..c885e750f 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -1,4 +1,5 @@ require 'rake' +require 'shellwords' module ParallelTests module Tasks From b53473527d5399b141a03706361d50f75320b0fb Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 13 Jun 2019 08:07:57 -0700 Subject: [PATCH 010/177] v2.29.1 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3f0630d05..636c62e37 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.29.0) + parallel_tests (2.29.1) parallel GEM @@ -74,4 +74,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 1.16.5 + 1.17.3 diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 5358c7c75..79798a9c7 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.29.0' + VERSION = Version = '2.29.1' end From c271895205ba3b68d60997d97c8a96fbb5f51644 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 30 Jul 2019 00:01:02 +0900 Subject: [PATCH 011/177] :warning: ambiguous first argument; put parentheses or a space even after `/' operator --- spec/parallel_tests/gherkin/runner_behaviour.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/parallel_tests/gherkin/runner_behaviour.rb b/spec/parallel_tests/gherkin/runner_behaviour.rb index 558edd44d..546bb3347 100644 --- a/spec/parallel_tests/gherkin/runner_behaviour.rb +++ b/spec/parallel_tests/gherkin/runner_behaviour.rb @@ -15,7 +15,7 @@ def call(*args) it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec' - should_run_with /script\/custom_rspec/ + should_run_with(/script\/custom_rspec/) call(['xxx'], 1, 22, {}) end From 97598195c603a14b97e32343d735a66d397c930b Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 30 Jul 2019 00:03:31 +0900 Subject: [PATCH 012/177] :warning: method redefined `pids` method is redefined at line 34 --- lib/parallel_tests/pids.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parallel_tests/pids.rb b/lib/parallel_tests/pids.rb index 025182aab..eb6b4c43a 100644 --- a/lib/parallel_tests/pids.rb +++ b/lib/parallel_tests/pids.rb @@ -2,7 +2,7 @@ module ParallelTests class Pids - attr_reader :pids, :file_path, :mutex + attr_reader :file_path, :mutex def initialize(file_path) @file_path = file_path From 48abe7269fa1108232d1ecdd12fedb423c8aa878 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 30 Jul 2019 00:04:40 +0900 Subject: [PATCH 013/177] :warning: assigned but unused variable - out --- spec/parallel_tests/test/runner_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index f5f3d73df..502fe07fe 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -475,7 +475,7 @@ def run_with_file(content) it "prints each stream to the correct stream" do skip "open3" - out, err = run_with_file("puts 123 ; $stderr.puts 345 ; exit 5") do |path| + _out, err = run_with_file("puts 123 ; $stderr.puts 345 ; exit 5") do |path| result = call("ruby #{path}", 1, 4, {}) expect(result).to include({ :stdout => "123\n", From 636ca65c8b8434efff7e9904f6a12130e29de730 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 30 Jul 2019 00:07:18 +0900 Subject: [PATCH 014/177] :warning: instance variable @feature, @ignore_tag_pattern not initialized --- lib/parallel_tests/gherkin/listener.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/parallel_tests/gherkin/listener.rb b/lib/parallel_tests/gherkin/listener.rb index 368e940c7..57fdbfffe 100644 --- a/lib/parallel_tests/gherkin/listener.rb +++ b/lib/parallel_tests/gherkin/listener.rb @@ -10,6 +10,7 @@ class Listener def initialize @steps, @uris = [], [] @collect = {} + @feature, @ignore_tag_pattern = nil reset_counters! end From e96a0e1bdcad98a614cc4da448c4c9ffe491d917 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 6 Aug 2019 13:06:36 -0700 Subject: [PATCH 015/177] v2.29.2 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 636c62e37..00d289b4f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.29.1) + parallel_tests (2.29.2) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 79798a9c7..e049ad5f8 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.29.1' + VERSION = Version = '2.29.2' end From 5a06939dfcb81e1ab603982a36600a140ff83619 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sat, 7 Dec 2019 17:36:27 +0700 Subject: [PATCH 016/177] Fix "Invalid gemspec in [.../parallel_tests.gemspec]: cannot load such file -- ./lib/parallel_tests/version" crash when using local git repo with Bundler --- parallel_tests.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 4e3f47222..f3e7bdb1e 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -1,5 +1,5 @@ name = "parallel_tests" -require "./lib/#{name}/version" +require_relative "lib/#{name}/version" Gem::Specification.new name, ParallelTests::VERSION do |s| s.summary = "Run Test::Unit / RSpec / Cucumber / Spinach in parallel" From 28a607a0336cc82cb42071694a210a93b6e071cb Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sat, 7 Dec 2019 19:44:14 +0700 Subject: [PATCH 017/177] Run rake tasks with bin/rake if it exists, to use the Spring preloader --- lib/parallel_tests/tasks.rb | 42 +++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index c885e750f..7f97fc23a 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -8,6 +8,14 @@ def rails_env ENV['RAILS_ENV'] || 'test' end + def rake_bin + # Prevent 'Exec format error' Errno::ENOEXEC on Windows + return "rake" if RUBY_PLATFORM =~ /mswin|mingw|cygwin/ + binstub_path = File.join('bin', 'rake') + return binstub_path if File.exist?(binstub_path) + "rake" + end + def load_lib $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..')) require "parallel_tests" @@ -89,18 +97,21 @@ def parse_args(args) namespace :parallel do desc "Setup test databases via db:setup --> parallel:setup[num_cpus]" task :setup, :count do |_,args| - command = "rake db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}" + command = "#{ParallelTests::Tasks.rake_bin} db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}" ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end desc "Create test databases via db:create --> parallel:create[num_cpus]" task :create, :count do |_,args| - ParallelTests::Tasks.run_in_parallel("rake db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + ParallelTests::Tasks.run_in_parallel( + "#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end desc "Drop test databases via db:drop --> parallel:drop[num_cpus]" task :drop, :count do |_,args| - ParallelTests::Tasks.run_in_parallel("rake db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args) + ParallelTests::Tasks.run_in_parallel( + "#{ParallelTests::Tasks.rake_bin} db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} " \ + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args) end desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]" @@ -114,42 +125,50 @@ def parse_args(args) # there is no separate dump / load for schema_format :sql -> do it safe and slow args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil taskname = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' - ParallelTests::Tasks.run_in_parallel("rake #{taskname}", args) + ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{taskname}", args) end end # when dumping/resetting takes too long desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]" task :migrate, :count do |_,args| - ParallelTests::Tasks.run_in_parallel("rake db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + ParallelTests::Tasks.run_in_parallel( + "#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]" task :rollback, :count do |_,args| - ParallelTests::Tasks.run_in_parallel("rake db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + ParallelTests::Tasks.run_in_parallel( + "#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end # just load the schema (good for integration server <-> no development db) desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" task :load_schema, :count do |_,args| - command = "rake #{ParallelTests::Tasks.purge_before_load} db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + command = "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ + "db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1" ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end # load the structure from the structure.sql file desc "Load structure for test databases via db:structure:load --> parallel:load_structure[num_cpus]" task :load_structure, :count do |_,args| - ParallelTests::Tasks.run_in_parallel("rake #{ParallelTests::Tasks.purge_before_load} db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args) + ParallelTests::Tasks.run_in_parallel( + "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ + "db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args) end desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]" task :seed, :count do |_,args| - ParallelTests::Tasks.run_in_parallel("rake db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + ParallelTests::Tasks.run_in_parallel( + "#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) end desc "Launch given rake command in parallel" task :rake, :command, :count do |_, args| - ParallelTests::Tasks.run_in_parallel("RAILS_ENV=#{ParallelTests::Tasks.rails_env} rake #{args.command}", args) + ParallelTests::Tasks.run_in_parallel( + "RAILS_ENV=#{ParallelTests::Tasks.rails_env} #{ParallelTests::Tasks.rake_bin} " \ + "#{args.command}", args) end ['test', 'spec', 'features', 'features-spinach'].each do |type| @@ -172,7 +191,8 @@ def parse_args(args) # Using the relative path to find the binary allow to run a specific version of it executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') - command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} --type #{test_framework} " \ + command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} " \ + "--type #{test_framework} " \ "-n #{count} " \ "--pattern '#{pattern}' " \ "--test-options '#{options}' " \ From 7c034cc7595e5fb9ec7da484e215e0d635cd2a24 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sat, 7 Dec 2019 19:05:42 +0700 Subject: [PATCH 018/177] Added info about the spring-commands-parallel-tests gem to get everything working with Spring --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 421dd4897..a0caee2b9 100644 --- a/Readme.md +++ b/Readme.md @@ -273,7 +273,7 @@ TIPS - Debug errors that only happen with multiple files using `--verbose` and [cleanser](https://github.com/grosser/cleanser) - `export PARALLEL_TEST_PROCESSORS=13` to override default processor count - Shell alias: `alias prspec='parallel_rspec -m 2 --'` - - [Spring] to use spring you have to [patch it](https://github.com/grosser/parallel_tests/wiki/Spring) + - [Spring] Add the [spring-commands-parallel-tests](https://github.com/DocSpring/spring-commands-parallel-tests) gem to your `Gemfile` to get `parallel_tests` working with Spring. - `--first-is-1` will make the first environment be `1`, so you can test while running your full suite.
`export PARALLEL_TEST_FIRST_IS_1=true` will provide the same result - [email_spec and/or action_mailer_cache_delivery](https://github.com/grosser/parallel_tests/wiki) From de5cfea4436b545fcd072ab32122667480480c70 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 7 Dec 2019 11:53:51 -0800 Subject: [PATCH 019/177] thx for the PRs --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index a0caee2b9..47367fe6b 100644 --- a/Readme.md +++ b/Readme.md @@ -373,6 +373,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Sandeep Singh](https://github.com/sandeepnagra) - [Calaway](https://github.com/calaway) - [alboyadjian](https://github.com/alboyadjian) + - [Nathan Broadbent](https://github.com/ndbroadbent) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 6b1a6f7de9d0429651fcb4f9638e186ebbf5a2be Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sun, 8 Dec 2019 03:59:04 +0700 Subject: [PATCH 020/177] Use db:structure:dump and parallel:load_structure for :sql schema_format. Clear the database connection before loading schema/structure to prevent "database is being accessed by other users" error --- Readme.md | 2 +- lib/parallel_tests/tasks.rb | 17 +++++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Readme.md b/Readme.md index 47367fe6b..53ff340f1 100644 --- a/Readme.md +++ b/Readme.md @@ -266,7 +266,7 @@ TIPS - Builds a HTML report from JSON with support for debug msgs & embedded Base64 images. ### General - - [SQL schema format] use :ruby schema format to get faster parallel:prepare` + - [SQL schema format] use [the `:sql` schema format](https://guides.rubyonrails.org/active_record_migrations.html#types-of-schema-dumps) to get faster parallel:prepare` - [ZSH] use quotes to use rake arguments `rake "parallel:prepare[3]"` - [Memcached] use different namespaces
e.g. `config.cache_store = ..., namespace: "test_#{ENV['TEST_ENV_NUMBER']}"` diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 7f97fc23a..ec5cbb575 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -117,16 +117,21 @@ def parse_args(args) desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]" task(:prepare, [:count]) do |_,args| ParallelTests::Tasks.check_for_pending_migrations - if defined?(ActiveRecord) && ActiveRecord::Base.schema_format == :ruby - # dump then load in parallel - Rake::Task['db:schema:dump'].invoke - Rake::Task['parallel:load_schema'].invoke(args[:count]) - else - # there is no separate dump / load for schema_format :sql -> do it safe and slow + # dump schema/structure then load in parallel + unless defined?(ActiveRecord::Base) args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil taskname = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{taskname}", args) + next end + + task_name = ActiveRecord::Base.schema_format == :ruby ? :schema : :structure + Rake::Task["db:#{task_name}:dump"].invoke + if defined?(ActiveRecord::Base) && ActiveRecord::Base.configurations.any? + # Must remove database connection to prevent "database is being accessed by other users" + ActiveRecord::Base.remove_connection + end + Rake::Task["parallel:load_#{task_name}"].invoke(args[:count]) end # when dumping/resetting takes too long From 2d41658b470af26b250024ffb10e541984b95e82 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sun, 8 Dec 2019 03:12:24 +0700 Subject: [PATCH 021/177] Fix flaky test by removing the .ordered expectation, since the tests are run in parallel threads and there are no guarantees about the execution order --- spec/parallel_tests/cli_spec.rb | 4 ++-- spec/rails_spec.rb | 2 -- spec/spec_helper.rb | 6 ------ 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 1a373aa03..1fa9e242b 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -315,8 +315,8 @@ def self.it_prints_nothing_about_rerun_commands(options) it "run twice with multiple groups" do skip "fails on jruby" if RUBY_PLATFORM == "java" options = common_options.merge(count: 3, only_group: [2,3]) - expect(subject).to receive(:run_tests).once.ordered.with(['ccc', 'ddd'], 0, 1, options).and_return(results) - expect(subject).to receive(:run_tests).once.ordered.with(['eee', 'fff'], 1, 1, options).and_return(results) + expect(subject).to receive(:run_tests).once.with(['ccc', 'ddd'], 0, 1, options).and_return(results) + expect(subject).to receive(:run_tests).once.with(['eee', 'fff'], 1, 1, options).and_return(results) subject.run(['test', '-n', '3', '--only-group', '2,3', '-t', 'my_test_runner']) end end diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 78a7b53b9..c9391b500 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -1,8 +1,6 @@ require 'spec_helper' describe 'rails' do - let(:test_timeout) { 420 } # this can take very long on fresh bundle ... - def sh(command, options={}) result = '' IO.popen(options.fetch(:environment, {}), command, err: [:child, :out]) do |io| diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 99426980d..ef40f50ba 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -188,12 +188,6 @@ def setup_runtime_log config.raise_errors_for_deprecations! - # sometimes stuff hangs -> do not hang everything - config.include(Module.new {def test_timeout;30;end }) - config.around do |example| - Timeout.timeout(test_timeout, &example) - end - config.after do ENV.delete "PARALLEL_TEST_GROUPS" ENV.delete "PARALLEL_TEST_PROCESSORS" From 550eafbe2736dcdaba6bb7bea9ddcf5c14cd3914 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sun, 8 Dec 2019 03:18:50 +0700 Subject: [PATCH 022/177] Cache gems in spec/fixtures/{rails51,rails52}/vendor/bundle to speed up CI builds --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0fe929ff8..be05baa76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,7 +11,11 @@ rvm: branches: only: [master] sudo: false -cache: bundler +cache: + bundler: true + directories: + - spec/fixtures/rails51/vendor/bundle + - spec/fixtures/rails52/vendor/bundle matrix: allow_failures: - rvm: ruby-head From a793d8fa8594b51ce6e603d97e6336911deca538 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sun, 8 Dec 2019 16:56:49 +0700 Subject: [PATCH 023/177] Fix another flaky test by adding a "TEST" prefix to more of the output expectations. (Failing build: https://travis-ci.org/grosser/parallel_tests/jobs/622216736?utm_medium=notification&utm_source=github_status) --- spec/integration_spec.rb | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 3fc3aecd2..45cdc63f3 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -229,7 +229,7 @@ def test_unicode it "runs with --group-by found" do # it only tests that it does not blow up, as it did before fixing... - write "spec/x1_spec.rb", "puts '111'" + write "spec/x1_spec.rb", "puts 'TEST111'" run_tests "spec", :type => 'rspec', :add => '--group-by found' end @@ -254,27 +254,27 @@ def test_unicode end it "runs with files that have spaces" do - write "test/xxx _test.rb", 'puts "YES"' + write "test/xxx _test.rb", 'puts "TEST_SUCCESS"' result = run_tests("test", processes: 2, type: 'test') - expect(result).to include "YES" + expect(result).to include "TEST_SUCCESS" end it "uses relative paths for easy copying" do - write "test/xxx_test.rb", 'puts "YES"' + write "test/xxx_test.rb", 'puts "Test output: YES"' result = run_tests("test", processes: 2, type: 'test', add: '--verbose') - expect(result).to include "YES" + expect(result).to include "Test output: YES" expect(result).to include "[test/xxx_test.rb]" expect(result).not_to include Dir.pwd end it "can run with given files" do - write "spec/x1_spec.rb", "puts '111'" - write "spec/x2_spec.rb", "puts '222'" - write "spec/x3_spec.rb", "puts '333'" + write "spec/x1_spec.rb", "puts 'TEST111'" + write "spec/x2_spec.rb", "puts 'TEST222'" + write "spec/x3_spec.rb", "puts 'TEST333'" result = run_tests "spec/x1_spec.rb spec/x3_spec.rb", :type => 'rspec' - expect(result).to include('111') - expect(result).to include('333') - expect(result).not_to include('222') + expect(result).to include('TEST111') + expect(result).to include('TEST333') + expect(result).not_to include('TEST222') end it "can run with test-options" do @@ -297,23 +297,23 @@ def test_unicode end it "filters test by given pattern and relative paths" do - write "spec/x_spec.rb", "puts 'XXX'" - write "spec/y_spec.rb", "puts 'YYY'" - write "spec/z_spec.rb", "puts 'ZZZ'" + write "spec/x_spec.rb", "puts 'TESTXXX'" + write "spec/y_spec.rb", "puts 'TESTYYY'" + write "spec/z_spec.rb", "puts 'TESTZZZ'" result = run_tests "spec", :add => "-p '^spec/(x|z)'", :type => "rspec" - expect(result).to include('XXX') - expect(result).not_to include('YYY') - expect(result).to include('ZZZ') + expect(result).to include('TESTXXX') + expect(result).not_to include('TESTYYY') + expect(result).to include('TESTZZZ') end it "excludes test by given pattern and relative paths" do - write "spec/x_spec.rb", "puts 'XXX'" - write "spec/acceptance/y_spec.rb", "puts 'YYY'" - write "spec/integration/z_spec.rb", "puts 'ZZZ'" + write "spec/x_spec.rb", "puts 'TESTXXX'" + write "spec/acceptance/y_spec.rb", "puts 'TESTYYY'" + write "spec/integration/z_spec.rb", "puts 'TESTZZZ'" result = run_tests "spec", :add => "--exclude-pattern 'spec/(integration|acceptance)'", :type => "rspec" - expect(result).to include('XXX') - expect(result).not_to include('YYY') - expect(result).not_to include('ZZZ') + expect(result).to include('TESTXXX') + expect(result).not_to include('TESTYYY') + expect(result).not_to include('TESTZZZ') end it "can wait_for_other_processes_to_finish" do From e48578eb0075a02f384a47637fc48bdd35cdce37 Mon Sep 17 00:00:00 2001 From: Nathan Broadbent Date: Sun, 8 Dec 2019 18:29:03 +0700 Subject: [PATCH 024/177] Decrease PARALLEL_TEST_HEARTBEAT_INTERVAL to fix occasional test failure (example: https://ci.appveyor.com/project/grosser/parallel-tests/builds/29391856/job/8j2dqxd7duf10gra) --- spec/integration_spec.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 45cdc63f3..71404cdab 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -160,15 +160,13 @@ def test_unicode it "can show simulated output when serializing stdout" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 0.5; puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST2"}}' - result = run_tests "spec", :type => 'rspec', :add => "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.1'} - + result = run_tests "spec", :type => 'rspec', :add => "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01'} expect(result).to match(/\.{4}.*TEST1.*\.{4}.*TEST2/m) end it "can show simulated output preceded by command when serializing stdout with verbose option" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST1"}}' - result = run_tests "spec --verbose", :type => 'rspec', :add => "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.2'} - + result = run_tests "spec --verbose", :type => 'rspec', :add => "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02'} expect(result).to match(/\.{5}.*\nbundle exec rspec spec\/xxx_spec\.rb\nTEST1/m) end From ed1a9dd6678a429ebcc1fe99c70d306a24447449 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 8 Dec 2019 17:04:53 -0800 Subject: [PATCH 025/177] cleanup task logic more --- Readme.md | 1 - lib/parallel_tests/tasks.rb | 25 +++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Readme.md b/Readme.md index 53ff340f1..44ed4db5f 100644 --- a/Readme.md +++ b/Readme.md @@ -266,7 +266,6 @@ TIPS - Builds a HTML report from JSON with support for debug msgs & embedded Base64 images. ### General - - [SQL schema format] use [the `:sql` schema format](https://guides.rubyonrails.org/active_record_migrations.html#types-of-schema-dumps) to get faster parallel:prepare` - [ZSH] use quotes to use rake arguments `rake "parallel:prepare[3]"` - [Memcached] use different namespaces
e.g. `config.cache_store = ..., namespace: "test_#{ENV['TEST_ENV_NUMBER']}"` diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index ec5cbb575..415ac1fc1 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -117,21 +117,22 @@ def parse_args(args) desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]" task(:prepare, [:count]) do |_,args| ParallelTests::Tasks.check_for_pending_migrations - # dump schema/structure then load in parallel - unless defined?(ActiveRecord::Base) + if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format) + # fast: dump once, load in parallel + type = (ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure") + Rake::Task["db:#{type}:dump"].invoke + + # remove database connection to prevent "database is being accessed by other users" + ActiveRecord::Base.remove_connection if ActiveRecord::Base.configurations.any? + + Rake::Task["parallel:load_#{type}"].invoke(args[:count]) + else + # slow: dump and load in in serial args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil - taskname = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' - ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{taskname}", args) + task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' + ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{task_name}", args) next end - - task_name = ActiveRecord::Base.schema_format == :ruby ? :schema : :structure - Rake::Task["db:#{task_name}:dump"].invoke - if defined?(ActiveRecord::Base) && ActiveRecord::Base.configurations.any? - # Must remove database connection to prevent "database is being accessed by other users" - ActiveRecord::Base.remove_connection - end - Rake::Task["parallel:load_#{task_name}"].invoke(args[:count]) end # when dumping/resetting takes too long From d3a5ffc895ce773eea3a4ba17ce8bda1ee6bd205 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 9 Dec 2019 21:46:02 -0800 Subject: [PATCH 026/177] v2.30.0 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 00d289b4f..e156649de 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.29.2) + parallel_tests (2.30.0) parallel GEM @@ -35,7 +35,7 @@ GEM minitest (5.5.1) multi_json (1.13.1) multi_test (0.1.2) - parallel (1.17.0) + parallel (1.19.1) power_assert (0.4.1) rake (12.0.0) rspec (3.5.0) diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index e049ad5f8..5d224c561 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.29.2' + VERSION = Version = '2.30.0' end From afa088bd3f452fbd7cd665889bcd62fe7e49139e Mon Sep 17 00:00:00 2001 From: Orien Madgwick <_@orien.io> Date: Thu, 12 Dec 2019 08:14:38 +1100 Subject: [PATCH 027/177] Add project metadata to the gemspec As per https://guides.rubygems.org/specification-reference/#metadata, add metadata to the gemspec file. This'll allow people to more easily access the source code, raise issues and read the wiki. These `bug_tracker_uri`, `wiki_uri`, `documentation_uri` and `source_code_uri` links will appear on the rubygems page at https://rubygems.org/gems/parallel_tests and be available via the rubygems API after the next release. --- parallel_tests.gemspec | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index f3e7bdb1e..2b795f422 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -6,6 +6,12 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.authors = ["Michael Grosser"] s.email = "michael@grosser.it" s.homepage = "http://github.com/grosser/#{name}" + s.metadata = { + "bug_tracker_uri" => "https://github.com/grosser/#{name}/issues", + "documentation_uri" => "https://github.com/grosser/#{name}/blob/v#{s.version}/Readme.md", + "source_code_uri" => "https://github.com/grosser/#{name}/tree/v#{s.version}", + "wiki_uri" => "https://github.com/grosser/#{name}/wiki", + } s.files = Dir["{lib,bin}/**/*"] + ["Readme.md"] s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] From f14266f3dd0ed770518bb5dfb295cd5e1a6c69fb Mon Sep 17 00:00:00 2001 From: Orien Madgwick <_@orien.io> Date: Thu, 12 Dec 2019 08:15:17 +1100 Subject: [PATCH 028/177] Use TLS for the homepage URI --- parallel_tests.gemspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 2b795f422..484d4472b 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -5,7 +5,7 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.summary = "Run Test::Unit / RSpec / Cucumber / Spinach in parallel" s.authors = ["Michael Grosser"] s.email = "michael@grosser.it" - s.homepage = "http://github.com/grosser/#{name}" + s.homepage = "https://github.com/grosser/#{name}" s.metadata = { "bug_tracker_uri" => "https://github.com/grosser/#{name}/issues", "documentation_uri" => "https://github.com/grosser/#{name}/blob/v#{s.version}/Readme.md", From d1400f69867ba1ea1c95c9ae6167a7900a5ce74d Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Wed, 18 Dec 2019 09:39:16 -0600 Subject: [PATCH 029/177] bring back test timeouts --- spec/rails_spec.rb | 3 +++ spec/spec_helper.rb | 9 +++++++++ 2 files changed, 12 insertions(+) diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index c9391b500..22fac5095 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -1,6 +1,8 @@ require 'spec_helper' describe 'rails' do + let(:test_timeout) { 600 } # this can take very long on fresh bundle ... + def sh(command, options={}) result = '' IO.popen(options.fetch(:environment, {}), command, err: [:child, :out]) do |io| @@ -10,6 +12,7 @@ def sh(command, options={}) result end + # TODO: rails 6 %w(rails51 rails52).each do |rails| it "can create and run #{rails}" do if RUBY_PLATFORM == "java" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ef40f50ba..2251a749d 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -180,6 +180,8 @@ def setup_runtime_log end end +TestTookTooLong = Class.new(Timeout::Error) + RSpec.configure do |config| config.filter_run :focus => true config.run_all_when_everything_filtered = true @@ -188,6 +190,13 @@ def setup_runtime_log config.raise_errors_for_deprecations! + # sometimes stuff hangs -> do not hang everything + # NOTE: the timeout error can sometimes swallow errors, comment it out if you run into trouble + config.include(Module.new {def test_timeout;30;end }) + config.around do |example| + Timeout.timeout(test_timeout, TestTookTooLong, &example) + end + config.after do ENV.delete "PARALLEL_TEST_GROUPS" ENV.delete "PARALLEL_TEST_PROCESSORS" From 5473259d97927650eeec419f5b91d74bcfc17f03 Mon Sep 17 00:00:00 2001 From: Tobias Kaesser Date: Tue, 14 Jan 2020 16:57:03 +0100 Subject: [PATCH 030/177] (deprecation) switched from 'bundle show' to 'bundle info', get rid of deprecation-warning --- lib/parallel_tests/rspec/runner.rb | 2 +- spec/parallel_tests/rspec/runner_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index 09ad6e3e7..1a3d90b91 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -18,7 +18,7 @@ def determine_executable when File.exist?("bin/rspec") ParallelTests.with_ruby_binary("bin/rspec") when ParallelTests.bundler_enabled? - cmd = (run("bundle show rspec-core") =~ %r{Could not find gem.*} ? "spec" : "rspec") + cmd = (run("bundle info rspec-core") =~ %r{Could not find gem.*} ? "spec" : "rspec") "bundle exec #{cmd}" else %w[spec rspec].detect{|cmd| system "#{cmd} --version > #{DEV_NULL} 2>&1" } diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index 54cf22fe8..5dc013717 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -55,7 +55,7 @@ def call(*args) expect(File).to receive(:file?).with('spec/parallel_spec.opts').and_return true allow(ParallelTests).to receive(:bundler_enabled?).and_return true - allow(ParallelTests::RSpec::Runner).to receive(:run).with("bundle show rspec-core").and_return "/foo/bar/rspec-core-2.4.2" + allow(ParallelTests::RSpec::Runner).to receive(:run).with("bundle info rspec-core").and_return "/foo/bar/rspec-core-2.4.2" should_run_with %r{rspec\s+(--color --tty )?-O spec/parallel_spec.opts} call('xxx', 1, 22, {}) From 0a5591609750d5ae8c7feb7d25bf25ee695e9a38 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 14 Jan 2020 08:42:53 -0800 Subject: [PATCH 031/177] v2.30.1 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index e156649de..611bd0eca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.30.0) + parallel_tests (2.30.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 5d224c561..946337167 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.30.0' + VERSION = Version = '2.30.1' end From 05f59d35058f1b988b3ea51652b4044e2dd8df59 Mon Sep 17 00:00:00 2001 From: Yury Druzhkov Date: Thu, 30 Jan 2020 20:34:32 +0300 Subject: [PATCH 032/177] Clean file path from cli --- lib/parallel_tests/cli.rb | 3 ++- spec/parallel_tests/cli_spec.rb | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index ae8584be5..fcd99df1e 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -2,6 +2,7 @@ require 'tempfile' require 'parallel_tests' require 'shellwords' +require 'pathname' module ParallelTests class CLI @@ -239,7 +240,7 @@ def parse_options!(argv) files, remaining = extract_file_paths(argv) unless options[:execute] abort "Pass files or folders to run" unless files.any? - options[:files] = files + options[:files] = files.map { |file_path| Pathname.new(file_path).cleanpath.to_s } end append_test_options(options, remaining) diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 1fa9e242b..2eecd202d 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -17,6 +17,10 @@ def call(*args) call(["-n3"]) end + it "cleanups file paths" do + expect(call(["./test"])).to eq(defaults) + end + it "parses execute" do expect(call(["--exec", "echo"])).to eq(execute: "echo") end @@ -106,10 +110,10 @@ def call(*args) context "when the -- option separator is used" do it "interprets arguments as files/directories" do expect(call(%w(-- test))).to eq( files: %w(test)) + expect(call(%w(-- ./test))).to eq( files: %w(test)) expect(call(%w(-- test test2))).to eq( files: %w(test test2)) expect(call(%w(-- --foo test))).to eq( files: %w(--foo test)) expect(call(%w(-- test --foo test2))).to eq( files: %w(test --foo test2)) - end it "corectly handles arguments with spaces" do From 25f99222d5aed8bfb8de18964cb78c28dc8318d5 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 31 Jan 2020 17:34:59 +0100 Subject: [PATCH 033/177] v2.31.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 611bd0eca..b3f81aaed 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.30.1) + parallel_tests (2.31.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 946337167..858222bc0 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.30.1' + VERSION = Version = '2.31.0' end From 0ee1c91834e80fc47314963e48c7648deda2f335 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 3 Feb 2020 08:46:40 +1100 Subject: [PATCH 034/177] Add 'parallel_split_test' to Tips in Readme --- Readme.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 44ed4db5f..fbe6e88cd 100644 --- a/Readme.md +++ b/Readme.md @@ -256,7 +256,8 @@ TIPS - Instantly see failures (instead of just a red F) with [rspec-instafail](https://github.com/grosser/rspec-instafail) - Use [rspec-retry](https://github.com/NoRedInk/rspec-retry) (not rspec-rerun) to rerun failed tests. - [JUnit formatter configuration](https://github.com/grosser/parallel_tests/wiki#with-rspec_junit_formatter----by-jgarber) - + - Use [parallel_split_test](https://github.com/grosser/parallel_split_test) to run multiple scenarios in a single spec file, concurrently. (`parallel_tests` [works at the file-level and intends to stay that way](https://github.com/grosser/parallel_tests/issues/747#issuecomment-580216980)) + ### Cucumber - Add a `parallel: foo` profile to your `config/cucumber.yml` and it will be used to run parallel tests From 8e6867fb07c9f5acc17018d22600bed9c4ee07d2 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 15 Feb 2020 10:59:46 -0800 Subject: [PATCH 035/177] calculate unknwon runtime lazily ... also avoid .any? which checks each element --- lib/parallel_tests/test/runner.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index dcba51288..d697027a4 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -188,11 +188,7 @@ def sort_by_runtime(tests, runtimes, options={}) puts "Runtime found for #{tests.count(&:last)} of #{tests.size} tests" end - # fill gaps with unknown-runtime if given, average otherwise - known, unknown = tests.partition(&:last) - average = (known.any? ? known.map!(&:last).inject(:+) / known.size : 1) - unknown_runtime = options[:unknown_runtime] || average - unknown.each { |set| set[1] = unknown_runtime } + set_unknown_runtime tests, options end def runtimes(tests, options) @@ -240,6 +236,16 @@ def files_in_folder(folder, options={}) private + # fill gaps with unknown-runtime if given, average otherwise + # NOTE: an optimization could be doing runtime by average runtime per file size, but would need file checks + def set_unknown_runtime(tests, options) + known, unknown = tests.partition(&:last) + return if unknown.empty? + unknown_runtime = options[:unknown_runtime] || + (known.empty? ? 1 : known.map!(&:last).inject(:+) / known.size) # average + unknown.each { |set| set[1] = unknown_runtime } + end + def report_process_command?(options) options[:verbose] || options[:verbose_process_command] end From 0d1c90fd825d5aceef5ec3487befce8af9572081 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 24 Feb 2020 08:10:23 -0800 Subject: [PATCH 036/177] Add github action for windows testing --- .github/workflows/main.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..f6eb8695c --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,11 @@ +name: CI + +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Run a one-line script + run: bundle exec rake From 5df5b94d8363354c8fad9c9f12926d1d1346f729 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 24 Feb 2020 08:13:38 -0800 Subject: [PATCH 037/177] try windows build --- .github/workflows/main.yml | 11 ----------- .github/workflows/windows.yml | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 11 deletions(-) delete mode 100644 .github/workflows/main.yml create mode 100644 .github/workflows/windows.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index f6eb8695c..000000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: CI - -on: [push] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Run a one-line script - run: bundle exec rake diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml new file mode 100644 index 000000000..646fd185f --- /dev/null +++ b/.github/workflows/windows.yml @@ -0,0 +1,32 @@ +name: windows + +on: [push, pull_request] + +jobs: + build: + runs-on: windows-latest + strategy: + fail-fast: false + matrix: + ruby: [2.7, 2.6, 2.5, 2.4, 2.3, 2.2] + steps: + - uses: actions/checkout@master + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ matrix.ruby }} + - name: Update MSYS2 + uses: MSP-Greg/msys2-action@master + with: + base: update + mingw: sqlite3 + - name: Install dependencies + run: | + ruby -e "Dir['{,spec/**/}Gemfile.lock'].each { |f| File.write(f, File.read(f).split('BUNDLED WITH').first)}" + bundle install + - name: Change TMPDIR to something non symlinked + run: | + echo "::set-env name=TMPDIR::$HOME/tmp" + mkdir $HOME/tmp + - name: Run test + run: bundle exec rake From 68f91f58d4475315952ce50d8abe1ea9054afa9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 24 Feb 2020 21:03:03 +0100 Subject: [PATCH 038/177] Test against newest rubies on Windows (#751) * Bring lock files up to date * Use latest bundler * bundle update rake To fix ``` d:/rubyinstaller-2.7.0-1-x64/lib/ruby/gems/2.7.0/gems/rake-12.0.0/lib/rake/application.rb:378: warning: deprecated Object#=~ is called on Proc; it always returns nil ``` * bundle update json To fix ``` d:/rubyinstaller-2.7.0-1-x64/lib/ruby/gems/2.7.0/gems/json-2.0.2/lib/json/common.rb:156: warning: Using the last argument as keyword parameters is deprecated ``` * Fix test resiliency * Workaround resolution issues on newest rubies * Adapt test exceptions to higher rubies Since on Windows, the result seems consistent from ruby 2.4. * Increase timeout for rails specs Since they still seem to hang sometimes. * Switch badge to Github Actions * Revert "Use latest bundler" This reverts commit 1aee2d2448bf56a2d1ad971368c15cabcbdef47d. --- Gemfile.lock | 6 +++--- Readme.md | 2 +- spec/fixtures/rails51/Gemfile | 2 +- spec/fixtures/rails51/Gemfile.lock | 6 ++++-- spec/fixtures/rails52/Gemfile | 2 +- spec/fixtures/rails52/Gemfile.lock | 6 ++++-- spec/integration_spec.rb | 6 ++++-- spec/parallel_tests/test/runner_spec.rb | 2 +- spec/rails_spec.rb | 3 ++- 9 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index b3f81aaed..706f55d2c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -30,14 +30,14 @@ GEM diff-lcs (1.3) gherkin (5.1.0) gherkin-ruby (0.3.2) - json (2.0.2) - json (2.0.2-java) + json (2.3.0) + json (2.3.0-java) minitest (5.5.1) multi_json (1.13.1) multi_test (0.1.2) parallel (1.19.1) power_assert (0.4.1) - rake (12.0.0) + rake (13.0.1) rspec (3.5.0) rspec-core (~> 3.5.0) rspec-expectations (~> 3.5.0) diff --git a/Readme.md b/Readme.md index fbe6e88cd..182d8ab2e 100644 --- a/Readme.md +++ b/Readme.md @@ -2,7 +2,7 @@ [![Gem Version](https://badge.fury.io/rb/parallel_tests.svg)](https://rubygems.org/gems/parallel_tests) [![Build Status](https://travis-ci.org/grosser/parallel_tests.svg)](https://travis-ci.org/grosser/parallel_tests/builds) -[![Build status](https://ci.appveyor.com/api/projects/status/708b1up4pqc34x3y?svg=true)](https://ci.appveyor.com/project/grosser/parallel-tests) +[![Build status](https://github.com/grosser/parallel_tests/workflows/windows/badge.svg)](https://github.com/grosser/parallel_tests/actions?query=workflow%3Awindows) Speedup Test::Unit + RSpec + Cucumber + Spinach by running parallel on multiple CPU cores.
ParallelTests splits tests into even groups (by number of lines or runtime) and runs each group in a single process with its own database. diff --git a/spec/fixtures/rails51/Gemfile b/spec/fixtures/rails51/Gemfile index 608606810..21ae41534 100644 --- a/spec/fixtures/rails51/Gemfile +++ b/spec/fixtures/rails51/Gemfile @@ -2,5 +2,5 @@ source 'https://rubygems.org' gem 'rails', '5.1.6' gem 'sqlite3' -gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] +gem 'tzinfo-data' gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails51/Gemfile.lock b/spec/fixtures/rails51/Gemfile.lock index fd386b0bf..32f77a6d1 100644 --- a/spec/fixtures/rails51/Gemfile.lock +++ b/spec/fixtures/rails51/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.27.1) + parallel_tests (2.31.0) parallel GEM @@ -65,7 +65,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) - parallel (1.13.0) + parallel (1.19.1) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) @@ -105,6 +105,8 @@ GEM thread_safe (0.3.6) tzinfo (1.2.5) thread_safe (~> 0.1) + tzinfo-data (1.2019.3) + tzinfo (>= 1.0.0) websocket-driver (0.6.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) diff --git a/spec/fixtures/rails52/Gemfile b/spec/fixtures/rails52/Gemfile index e0dda044e..1caed7b40 100644 --- a/spec/fixtures/rails52/Gemfile +++ b/spec/fixtures/rails52/Gemfile @@ -2,5 +2,5 @@ source 'https://rubygems.org' gem 'rails', '5.2.1' gem 'sqlite3' -gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby] +gem 'tzinfo-data' gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails52/Gemfile.lock b/spec/fixtures/rails52/Gemfile.lock index c1035324d..d0f215351 100644 --- a/spec/fixtures/rails52/Gemfile.lock +++ b/spec/fixtures/rails52/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.27.1) + parallel_tests (2.31.0) parallel GEM @@ -72,7 +72,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) - parallel (1.13.0) + parallel (1.19.1) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) @@ -113,6 +113,8 @@ GEM thread_safe (0.3.6) tzinfo (1.2.5) thread_safe (~> 0.1) + tzinfo-data (1.2019.3) + tzinfo (>= 1.0.0) websocket-driver (0.7.0) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.3) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 71404cdab..72be62442 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -320,7 +320,9 @@ def test_unicode write "test/b_test.rb", "sleep 1; puts 'OutputB'" write "test/c_test.rb", "sleep 1.5; puts 'OutputC'" write "test/d_test.rb", "sleep 2; puts 'OutputD'" - expect(run_tests("test", :processes => 4)).to match(/OutputB\s+OutputC\s+OutputD\s+OutputA/) + actual = run_tests("test", :processes => 4).scan(/Output[ABCD]/) + actual_sorted = [*actual[0..2].sort, actual[3]] + expect(actual_sorted).to match(["OutputB", "OutputC", "OutputD", "OutputA"]) end it "can run only a single group" do @@ -424,7 +426,7 @@ def test_unicode write "features/fail2.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" results = run_tests "features", :processes => 3, :type => "cucumber", :fail => true - failing_scenarios = if Gem.win_platform? && RUBY_VERSION.start_with?("2.4") + failing_scenarios = if Gem.win_platform? && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4") ["cucumber features/fail1.feature:2 # Scenario: xxx", "cucumber features/fail2.feature:2 # Scenario: xxx"] else ["cucumber features/fail2.feature:2 # Scenario: xxx", "cucumber features/fail1.feature:2 # Scenario: xxx"] diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 502fe07fe..26f6d72b4 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -41,7 +41,7 @@ def call(*args) end it "uses given when passed found" do - result = Gem.win_platform? && RUBY_VERSION.start_with?("2.4") ? [["a", "b"], ["c"]] : [["a", "c"], ["b"]] + result = Gem.win_platform? && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4") ? [["a", "b"], ["c"]] : [["a", "c"], ["b"]] expect(call(["a", "b", "c"], 2, group_by: :found)).to eq(result) end diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 22fac5095..6ead5b627 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' describe 'rails' do - let(:test_timeout) { 600 } # this can take very long on fresh bundle ... + let(:test_timeout) { 800 } # this can take very long on fresh bundle ... def sh(command, options={}) result = '' @@ -26,6 +26,7 @@ def sh(command, options={}) ENV.delete("RACK_ENV") sh "bundle config --local path vendor/bundle" + sh "bundle config --local force_ruby_platform true" sh "bundle install" sh "rm -rf db/*.sqlite3" sh "bundle exec rake db:setup parallel:create --trace 2>&1" From e0d635fefb15d3bd0471d6a0adbea493086f769a Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 24 Feb 2020 12:21:26 -0800 Subject: [PATCH 039/177] remove appveyor --- appveyor.yml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 appveyor.yml diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 6ee592f08..000000000 --- a/appveyor.yml +++ /dev/null @@ -1,21 +0,0 @@ -version: '1.0.{build}' - -environment: - matrix: - - RUBY_VERSION: 22-x64 - - RUBY_VERSION: 23-x64 - - RUBY_VERSION: 24-x64 - -install: - - set PATH=C:\Ruby%RUBY_VERSION%\bin;%PATH% - - bundle install - -build: off - -before_test: - - ruby -v - - gem -v - - bundle -v - -test_script: - - bundle exec rake From ce5e995326e027a8873b4f6202da4f96517df9a4 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 15 Mar 2020 12:52:04 -0700 Subject: [PATCH 040/177] remove spec, it causes trouble and is lon dead (#754) --- lib/parallel_tests/rspec/runner.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index 1a3d90b91..f18051312 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -14,17 +14,14 @@ def run_tests(test_files, process_number, num_processes, options) end def determine_executable - cmd = case + case when File.exist?("bin/rspec") ParallelTests.with_ruby_binary("bin/rspec") when ParallelTests.bundler_enabled? - cmd = (run("bundle info rspec-core") =~ %r{Could not find gem.*} ? "spec" : "rspec") - "bundle exec #{cmd}" + "bundle exec rspec" else - %w[spec rspec].detect{|cmd| system "#{cmd} --version > #{DEV_NULL} 2>&1" } + "rspec" end - - cmd or raise("Can't find executables rspec or spec") end def runtime_log From 67c8dab0a0de0ab8ebb7a7795f48cbc143e3bd2c Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 15 Mar 2020 12:52:19 -0700 Subject: [PATCH 041/177] v2.32.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 706f55d2c..113035186 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.31.0) + parallel_tests (2.32.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 858222bc0..0fbcc1b01 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.31.0' + VERSION = Version = '2.32.0' end From c40b34babb0f4433e0219bc00627764b916f07db Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 10 May 2020 14:34:32 -0700 Subject: [PATCH 042/177] remove name override logic that never worked (#758) --- lib/parallel_tests/cli.rb | 3 +-- lib/parallel_tests/rspec/runner.rb | 2 -- lib/parallel_tests/test/runner.rb | 6 ------ 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index fcd99df1e..66376c7d4 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -316,9 +316,8 @@ def detailed_duration(seconds) end def final_fail_message - fail_message = "#{@runner.name}s Failed" + fail_message = "Tests Failed" fail_message = "\e[31m#{fail_message}\e[0m" if use_colors? - fail_message end diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index f18051312..e84c48809 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -4,8 +4,6 @@ module ParallelTests module RSpec class Runner < ParallelTests::Test::Runner DEV_NULL = (WINDOWS ? "NUL" : "/dev/null") - NAME = 'RSpec' - class << self def run_tests(test_files, process_number, num_processes, options) exe = executable # expensive, so we cache diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index d697027a4..55e48fafb 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -3,15 +3,9 @@ module ParallelTests module Test class Runner - NAME = 'Test' - class << self # --- usually overwritten by other runners - def name - NAME - end - def runtime_log 'tmp/parallel_runtime_test.log' end From 1c8761ab8abb63a1af70d0ab9b720dedef016a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 4 Jun 2020 22:01:04 +0200 Subject: [PATCH 043/177] Drop ruby 2.2 support (#759) * Lock all files to proper parallel_tests version * Drop ruby 2.2 support It's EoL and cucumber 4 does not support it. * Maybe this is no longer needed --- .github/workflows/windows.yml | 7 +------ .travis.yml | 1 - parallel_tests.gemspec | 2 +- spec/fixtures/rails51/Gemfile.lock | 2 +- spec/fixtures/rails52/Gemfile.lock | 2 +- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 646fd185f..cfe8a7bac 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -8,18 +8,13 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.7, 2.6, 2.5, 2.4, 2.3, 2.2] + ruby: [2.7, 2.6, 2.5, 2.4, 2.3] steps: - uses: actions/checkout@master - name: Set up Ruby uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - - name: Update MSYS2 - uses: MSP-Greg/msys2-action@master - with: - base: update - mingw: sqlite3 - name: Install dependencies run: | ruby -e "Dir['{,spec/**/}Gemfile.lock'].each { |f| File.write(f, File.read(f).split('BUNDLED WITH').first)}" diff --git a/.travis.yml b/.travis.yml index be05baa76..17c48a9ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ env: - RUBYOPT=-W0 rvm: - - 2.2 - 2.3 - 2.4 - 2.5 diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 484d4472b..0feaafa4f 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -16,5 +16,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.2.0' + s.required_ruby_version = '>= 2.3.0' end diff --git a/spec/fixtures/rails51/Gemfile.lock b/spec/fixtures/rails51/Gemfile.lock index 32f77a6d1..953a112c2 100644 --- a/spec/fixtures/rails51/Gemfile.lock +++ b/spec/fixtures/rails51/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.31.0) + parallel_tests (2.32.0) parallel GEM diff --git a/spec/fixtures/rails52/Gemfile.lock b/spec/fixtures/rails52/Gemfile.lock index d0f215351..d292523c4 100644 --- a/spec/fixtures/rails52/Gemfile.lock +++ b/spec/fixtures/rails52/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.31.0) + parallel_tests (2.32.0) parallel GEM From c68dec64bcd27ec6356bce9e5944607cc21b1b12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 4 Jun 2020 23:52:09 +0200 Subject: [PATCH 044/177] Drop ruby 2.3 support (#760) --- .github/workflows/windows.yml | 2 +- .travis.yml | 1 - parallel_tests.gemspec | 2 +- spec/integration_spec.rb | 2 +- spec/parallel_tests/test/runner_spec.rb | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index cfe8a7bac..b3c39e743 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -8,7 +8,7 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.7, 2.6, 2.5, 2.4, 2.3] + ruby: [2.7, 2.6, 2.5, 2.4] steps: - uses: actions/checkout@master - name: Set up Ruby diff --git a/.travis.yml b/.travis.yml index 17c48a9ed..e6dd91548 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ env: - RUBYOPT=-W0 rvm: - - 2.3 - 2.4 - 2.5 - 2.6 diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 0feaafa4f..8bbbd9843 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -16,5 +16,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.3.0' + s.required_ruby_version = '>= 2.4.0' end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 72be62442..23bc2a8a8 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -426,7 +426,7 @@ def test_unicode write "features/fail2.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" results = run_tests "features", :processes => 3, :type => "cucumber", :fail => true - failing_scenarios = if Gem.win_platform? && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4") + failing_scenarios = if Gem.win_platform? ["cucumber features/fail1.feature:2 # Scenario: xxx", "cucumber features/fail2.feature:2 # Scenario: xxx"] else ["cucumber features/fail2.feature:2 # Scenario: xxx", "cucumber features/fail1.feature:2 # Scenario: xxx"] diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 26f6d72b4..90a6fcf68 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -41,7 +41,7 @@ def call(*args) end it "uses given when passed found" do - result = Gem.win_platform? && Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4") ? [["a", "b"], ["c"]] : [["a", "c"], ["b"]] + result = Gem.win_platform? ? [["a", "b"], ["c"]] : [["a", "c"], ["b"]] expect(call(["a", "b", "c"], 2, group_by: :found)).to eq(result) end From db7d04631e7e506dd8540f7eca5cc8aff75bfb57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 10 Jun 2020 16:34:37 +0200 Subject: [PATCH 045/177] Fix a bundler deprecation when running specs (#761) --- Gemfile.lock | 2 +- spec/fixtures/rails51/Gemfile.lock | 2 +- spec/fixtures/rails52/Gemfile.lock | 2 +- spec/rails_spec.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 113035186..dfba9a65c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -74,4 +74,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 1.17.3 + 2.1.4 diff --git a/spec/fixtures/rails51/Gemfile.lock b/spec/fixtures/rails51/Gemfile.lock index 953a112c2..8733a076b 100644 --- a/spec/fixtures/rails51/Gemfile.lock +++ b/spec/fixtures/rails51/Gemfile.lock @@ -121,4 +121,4 @@ DEPENDENCIES tzinfo-data BUNDLED WITH - 1.16.6 + 2.1.4 diff --git a/spec/fixtures/rails52/Gemfile.lock b/spec/fixtures/rails52/Gemfile.lock index d292523c4..1044f004f 100644 --- a/spec/fixtures/rails52/Gemfile.lock +++ b/spec/fixtures/rails52/Gemfile.lock @@ -129,4 +129,4 @@ DEPENDENCIES tzinfo-data BUNDLED WITH - 1.16.6 + 2.1.4 diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 6ead5b627..dec26360e 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -20,7 +20,7 @@ def sh(command, options={}) end Dir.chdir("spec/fixtures/#{rails}") do - Bundler.with_clean_env do + Bundler.with_unbundled_env do # unset travis things ENV.delete("RAILS_ENV") ENV.delete("RACK_ENV") From 3fdb33fc516c6a520274d12feae57b5888770979 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 10 Jun 2020 16:42:48 +0200 Subject: [PATCH 046/177] Completly move to Github Actions (#763) * Run tests on ruby 2.7 * `ruby/setup-ruby` comes with the right bundler * Add head versions to github actions file * Add RUBYOPT to github actions config * Only run the master branch on push Just like in TravisCI. * Remove TravisCI in favor of Github Actions * Github Actions should be fast enough --- .github/workflows/{windows.yml => test.yml} | 23 ++++++++++++++------- .travis.yml | 23 --------------------- spec/integration_spec.rb | 4 ++-- 3 files changed, 18 insertions(+), 32 deletions(-) rename .github/workflows/{windows.yml => test.yml} (51%) delete mode 100644 .travis.yml diff --git a/.github/workflows/windows.yml b/.github/workflows/test.yml similarity index 51% rename from .github/workflows/windows.yml rename to .github/workflows/test.yml index b3c39e743..6ee8bd06e 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/test.yml @@ -1,23 +1,31 @@ -name: windows +name: test -on: [push, pull_request] +on: + push: + branches: + - master + + pull_request: jobs: build: - runs-on: windows-latest + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - ruby: [2.7, 2.6, 2.5, 2.4] + ruby: [2.7, 2.6, 2.5, 2.4, head, jruby-head] + os: [ubuntu-latest, windows-latest] + env: + RUBYOPT: -W0 steps: - uses: actions/checkout@master - - name: Set up Ruby - uses: ruby/setup-ruby@v1 + - name: Setup OS dependencies + uses: MSP-Greg/setup-ruby-pkgs@v1 with: ruby-version: ${{ matrix.ruby }} + apt-get: libsqlite3-dev - name: Install dependencies run: | - ruby -e "Dir['{,spec/**/}Gemfile.lock'].each { |f| File.write(f, File.read(f).split('BUNDLED WITH').first)}" bundle install - name: Change TMPDIR to something non symlinked run: | @@ -25,3 +33,4 @@ jobs: mkdir $HOME/tmp - name: Run test run: bundle exec rake + continue-on-error: ${{ endsWith(matrix.ruby, 'head') }} diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e6dd91548..000000000 --- a/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -env: - - RUBYOPT=-W0 -rvm: - - 2.4 - - 2.5 - - 2.6 - - ruby-head - - jruby-head -branches: - only: [master] -sudo: false -cache: - bundler: true - directories: - - spec/fixtures/rails51/vendor/bundle - - spec/fixtures/rails52/vendor/bundle -matrix: - allow_failures: - - rvm: ruby-head - - rvm: jruby-head - fast_finish: true -bundler_args: "--jobs 4" -before_install: ruby -e "Dir['{,spec/**/}Gemfile.lock'].each { |f| File.write(f, File.read(f).split('BUNDLED WITH').first)}" diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 23bc2a8a8..7b157bcd1 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -540,7 +540,7 @@ class A < Spinach::FeatureSteps describe "graceful shutdown" do # Process.kill on Windows doesn't work as expected. It kills all process group instead of just one process. it "passes on int signal to child processes", unless: Gem.win_platform? do - timeout = (ENV["TRAVIS"] ? 4 : 2) # travis is slower so it needs some extra time + timeout = 2 write "spec/test_spec.rb", "sleep #{timeout}; describe { specify { 'Should not get here' }; specify { p 'Should not get here either'} }" pid = nil Thread.new { sleep timeout - 0.5; Process.kill("INT", pid) } @@ -553,7 +553,7 @@ class A < Spinach::FeatureSteps # Process.kill on Windows doesn't work as expected. It kills all process group instead of just one process. it "exits immediately if another int signal is received", unless: Gem.win_platform? do - timeout = (ENV["TRAVIS"] ? 4 : 2) # travis is slower so it needs some extra time + timeout = 2 write "spec/test_spec.rb", "describe { specify { sleep #{timeout}; p 'Should not get here'} }" pid = nil Thread.new { sleep timeout - 0.5; Process.kill("INT", pid) } From d9af8f6bafe6d591a0d6fc52359df31f44ed2a3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 10 Jun 2020 18:50:46 +0200 Subject: [PATCH 047/177] Cucumber 4 support (#762) --- Gemfile | 3 +- Gemfile.lock | 107 +++++++++++------- .../cucumber/features_with_steps.rb | 31 +++++ .../cucumber/scenario_line_logger.rb | 32 +++--- lib/parallel_tests/cucumber/scenarios.rb | 40 +++---- lib/parallel_tests/gherkin/listener.rb | 2 - lib/parallel_tests/gherkin/runtime_logger.rb | 2 +- lib/parallel_tests/grouper.rb | 22 +--- 8 files changed, 138 insertions(+), 101 deletions(-) create mode 100644 lib/parallel_tests/cucumber/features_with_steps.rb diff --git a/Gemfile b/Gemfile index 2091b9f62..c0f80d6f0 100644 --- a/Gemfile +++ b/Gemfile @@ -5,6 +5,7 @@ gem 'bump' gem 'test-unit' gem 'minitest', '~> 5.5.0' gem 'rspec', '~> 3.3' -gem 'cucumber', "~> 3.0" +gem 'cucumber', "~> 4.0" +gem 'cuke_modeler', '~> 3.0' gem 'spinach' gem 'rake' diff --git a/Gemfile.lock b/Gemfile.lock index dfba9a65c..cd6e0fa44 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,65 +7,94 @@ PATH GEM remote: https://rubygems.org/ specs: - backports (3.11.4) - builder (3.2.3) - bump (0.5.3) + activesupport (5.2.4.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + builder (3.2.4) + bump (0.9.0) colorize (0.8.1) - cucumber (3.1.2) - builder (>= 2.1.2) - cucumber-core (~> 3.2.0) - cucumber-expressions (~> 6.0.1) - cucumber-wire (~> 0.0.1) - diff-lcs (~> 1.3) - gherkin (~> 5.1.0) - multi_json (>= 1.7.5, < 2.0) - multi_test (>= 0.1.2) - cucumber-core (3.2.1) - backports (>= 3.8.0) - cucumber-tag_expressions (~> 1.1.0) - gherkin (~> 5.0) - cucumber-expressions (6.0.1) - cucumber-tag_expressions (1.1.1) - cucumber-wire (0.0.1) + concurrent-ruby (1.1.6) + cucumber (4.0.0) + builder (~> 3.2, >= 3.2.3) + cucumber-core (~> 7.0, >= 7.0.0) + cucumber-cucumber-expressions (~> 10.1, >= 10.1.0) + cucumber-gherkin (~> 13.0, >= 13.0.0) + cucumber-html-formatter (~> 6.0, >= 6.0.1) + cucumber-messages (~> 12.1, >= 12.1.1) + cucumber-wire (~> 3.0, >= 3.0.0) + diff-lcs (~> 1.3, >= 1.3) + multi_test (~> 0.1, >= 0.1.2) + sys-uname (~> 1.0, >= 1.0.2) + cucumber-core (7.0.0) + cucumber-gherkin (~> 13.0, >= 13.0.0) + cucumber-messages (~> 12.1, >= 12.1.1) + cucumber-tag-expressions (~> 2.0, >= 2.0.4) + cucumber-cucumber-expressions (10.2.0) + cucumber-gherkin (13.0.0) + cucumber-messages (~> 12.0, >= 12.0.0) + cucumber-html-formatter (6.0.2) + cucumber-messages (~> 12.1, >= 12.1.1) + cucumber-messages (12.1.1) + protobuf-cucumber (~> 3.10, >= 3.10.8) + cucumber-tag-expressions (2.0.4) + cucumber-wire (3.0.0) + cucumber-core (~> 7.0, >= 7.0.0) + cucumber-cucumber-expressions (~> 10.1, >= 10.1.0) + cucumber-messages (~> 12.1, >= 12.1.1) + cuke_modeler (3.0.0) + cucumber-gherkin (< 14.0) diff-lcs (1.3) - gherkin (5.1.0) + ffi (1.13.1) gherkin-ruby (0.3.2) + i18n (1.8.3) + concurrent-ruby (~> 1.0) json (2.3.0) - json (2.3.0-java) + middleware (0.1.0) minitest (5.5.1) - multi_json (1.13.1) multi_test (0.1.2) parallel (1.19.1) - power_assert (0.4.1) + power_assert (1.2.0) + protobuf-cucumber (3.10.8) + activesupport (>= 3.2) + middleware + thor + thread_safe rake (13.0.1) - rspec (3.5.0) - rspec-core (~> 3.5.0) - rspec-expectations (~> 3.5.0) - rspec-mocks (~> 3.5.0) - rspec-core (3.5.4) - rspec-support (~> 3.5.0) - rspec-expectations (3.5.0) + rspec (3.9.0) + rspec-core (~> 3.9.0) + rspec-expectations (~> 3.9.0) + rspec-mocks (~> 3.9.0) + rspec-core (3.9.2) + rspec-support (~> 3.9.3) + rspec-expectations (3.9.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-mocks (3.5.0) + rspec-support (~> 3.9.0) + rspec-mocks (3.9.1) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.5.0) - rspec-support (3.5.0) - spinach (0.9.0) + rspec-support (~> 3.9.0) + rspec-support (3.9.3) + spinach (0.11.0) colorize gherkin-ruby (>= 0.3.2) json - test-unit (3.2.3) + sys-uname (1.2.1) + ffi (>= 1.0.0) + test-unit (3.3.6) power_assert + thor (1.0.1) + thread_safe (0.3.6) + tzinfo (1.2.7) + thread_safe (~> 0.1) PLATFORMS - java ruby - x64-mingw32 DEPENDENCIES bump - cucumber (~> 3.0) + cucumber (~> 4.0) + cuke_modeler (~> 3.0) minitest (~> 5.5.0) parallel_tests! rake diff --git a/lib/parallel_tests/cucumber/features_with_steps.rb b/lib/parallel_tests/cucumber/features_with_steps.rb new file mode 100644 index 000000000..6ef359df3 --- /dev/null +++ b/lib/parallel_tests/cucumber/features_with_steps.rb @@ -0,0 +1,31 @@ +begin + gem "cuke_modeler", "~> 3.0" + require 'cuke_modeler' +rescue LoadError + raise 'Grouping by number of cucumber steps requires the `cuke_modeler` modeler gem with requirement `~> 3.0`. Add `gem "cuke_modeler", "~> 3.0"` to your `Gemfile`, run `bundle install` and try again.' +end + +module ParallelTests + module Cucumber + class FeaturesWithSteps + class << self + def all(tests, options) + ignore_tag_pattern = options[:ignore_tag_pattern].nil? ? nil : Regexp.compile(options[:ignore_tag_pattern]) + # format of hash will be FILENAME => NUM_STEPS + steps_per_file = tests.each_with_object({}) do |file,steps| + feature = ::CukeModeler::FeatureFile.new(file).feature + + # skip feature if it matches tag regex + next if feature.tags.grep(ignore_tag_pattern).any? + + # count the number of steps in the file + # will only include a feature if the regex does not match + all_steps = feature.scenarios.map{|a| a.steps.count if a.tags.grep(ignore_tag_pattern).empty? }.compact + steps[file] = all_steps.inject(0,:+) + end + steps_per_file.sort_by { |_, value| -value } + end + end + end + end +end diff --git a/lib/parallel_tests/cucumber/scenario_line_logger.rb b/lib/parallel_tests/cucumber/scenario_line_logger.rb index b3e0a59ac..6ac24ce80 100644 --- a/lib/parallel_tests/cucumber/scenario_line_logger.rb +++ b/lib/parallel_tests/cucumber/scenario_line_logger.rb @@ -1,37 +1,33 @@ -require 'cucumber/tag_expressions/parser' -require 'cucumber/core/gherkin/tag_expression' - module ParallelTests module Cucumber module Formatters class ScenarioLineLogger attr_reader :scenarios - def initialize(tag_expression = ::Cucumber::Core::Gherkin::TagExpression.new([])) + def initialize(tag_expression = nil) @scenarios = [] @tag_expression = tag_expression end def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) - scenario_tags = feature_element[:tags].map { |tag| tag[:name] } + scenario_tags = feature_element.tags.map { |tag| tag.name } scenario_tags = feature_tags + scenario_tags - if feature_element[:examples].nil? # :Scenario - test_line = feature_element[:location][:line] + if feature_element.is_a?(CukeModeler::Scenario) # :Scenario + test_line = feature_element.source_line # We don't accept the feature_element if the current tags are not valid - return unless @tag_expression.evaluate(scenario_tags) + return unless matches_tags?(scenario_tags) # or if it is not at the correct location return if line_numbers.any? && !line_numbers.include?(test_line) - @scenarios << [uri, feature_element[:location][:line]].join(":") + @scenarios << [uri, feature_element.source_line].join(":") else # :ScenarioOutline - feature_element[:examples].each do |example| - example_tags = example[:tags].map { |tag| tag[:name] } + feature_element.examples.each do |example| + example_tags = example.tags.map(&:name) example_tags = scenario_tags + example_tags - next unless @tag_expression.evaluate(example_tags) - rows = example[:tableBody].select { |body| body[:type] == :TableRow } - rows.each do |row| - test_line = row[:location][:line] + next unless matches_tags?(example_tags) + example.rows[1..-1].each do |row| + test_line = row.source_line next if line_numbers.any? && !line_numbers.include?(test_line) @scenarios << [uri, test_line].join(':') @@ -42,6 +38,12 @@ def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) def method_missing(*args) end + + private + + def matches_tags?(tags) + @tag_expression.nil? || @tag_expression.evaluate(tags) + end end end end diff --git a/lib/parallel_tests/cucumber/scenarios.rb b/lib/parallel_tests/cucumber/scenarios.rb index 1352a5f3b..b7778f0d2 100644 --- a/lib/parallel_tests/cucumber/scenarios.rb +++ b/lib/parallel_tests/cucumber/scenarios.rb @@ -1,12 +1,17 @@ require 'cucumber/tag_expressions/parser' -require 'cucumber/core/gherkin/tag_expression' require 'cucumber/runtime' require 'cucumber' require 'parallel_tests/cucumber/scenario_line_logger' require 'parallel_tests/gherkin/listener' -require 'gherkin/errors' require 'shellwords' +begin + gem "cuke_modeler", "~> 3.0" + require 'cuke_modeler' +rescue LoadError + raise 'Grouping by individual cucumber scenarios requires the `cuke_modeler` modeler gem with requirement `~> 3.0`. Add `gem "cuke_modeler", "~> 3.0"` to your `Gemfile`, run `bundle install` and try again.' +end + module ParallelTests module Cucumber class Scenarios @@ -40,32 +45,17 @@ def split_into_scenarios(files, tags='') path, *test_lines = path.split(/:(?=\d+)/) test_lines.map!(&:to_i) - # We encode the file and get the content of it - source = ::Cucumber::Runtime::NormalisedEncodingFile.read(path) # We create a Gherkin document, this will be used to decode the details of each scenario - document = ::Cucumber::Core::Gherkin::Document.new(path, source) - - # We create a parser for the gherkin document - parser = ::Gherkin::Parser.new() - scanner = ::Gherkin::TokenScanner.new(document.body) - - begin - # We make an attempt to parse the gherkin document, this could be failed if the document is not well formatted - result = parser.parse(scanner) - feature_tags = result[:feature][:tags].map { |tag| tag[:name] } - - # We loop on each children of the feature - result[:feature][:children].each do |feature_element| - # If the type of the child is not a scenario or scenario outline, we continue, we are only interested by the name of the scenario here - next unless /Scenario/.match(feature_element[:type]) + document = ::CukeModeler::FeatureFile.new(path) + feature = document.feature - # It's a scenario, we add it to the scenario_line_logger - scenario_line_logger.visit_feature_element(document.uri, feature_element, feature_tags, line_numbers: test_lines) - end + # We make an attempt to parse the gherkin document, this could be failed if the document is not well formatted + feature_tags = feature.tags.map(&:name) - rescue StandardError => e - # Exception if the document is no well formated or error in the tags - raise ::Cucumber::Core::Gherkin::ParseError.new("#{document.uri}: #{e.message}") + # We loop on each children of the feature + feature.tests.each do |test| + # It's a scenario, we add it to the scenario_line_logger + scenario_line_logger.visit_feature_element(document.path, test, feature_tags, line_numbers: test_lines) end end diff --git a/lib/parallel_tests/gherkin/listener.rb b/lib/parallel_tests/gherkin/listener.rb index 57fdbfffe..f5a60aaa1 100644 --- a/lib/parallel_tests/gherkin/listener.rb +++ b/lib/parallel_tests/gherkin/listener.rb @@ -1,5 +1,3 @@ -require 'gherkin/parser' - module ParallelTests module Gherkin class Listener diff --git a/lib/parallel_tests/gherkin/runtime_logger.rb b/lib/parallel_tests/gherkin/runtime_logger.rb index 61dfe927e..b1b0d4ce2 100644 --- a/lib/parallel_tests/gherkin/runtime_logger.rb +++ b/lib/parallel_tests/gherkin/runtime_logger.rb @@ -14,7 +14,7 @@ def initialize(config) end config.on_event :test_case_finished do |event| - @example_times[event.test_case.feature.file] += ParallelTests.now.to_f - @start_at + @example_times[event.test_case.location.file] += ParallelTests.now.to_f - @start_at end config.on_event :test_run_finished do |_| diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index d5952d0ba..0db018a7e 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -2,7 +2,7 @@ module ParallelTests class Grouper class << self def by_steps(tests, num_groups, options) - features_with_steps = build_features_with_steps(tests, options) + features_with_steps = group_by_features_with_steps(tests, options) in_even_groups_by_size(features_with_steps, num_groups) end @@ -41,23 +41,9 @@ def add_to_group(group, item, size) group[:size] += size end - def build_features_with_steps(tests, options) - require 'gherkin/parser' - ignore_tag_pattern = options[:ignore_tag_pattern].nil? ? nil : Regexp.compile(options[:ignore_tag_pattern]) - parser = ::Gherkin::Parser.new - # format of hash will be FILENAME => NUM_STEPS - steps_per_file = tests.each_with_object({}) do |file,steps| - feature = parser.parse(File.read(file)).fetch(:feature) - - # skip feature if it matches tag regex - next if feature[:tags].grep(ignore_tag_pattern).any? - - # count the number of steps in the file - # will only include a feature if the regex does not match - all_steps = feature[:children].map{|a| a[:steps].count if a[:tags].grep(ignore_tag_pattern).empty? }.compact - steps[file] = all_steps.inject(0,:+) - end - steps_per_file.sort_by { |_, value| -value } + def group_by_features_with_steps(tests, options) + require 'parallel_tests/cucumber/features_with_steps' + ParallelTests::Cucumber::FeaturesWithSteps.all(tests, options) end def group_by_scenarios(tests, options={}) From ac527762dc97e9af363f2a69fcd324f8acf2cefb Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Wed, 10 Jun 2020 09:51:41 -0700 Subject: [PATCH 048/177] v3.0.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index cd6e0fa44..a0ef3d1ab 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (2.32.0) + parallel_tests (3.0.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 0fbcc1b01..36c0a102e 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '2.32.0' + VERSION = Version = '3.0.0' end From f997437de4532e76e02038469251d087bef6c903 Mon Sep 17 00:00:00 2001 From: Jared Beck Date: Wed, 10 Jun 2020 20:14:31 -0400 Subject: [PATCH 049/177] Introduce Changelog and PR template (#765) --- .github/PULL_REQUEST_TEMPLATE.md | 7 ++++++ CHANGELOG.md | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 .github/PULL_REQUEST_TEMPLATE.md create mode 100644 CHANGELOG.md diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..32fc21374 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,7 @@ +Thank you for your contribution! + +## Checklist +- [ ] Feature branch is up-to-date with `master` (if not - rebase it). +- [ ] Added tests. +- [ ] Added an entry to the [Changelog](../blob/master/CHANGELOG.md) if the new + code introduces user-observable changes. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..b1be18a37 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,39 @@ +# Changelog + +## Unreleased + +### Breaking Changes + +- None + +### Added + +- None + +### Fixed + +- None + +## 3.0.0 - 2020-06-10 + +### Breaking Changes + +- Cucumber 3 support removed (#762) + +### Added + +- Cucumber 4 support (#762) + +### Fixed + +- Fix a bundler deprecation when running specs (#761) +- remove name override logic that never worked (#758) + +### Dependencies + +- Drop ruby 2.3 support (#760) +- Drop ruby 2.2 support (#759) + +## Previous versions + +No docs yet. Contributions welcome! From 6bd12f20adceceedcdb5e95b60e036ce079650e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 13 Jun 2020 21:34:12 +0200 Subject: [PATCH 050/177] More accurate description of breaking changes (#766) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1be18a37..db05cc30e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ ### Breaking Changes -- Cucumber 3 support removed (#762) +- The `--group-by` flag with value `steps` and `features` now requires end users to add the `cuke_modeler` gem to their Gemfile (#762). ### Added From 78649d06363a4ecf9a60210eb8be9700878938bf Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 23 Jul 2020 23:00:34 -0700 Subject: [PATCH 051/177] fail fast rework (#770) add --fail-fast --- .github/PULL_REQUEST_TEMPLATE.md | 1 + CHANGELOG.md | 2 +- Readme.md | 11 +-- lib/parallel_tests/cli.rb | 4 +- spec/integration_spec.rb | 128 +++++++++++++++++++++---------- 5 files changed, 100 insertions(+), 46 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 32fc21374..a112c405a 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,3 +5,4 @@ Thank you for your contribution! - [ ] Added tests. - [ ] Added an entry to the [Changelog](../blob/master/CHANGELOG.md) if the new code introduces user-observable changes. +- [ ] Update Readme.md when cli options are changed diff --git a/CHANGELOG.md b/CHANGELOG.md index db05cc30e..a2a9eb8d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Added -- None +- `--fail-fast` stops all groups if one group fails. Can be used to stop all groups if one test failed by using `fail-fast` in the test-framework too (for example rspec via `--test-options '--fail-fast'` or in `.rspec_parallel`). ### Fixed diff --git a/Readme.md b/Readme.md index 182d8ab2e..3463335a4 100644 --- a/Readme.md +++ b/Readme.md @@ -192,7 +192,6 @@ Setup for non-rails Options are: - -n [PROCESSES] How many processes to use, default: available CPUs -p, --pattern [PATTERN] run tests matching this regex pattern --exclude-pattern [PATTERN] exclude tests matching this regex pattern @@ -222,12 +221,14 @@ Options are: --ignore-tags [PATTERN] When counting steps ignore scenarios with tags that match this pattern --nice execute test commands with low priority. --runtime-log [PATH] Location of previously recorded test runtimes - --allowed-missing Allowed percentage of missing runtimes (default = 50) + --allowed-missing [INT] Allowed percentage of missing runtimes (default = 50) --unknown-runtime [FLOAT] Use given number as unknown runtime (otherwise use average time) + --first-is-1 Use "1" as TEST_ENV_NUMBER to not reuse the default test environment + --fail-fast Stop all groups when one group fails (best used with --test-options '--fail-fast' if supported --verbose Print debug output - --verbose-process-command Print the command that will be executed by each process before it begins - --verbose-rerun-command After a process fails, print the command executed by that process - --quiet Print only test output + --verbose-process-command Displays only the command that will be executed by each process + --verbose-rerun-command When there are failures, displays the command executed by each process that failed + --quiet Print only tests output -v, --version Show Version -h, --help Show this. diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 66376c7d4..089cd8386 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -42,9 +42,10 @@ def execute_in_parallel(items, num_processes, options) Tempfile.open 'parallel_tests-lock' do |lock| ParallelTests.with_pid_file do simulate_output_for_ci options[:serialize_stdout] do - Parallel.map(items, :in_threads => num_processes) do |item| + Parallel.map(items, in_threads: num_processes) do |item| result = yield(item) reprint_output(result, lock.path) if options[:serialize_stdout] + ParallelTests.stop_all_processes if options[:fail_fast] && result[:exit_status] != 0 result end end @@ -220,6 +221,7 @@ def parse_options!(argv) opts.on("--allowed-missing [INT]", Integer, "Allowed percentage of missing runtimes (default = 50)") { |percent| options[:allowed_missing_percent] = percent } opts.on("--unknown-runtime [FLOAT]", Float, "Use given number as unknown runtime (otherwise use average time)") { |time| options[:unknown_runtime] = time } opts.on("--first-is-1", "Use \"1\" as TEST_ENV_NUMBER to not reuse the default test environment") { options[:first_is_1] = true } + opts.on("--fail-fast", "Stop all groups when one group fails (best used with --test-options '--fail-fast' if supported") { options[:fail_fast] = true } opts.on("--verbose", "Print debug output") { options[:verbose] = true } opts.on("--verbose-process-command", "Displays only the command that will be executed by each process") { options[:verbose_process_command] = true } opts.on("--verbose-rerun-command", "When there are failures, displays the command executed by each process that failed") { options[:verbose_rerun_command] = true } diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 7b157bcd1..bfb32323c 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -28,7 +28,7 @@ def bin_folder "#{File.expand_path(File.dirname(__FILE__))}/../bin" end - def executable(options={}) + def executable(options = {}) "ruby #{bin_folder}/parallel_#{options[:type] || 'test'}" end @@ -36,9 +36,9 @@ def ensure_folder(folder) FileUtils.mkpath(folder) unless File.exist?(folder) end - def run_tests(test_folder, options={}) + def run_tests(test_folder, options = {}) ensure_folder folder - processes = "-n #{options[:processes]||2}" unless options[:processes] == false + processes = "-n #{options[:processes] || 2}" unless options[:processes] == false command = "#{executable(options)} #{test_folder} #{processes} #{options[:add]}" result = '' Dir.chdir(folder) do @@ -67,7 +67,7 @@ def self.it_fails_without_any_files(type) write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){puts "TEST2"}}' # set processes to false so we verify empty groups are discarded by default - result = run_tests "spec", :type => 'rspec', :processes => 4 + result = run_tests "spec", type: 'rspec', processes: 4 # test ran and gave their puts expect(result).to include('TEST1') @@ -83,9 +83,59 @@ def self.it_fails_without_any_files(type) expect(result).to include '2 processes for 2 specs, ~ 1 specs per process' end + describe "--fail-fast" do + def run_tests(test_option: nil) + super( + "spec", + fail: true, + type: 'rspec', + processes: 2, + # group-by + order for stable execution ... doc and verbose to ease debugging + add: "--group-by found --verbose --fail-fast --test-options '--format doc --order defined #{test_option}'" + ) + end + + before do + write 'spec/xxx1_spec.rb', 'describe("T1"){it("E1"){puts "YE" + "S"; sleep 0.5; expect(1).to eq(2)}}' # group 1 executed + write 'spec/xxx2_spec.rb', 'describe("T2"){it("E2"){sleep 1; puts "OK"}}' # group 2 executed + write 'spec/xxx3_spec.rb', 'describe("T3"){it("E3"){puts "NO3"}}' # group 1 skipped + write 'spec/xxx4_spec.rb', 'describe("T4"){it("E4"){puts "NO4"}}' # group 2 skipped + write 'spec/xxx5_spec.rb', 'describe("T5"){it("E5"){puts "NO5"}}' # group 1 skipped + write 'spec/xxx6_spec.rb', 'describe("T6"){it("E6"){puts "NO6"}}' # group 2 skipped + end + + it "can fail fast on a single test" do + result = run_tests(test_option: "--fail-fast") + + expect(result).to include_exactly_times("YES", 1) + expect(result).to include_exactly_times("OK", 1) # is allowed to finish but no new test is started after + expect(result).to_not include("NO") + + expect(result).to include_exactly_times('1 example, 1 failure', 1) # rspec group 1 + expect(result).to include_exactly_times('1 example, 0 failure', 1) # rspec group 2 + expect(result).to include_exactly_times('2 examples, 1 failure', 1) # parallel_rspec summary + + expect(result).to include '2 processes for 6 specs, ~ 3 specs per process' + end + + it "can fail fast on a single group" do + result = run_tests + + expect(result).to include_exactly_times("YES", 1) + expect(result).to include_exactly_times("OK", 1) # is allowed to finish but no new test is started after + expect(result).to include_exactly_times("NO", 2) + + expect(result).to include_exactly_times('3 examples, 1 failure', 1) # rspec group 1 + expect(result).to include_exactly_times('1 example, 0 failure', 1) # rspec group 2 + expect(result).to include_exactly_times('4 examples, 1 failure', 1) # parallel_rspec summary + + expect(result).to include '2 processes for 6 specs, ~ 3 specs per process' + end + end + it "runs tests which outputs accented characters" do write "spec/xxx_spec.rb", "#encoding: utf-8\ndescribe('it'){it('should'){puts 'Byłem tu'}}" - result = run_tests "spec", :type => 'rspec' + result = run_tests "spec", type: 'rspec' # test ran and gave their puts expect(result).to include('Byłem tu') end @@ -99,17 +149,17 @@ def test_unicode end end EOF + # Need to tell Ruby to default to utf-8 to simulate environments where # this is set. (Otherwise, it defaults to nil and the undefined conversion # issue doesn't come up.) - result = run_tests('test', :fail => true, - :export => {'RUBYOPT' => 'Eutf-8:utf-8'}) + result = run_tests('test', fail: true, export: {'RUBYOPT' => 'Eutf-8:utf-8'}) expect(result).to include('¯\_(ツ)_/¯') end it "does not run any tests if there are none" do write 'spec/xxx_spec.rb', '1' - result = run_tests "spec", :type => 'rspec' + result = run_tests "spec", type: 'rspec' expect(result).to include('No examples found') expect(result).to include('Took') end @@ -117,7 +167,7 @@ def test_unicode it "shows command and rerun with --verbose" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec --verbose", :type => 'rspec', :fail => true + result = run_tests "spec --verbose", type: 'rspec', fail: true expect(result).to include printed_commands expect(result).to include printed_rerun expect(result).to include "bundle exec rspec spec/xxx_spec.rb" @@ -126,14 +176,14 @@ def test_unicode it "shows only rerun with --verbose-rerun-command" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec --verbose-rerun-command", :type => 'rspec', :fail => true + result = run_tests "spec --verbose-rerun-command", type: 'rspec', fail: true expect(result).to include printed_rerun expect(result).to_not include printed_commands end it "shows only process with --verbose-process-command" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec --verbose-process-command", :type => 'rspec', :fail => true + result = run_tests "spec --verbose-process-command", type: 'rspec', fail: true expect(result).to_not include printed_rerun expect(result).to include printed_commands end @@ -141,7 +191,7 @@ def test_unicode it "fails when tests fail" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec", :fail => true, :type => 'rspec' + result = run_tests "spec", fail: true, type: 'rspec' expect(result).to include_exactly_times('1 example, 1 failure', 1) expect(result).to include_exactly_times('1 example, 0 failure', 1) @@ -151,7 +201,7 @@ def test_unicode it "can serialize stdout" do write 'spec/xxx_spec.rb', '5.times{describe("it"){it("should"){sleep 0.01; puts "TEST1"}}}' write 'spec/xxx2_spec.rb', 'sleep 0.01; 5.times{describe("it"){it("should"){sleep 0.01; puts "TEST2"}}}' - result = run_tests "spec", :type => 'rspec', :add => "--serialize-stdout" + result = run_tests "spec", type: 'rspec', add: "--serialize-stdout" expect(result).not_to match(/TEST1.*TEST2.*TEST1/m) expect(result).not_to match(/TEST2.*TEST1.*TEST2/m) @@ -160,20 +210,20 @@ def test_unicode it "can show simulated output when serializing stdout" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 0.5; puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST2"}}' - result = run_tests "spec", :type => 'rspec', :add => "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01'} + result = run_tests "spec", type: 'rspec', add: "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01'} expect(result).to match(/\.{4}.*TEST1.*\.{4}.*TEST2/m) end it "can show simulated output preceded by command when serializing stdout with verbose option" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST1"}}' - result = run_tests "spec --verbose", :type => 'rspec', :add => "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02'} + result = run_tests "spec --verbose", type: 'rspec', add: "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02'} expect(result).to match(/\.{5}.*\nbundle exec rspec spec\/xxx_spec\.rb\nTEST1/m) end it "can serialize stdout and stderr" do write 'spec/xxx_spec.rb', '5.times{describe("it"){it("should"){sleep 0.01; $stderr.puts "errTEST1"; puts "TEST1"}}}' write 'spec/xxx2_spec.rb', 'sleep 0.01; 5.times{describe("it"){it("should"){sleep 0.01; $stderr.puts "errTEST2"; puts "TEST2"}}}' - result = run_tests "spec", :type => 'rspec', :add => "--serialize-stdout --combine-stderr" + result = run_tests "spec", type: 'rspec', add: "--serialize-stdout --combine-stderr" expect(result).not_to match(/TEST1.*TEST2.*TEST1/m) expect(result).not_to match(/TEST2.*TEST1.*TEST2/m) @@ -228,7 +278,7 @@ def test_unicode it "runs with --group-by found" do # it only tests that it does not blow up, as it did before fixing... write "spec/x1_spec.rb", "puts 'TEST111'" - run_tests "spec", :type => 'rspec', :add => '--group-by found' + run_tests "spec", type: 'rspec', add: '--group-by found' end it "runs in parallel" do @@ -269,7 +319,7 @@ def test_unicode write "spec/x1_spec.rb", "puts 'TEST111'" write "spec/x2_spec.rb", "puts 'TEST222'" write "spec/x3_spec.rb", "puts 'TEST333'" - result = run_tests "spec/x1_spec.rb spec/x3_spec.rb", :type => 'rspec' + result = run_tests "spec/x1_spec.rb spec/x3_spec.rb", type: 'rspec' expect(result).to include('TEST111') expect(result).to include('TEST333') expect(result).not_to include('TEST222') @@ -285,9 +335,9 @@ def test_unicode it "runs with PARALLEL_TEST_PROCESSORS processes" do skip if RUBY_PLATFORM == "java" # execution expired issue on JRuby processes = 5 - processes.times { |i| + processes.times do |i| write "spec/x#{i}_spec.rb", "puts %{ENV-\#{ENV['TEST_ENV_NUMBER']}-}" - } + end result = run_tests( "spec", export: {"PARALLEL_TEST_PROCESSORS" => processes.to_s}, processes: processes, type: 'rspec' ) @@ -298,7 +348,7 @@ def test_unicode write "spec/x_spec.rb", "puts 'TESTXXX'" write "spec/y_spec.rb", "puts 'TESTYYY'" write "spec/z_spec.rb", "puts 'TESTZZZ'" - result = run_tests "spec", :add => "-p '^spec/(x|z)'", :type => "rspec" + result = run_tests "spec", add: "-p '^spec/(x|z)'", type: "rspec" expect(result).to include('TESTXXX') expect(result).not_to include('TESTYYY') expect(result).to include('TESTZZZ') @@ -308,7 +358,7 @@ def test_unicode write "spec/x_spec.rb", "puts 'TESTXXX'" write "spec/acceptance/y_spec.rb", "puts 'TESTYYY'" write "spec/integration/z_spec.rb", "puts 'TESTZZZ'" - result = run_tests "spec", :add => "--exclude-pattern 'spec/(integration|acceptance)'", :type => "rspec" + result = run_tests "spec", add: "--exclude-pattern 'spec/(integration|acceptance)'", type: "rspec" expect(result).to include('TESTXXX') expect(result).not_to include('TESTYYY') expect(result).not_to include('TESTZZZ') @@ -320,7 +370,7 @@ def test_unicode write "test/b_test.rb", "sleep 1; puts 'OutputB'" write "test/c_test.rb", "sleep 1.5; puts 'OutputC'" write "test/d_test.rb", "sleep 2; puts 'OutputD'" - actual = run_tests("test", :processes => 4).scan(/Output[ABCD]/) + actual = run_tests("test", processes: 4).scan(/Output[ABCD]/) actual_sorted = [*actual[0..2].sort, actual[3]] expect(actual_sorted).to match(["OutputB", "OutputC", "OutputD", "OutputA"]) end @@ -330,11 +380,11 @@ def test_unicode write "test/long_test.rb", "puts 'this is a long test'" write "test/short_test.rb", "puts 'short test'" - group_1_result = run_tests("test", :processes => 2, :add => '--only-group 1') + group_1_result = run_tests("test", processes: 2, add: '--only-group 1') expect(group_1_result).to include("this is a long test") expect(group_1_result).not_to include("short test") - group_2_result = run_tests("test", :processes => 2, :add => '--only-group 2') + group_2_result = run_tests("test", processes: 2, add: '--only-group 2') expect(group_2_result).not_to include("this is a long test") expect(group_2_result).to include("short test") end @@ -345,7 +395,7 @@ def test_unicode it "captures seed with random failures with --verbose" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){1.should == 2}}' - result = run_tests "spec --verbose", :add => "--test-options '--seed 1234'", :fail => true, :type => 'rspec' + result = run_tests "spec --verbose", add: "--test-options '--seed 1234'", fail: true, type: 'rspec' expect(result).to include("Randomized with seed 1234") expect(result).to include("bundle exec rspec spec/xxx2_spec.rb --seed 1234") end @@ -360,7 +410,7 @@ def test_unicode it "passes test options" do write "test/x1_test.rb", "require 'test/unit'; class XTest < Test::Unit::TestCase; def test_xxx; end; end" - result = run_tests("test", :add => '--test-options "-v"') + result = run_tests("test", add: '--test-options "-v"') expect(result).to include('test_xxx') # verbose output of every test end @@ -380,7 +430,7 @@ def test_unicode it "runs tests which outputs accented characters" do write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I print accented characters" write "features/steps/a.rb", "#encoding: utf-8\nGiven('I print accented characters'){ puts \"I tu też\" }" - result = run_tests "features", :type => "cucumber", :add => '--pattern good' + result = run_tests "features", type: "cucumber", add: '--pattern good' expect(result).to include('I tu też') end @@ -390,7 +440,7 @@ def test_unicode write "features/b.feature", "Feature: xxx\n Scenario: xxx\n Given I FAIL" write "features/steps/a.rb", "Given('I print TEST_ENV_NUMBER'){ puts \"YOUR TEST ENV IS \#{ENV['TEST_ENV_NUMBER']}!\" }" - result = run_tests "features", :type => "cucumber", :add => '--pattern good' + result = run_tests "features", type: "cucumber", add: '--pattern good' expect(result).to include('YOUR TEST ENV IS 2!') expect(result).to include('YOUR TEST ENV IS !') @@ -406,7 +456,7 @@ def test_unicode # needs sleep so that runtime loggers dont overwrite each other initially write "features/good#{i}.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit" } - run_tests "features", :type => "cucumber" + run_tests "features", type: "cucumber" expect(read(log).gsub(/\.\d+/, '').split("\n")).to match_array(["features/good0.feature:0", "features/good1.feature:0"]) end @@ -414,7 +464,7 @@ def test_unicode 2.times { |i| write "features/good#{i}.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" } - result = run_tests "features", :type => "cucumber", :add => '-n 3' + result = run_tests "features", type: "cucumber", add: '-n 3' expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end @@ -424,7 +474,7 @@ def test_unicode write "features/pass.feature", "Feature: xxx\n Scenario: xxx\n Given I pass" write "features/fail1.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" write "features/fail2.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" - results = run_tests "features", :processes => 3, :type => "cucumber", :fail => true + results = run_tests "features", processes: 3, type: "cucumber", fail: true failing_scenarios = if Gem.win_platform? ["cucumber features/fail1.feature:2 # Scenario: xxx", "cucumber features/fail2.feature:2 # Scenario: xxx"] @@ -459,7 +509,7 @@ def test_unicode | one | | two | EOS - result = run_tests "features", :type => "cucumber", :add => "--group-by scenarios" + result = run_tests "features", type: "cucumber", add: "--group-by scenarios" expect(result).to include("2 processes for 4 scenarios") end @@ -467,14 +517,14 @@ def test_unicode write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" write "features/good2.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" - result = run_tests "features", :type => "cucumber", :add => '--group-by steps' + result = run_tests "features", type: "cucumber", add: '--group-by steps' expect(result).to include("2 processes for 2 features") end it "captures seed with random failures with --verbose" do write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" - result = run_tests "features --verbose", :type => "cucumber", :add => '--test-options "--order random:1234"', :fail => true + result = run_tests "features --verbose", type: "cucumber", add: '--test-options "--order random:1234"', fail: true expect(result).to include("Randomized with seed 1234") expect(result).to match(%r{bundle exec cucumber "?features/good1.feature"? --order random:1234}) end @@ -497,7 +547,7 @@ class A < Spinach::FeatureSteps it "runs tests which outputs accented characters" do write "features/good1.feature", "Feature: a\n Scenario: xxx\n Given I print accented characters" write "features/steps/a.rb", "#encoding: utf-8\nclass A < Spinach::FeatureSteps\nGiven 'I print accented characters' do\n puts \"I tu też\" \n end\nend" - result = run_tests "features", :type => "spinach", :add => 'features/good1.feature' #, :add => '--pattern good' + result = run_tests "features", type: "spinach", add: 'features/good1.feature' #, :add => '--pattern good' expect(result).to include('I tu też') end @@ -506,7 +556,7 @@ class A < Spinach::FeatureSteps write "features/good2.feature", "Feature: a\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" write "features/b.feature", "Feature: b\n Scenario: xxx\n Given I FAIL" #Expect this not to be run - result = run_tests "features", :type => "spinach", :add => '--pattern good' + result = run_tests "features", type: "spinach", add: '--pattern good' expect(result).to include('YOUR TEST ENV IS 2!') expect(result).to include('YOUR TEST ENV IS !') @@ -522,7 +572,7 @@ class A < Spinach::FeatureSteps # needs sleep so that runtime loggers dont overwrite each other initially write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit" } - run_tests "features", :type => "spinach" + run_tests "features", type: "spinach" expect(read(log).gsub(/\.\d+/, '').split("\n")).to match_array(["features/good0.feature:0", "features/good1.feature:0"]) end @@ -530,7 +580,7 @@ class A < Spinach::FeatureSteps 2.times { |i| write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n" } - result = run_tests "features", :type => "spinach", :add => '-n 3' + result = run_tests "features", type: "spinach", add: '-n 3' expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end From 725c56a28068c42855eed5781071e8f05ff193db Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 23 Jul 2020 23:02:13 -0700 Subject: [PATCH 052/177] v3.1.0 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index a0ef3d1ab..40eb168c5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.0.0) + parallel_tests (3.1.0) parallel GEM @@ -54,7 +54,7 @@ GEM middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) - parallel (1.19.1) + parallel (1.19.2) power_assert (1.2.0) protobuf-cucumber (3.10.8) activesupport (>= 3.2) diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 36c0a102e..945e85fae 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '3.0.0' + VERSION = Version = '3.1.0' end From f3355e53027ae797d8af103311795d99ae2a6802 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 23 Jul 2020 23:05:02 -0700 Subject: [PATCH 053/177] changelog --- CHANGELOG.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2a9eb8d8..af0bad05b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,12 +8,18 @@ ### Added -- `--fail-fast` stops all groups if one group fails. Can be used to stop all groups if one test failed by using `fail-fast` in the test-framework too (for example rspec via `--test-options '--fail-fast'` or in `.rspec_parallel`). +- None ### Fixed - None +## 3.1.0 - 2020-07-23 + +### Added + +- `--fail-fast` stops all groups if one group fails. Can be used to stop all groups if one test failed by using `fail-fast` in the test-framework too (for example rspec via `--test-options '--fail-fast'` or in `.rspec_parallel`). + ## 3.0.0 - 2020-06-10 ### Breaking Changes From a9ee96306ba829ddb5caf7e57119288f370df3f3 Mon Sep 17 00:00:00 2001 From: Tobias Pfeiffer Date: Tue, 11 Aug 2020 20:09:14 +0200 Subject: [PATCH 054/177] Highlight availability of ParallelTests module (#773) * Highlight availability of ParallelTests module Fixes #772 * Add explicit require as a fix instead --- Readme.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 3463335a4..29e99ff68 100644 --- a/Readme.md +++ b/Readme.md @@ -82,6 +82,8 @@ Running things once =================== ```Ruby +require "parallel_tests" + # preparation: # affected by race-condition: first process may boot slower than the second # either sleep a bit or use a lock for example File.lock @@ -97,7 +99,6 @@ at_exit do undo_something end end - ``` Even test group run-times @@ -258,7 +259,7 @@ TIPS - Use [rspec-retry](https://github.com/NoRedInk/rspec-retry) (not rspec-rerun) to rerun failed tests. - [JUnit formatter configuration](https://github.com/grosser/parallel_tests/wiki#with-rspec_junit_formatter----by-jgarber) - Use [parallel_split_test](https://github.com/grosser/parallel_split_test) to run multiple scenarios in a single spec file, concurrently. (`parallel_tests` [works at the file-level and intends to stay that way](https://github.com/grosser/parallel_tests/issues/747#issuecomment-580216980)) - + ### Cucumber - Add a `parallel: foo` profile to your `config/cucumber.yml` and it will be used to run parallel tests From ab0f8eb2d8e8419b6fab09fcea1f2d74cea10d1a Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Fri, 21 Aug 2020 23:59:49 +0900 Subject: [PATCH 055/177] Tweak an error message (#775) I have encountered the following error message in real world application development. ```console RuntimeError: Runtime log file 'tmp/parallel_runtime_rspec.log' does not contain sufficient data to sort 578 test files, please update it. ``` I think that removing a runtime log file may be a faster solution. This PR adds a hint to options users should choose. --- lib/parallel_tests/test/runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 55e48fafb..fac956751 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -173,7 +173,7 @@ def sort_by_runtime(tests, runtimes, options={}) allowed_missing -= 1 unless time = runtimes[test] if allowed_missing < 0 log = options[:runtime_log] || runtime_log - raise "Runtime log file '#{log}' does not contain sufficient data to sort #{tests.size} test files, please update it." + raise "Runtime log file '#{log}' does not contain sufficient data to sort #{tests.size} test files, please update or remove it." end [test, time] end From 135673d211aa5e970127a63379c4eb49da37c68a Mon Sep 17 00:00:00 2001 From: Chris Gunther Date: Thu, 27 Aug 2020 21:30:17 -0400 Subject: [PATCH 056/177] Force RAILS_ENV to be "test" in rake tasks (#776) After #732, if you're using the SQL schema format, `parallel:prepare` now calls `db:purge db:structure:load` where it used to call `db:test:prepare`. The old task forced using the test environment, however the new tasks make no assumptions about the environment. Therefore, when combined with a Spring-ified rake binstub, where Spring defaults to the development environment, when `parallel:prepare` calls `db:purge db:structure:load`, they're running in the development environment against the development database, instead of in the test environment against the test database. Now the environment is forced to be "test" in all rake tasks regardless of the RAILS_ENV that might have been set, whether by Spring or the user. This has the side-effect of removing the ability to run the tasks in a test-like environment that's named something other than "test". I believe this fixes #768. --- CHANGELOG.md | 4 ++-- lib/parallel_tests/tasks.rb | 2 +- spec/parallel_tests/tasks_spec.rb | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af0bad05b..0baa9a533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Breaking Changes -- None +- RAILS_ENV cannot be specified for rake tasks (#776). ### Added @@ -12,7 +12,7 @@ ### Fixed -- None +- Rake tasks will no longer run against development environment when using a Spring-ified rake binstub (#776). ## 3.1.0 - 2020-07-23 diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 415ac1fc1..406fece48 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -5,7 +5,7 @@ module ParallelTests module Tasks class << self def rails_env - ENV['RAILS_ENV'] || 'test' + 'test' end def rake_bin diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index acc93d2db..0ab65b6b0 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -35,13 +35,13 @@ end describe ".rails_env" do - it "should be test when nothing was set" do + it "should be test" do expect(ParallelTests::Tasks.rails_env).to eq("test") end - it "should be whatever was set" do + it "should disregard whatever was set" do ENV["RAILS_ENV"] = "foo" - expect(ParallelTests::Tasks.rails_env).to eq("foo") + expect(ParallelTests::Tasks.rails_env).to eq("test") end end From c410a72a6d0b1279637c84d766737599e9719c53 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 27 Aug 2020 18:30:43 -0700 Subject: [PATCH 057/177] v3.2.0 --- CHANGELOG.md | 14 ++++++++++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0baa9a533..e1253599c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ ### Breaking Changes +- None + +### Added + +- None + +### Fixed + +- None + +## 3.2.0 - 2020-08-27 + +### Breaking Changes + - RAILS_ENV cannot be specified for rake tasks (#776). ### Added diff --git a/Gemfile.lock b/Gemfile.lock index 40eb168c5..1d97b151e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.1.0) + parallel_tests (3.2.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 945e85fae..8c7129a96 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '3.1.0' + VERSION = Version = '3.2.0' end From d95ea27868effb1ad447a71bc4a04086e688d73e Mon Sep 17 00:00:00 2001 From: Vikram B Kumar Date: Wed, 16 Sep 2020 15:22:21 -0400 Subject: [PATCH 058/177] Add support for more than one isolated process. (#779) --- CHANGELOG.md | 2 ++ Readme.md | 4 ++- lib/parallel_tests/cli.rb | 6 ++++ lib/parallel_tests/grouper.rb | 37 +++++++++++++++++++++---- spec/parallel_tests/cli_spec.rb | 20 +++++++++++++ spec/parallel_tests/grouper_spec.rb | 13 +++++++++ spec/parallel_tests/test/runner_spec.rb | 20 +++++++++++++ 7 files changed, 96 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1253599c..a67fa413b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Added support for multiple isolated processes. + ### Breaking Changes - None diff --git a/Readme.md b/Readme.md index 29e99ff68..9f49d054f 100644 --- a/Readme.md +++ b/Readme.md @@ -205,7 +205,9 @@ Options are: default - runtime when runtime log is filled otherwise filesize -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run -s, --single [PATTERN] Run all matching files in the same process - -i, --isolate Do not run any other tests in the group used by --single(-s) + -i, --isolate Do not run any other tests in the group used by --single(-s). + Automatically turned on if --isolate-n is set above 0. + --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on. --only-group INT[, INT] -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER'] -o, --test-options '[OPTIONS]' execute test commands with those options diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 089cd8386..c9b0bca81 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -192,6 +192,12 @@ def parse_options!(argv) options[:isolate] = true end + opts.on("--isolate-n [PROCESSES]", + Integer, + "Use 'isolate' singles with number of processes, default: 1.") do |n| + options[:isolate_count] = n + end + opts.on("--only-group INT[, INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index 0db018a7e..de0d1babc 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -15,19 +15,46 @@ def in_even_groups_by_size(items, num_groups, options= {}) groups = Array.new(num_groups) { {:items => [], :size => 0} } # add all files that should run in a single process to one group - (options[:single_process] || []).each do |pattern| - matched, items = items.partition { |item, _size| item =~ pattern } - matched.each { |item, size| add_to_group(groups.first, item, size) } + single_process_patterns = options[:single_process] || [] + + single_items, items = items.partition do |item, _size| + single_process_patterns.any? { |pattern| item =~ pattern } end - groups_to_fill = (options[:isolate] ? groups[1..-1] : groups) - group_features_by_size(items_to_group(items), groups_to_fill) + isolate_count = isolate_count(options) + + if isolate_count >= num_groups + raise 'Number of isolated processes must be less than total the number of processes' + end + + if isolate_count >= 1 + # add all files that should run in a multiple isolated processes to their own groups + group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)]) + # group the non-isolated by size + group_features_by_size(items_to_group(items), groups[isolate_count..-1]) + else + # add all files that should run in a single non-isolated process to first group + single_items.each { |item, size| add_to_group(groups.first, item, size) } + + # group all by size + group_features_by_size(items_to_group(items), groups) + end groups.map! { |g| g[:items].sort } end private + def isolate_count(options) + if options[:isolate_count] && options[:isolate_count] > 1 + options[:isolate_count] + elsif options[:isolate] + 1 + else + 0 + end + end + def largest_first(files) files.sort_by{|_item, size| size }.reverse end diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 2eecd202d..7be6f4c8e 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -107,6 +107,26 @@ def call(*args) end end + context "single and isolate" do + it "single_process should be an array of patterns" do + expect(call(["test", "--single", '1'])).to eq(defaults.merge(single_process: [/1/])) + end + + it "single_process should be an array of patterns" do + expect(call(["test", "--single", '1', "--single", '2'])).to eq(defaults.merge(single_process: [/1/, /2/])) + end + + it "isolate should set isolate_count defaults" do + expect(call(["test", "--single", '1', "--isolate"])).to eq(defaults.merge(single_process: [/1/], isolate: true)) + end + + it "isolate_n should set isolate_count and turn on isolate" do + expect(call(["test", "-n", "3", "--single", '1', "--isolate-n", "2"])).to eq( + defaults.merge(count: 3, single_process: [/1/], isolate_count: 2) + ) + end + end + context "when the -- option separator is used" do it "interprets arguments as files/directories" do expect(call(%w(-- test))).to eq( files: %w(test)) diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index d8710d95b..ee571a364 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -54,9 +54,22 @@ def call(num_groups, options={}) expect(call(2, :single_process => [/1|2|3|4/])).to eq([["1", "2", "3", "4"], ["5"]]) end + it "groups single items into specified isolation groups" do + expect(call(3, :single_process => [/1|2|3|4/], :isolate_count => 2)).to eq([["1", "4"], ["2", "3"], ["5"]]) + end + it "groups single items with others if there are too few" do expect(call(2, :single_process => [/1/])).to eq([["1", "3", "4"], ["2", "5"]]) end + + it "groups must abort when isolate_count is out of bounds" do + expect { + call(3, :single_process => [/1/], :isolate_count => 3) + }.to raise_error( + "Number of isolated processes must be less than total the number of processes" + ) + end + end describe '.by_scenarios' do diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 90a6fcf68..34b1778eb 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -146,6 +146,26 @@ def call(*args) expect(valid_combinations).to include(actual) end + + it "groups by size and use specified number of isolation groups" do + skip if RUBY_PLATFORM == "java" + expect(ParallelTests::Test::Runner).to receive(:runtimes). + and_return({"aaa1" => 1, "aaa2" => 3, "aaa3" => 2, "bbb" => 3, "ccc" => 1, "ddd" => 2}) + result = call(["aaa1", "aaa2", "aaa3", "bbb", "ccc", "ddd", "eee"], 4, isolate_count: 2, single_process: [/^aaa/], group_by: :runtime) + + isolated_1, isolated_2, *groups = result + expect(isolated_1).to eq(["aaa2"]) + expect(isolated_2).to eq(["aaa1", "aaa3"]) + actual = groups.map(&:to_set).to_set + + # both eee and ccs are the same size, so either can be in either group + valid_combinations = [ + [["bbb", "eee"], ["ccc", "ddd"]].map(&:to_set).to_set, + [["bbb", "ccc"], ["eee", "ddd"]].map(&:to_set).to_set + ] + + expect(valid_combinations).to include(actual) + end end end From a798ae733e4e646cc3b948610c919e53ebcdc9b0 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Wed, 16 Sep 2020 12:22:43 -0700 Subject: [PATCH 059/177] v3.3.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1d97b151e..77a55458b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.2.0) + parallel_tests (3.3.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 8c7129a96..3494c3611 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '3.2.0' + VERSION = Version = '3.3.0' end From af4d79627842a0927b244aa1a3e9b9cc07eaa01b Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Wed, 16 Sep 2020 12:28:15 -0700 Subject: [PATCH 060/177] update changelog --- CHANGELOG.md | 8 +++++++- Readme.md | 5 +++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a67fa413b..1ada4f302 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- Added support for multiple isolated processes. +Add changes here in your PR ### Breaking Changes @@ -16,6 +16,12 @@ - None +## 3.3.0 - 2020-09-16 + +### Added + +- Added support for multiple isolated processes. + ## 3.2.0 - 2020-08-27 ### Breaking Changes diff --git a/Readme.md b/Readme.md index 9f49d054f..72003c515 100644 --- a/Readme.md +++ b/Readme.md @@ -205,9 +205,9 @@ Options are: default - runtime when runtime log is filled otherwise filesize -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run -s, --single [PATTERN] Run all matching files in the same process - -i, --isolate Do not run any other tests in the group used by --single(-s). + -i, --isolate Do not run any other tests in the group used by --single(-s). Automatically turned on if --isolate-n is set above 0. - --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on. + --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on. --only-group INT[, INT] -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER'] -o, --test-options '[OPTIONS]' execute test commands with those options @@ -378,6 +378,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Calaway](https://github.com/calaway) - [alboyadjian](https://github.com/alboyadjian) - [Nathan Broadbent](https://github.com/ndbroadbent) + - [Vikram B Kumar](https://github.com/v-kumar) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 0279b3cb0dd59a1b14879f41eb7a88009cc65bfe Mon Sep 17 00:00:00 2001 From: Liz Zhang Date: Tue, 20 Oct 2020 14:37:37 -0400 Subject: [PATCH 061/177] Update changelog to include releases 2.23.0 to 2.32.0 (#786) --- CHANGELOG.md | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ada4f302..3a51d068b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -62,6 +62,104 @@ Add changes here in your PR - Drop ruby 2.3 support (#760) - Drop ruby 2.2 support (#759) +## 2.32.0 - 2020-03-15 + +### Fixed +- Calculate unknown runtimes lazily when running tests grouped by runtime ([#750](https://github.com/grosser/parallel_tests/pull/750)). + +## 2.31.0 - 2020-01-31 + +### Fixed +- File paths passed from the CLI are now cleaned (consecutive slashes and useless dots removed) ([#748](https://github.com/grosser/parallel_tests/pull/748)). + +## 2.30.1 - 2020-01-14 + +### Added +- Add project metadata to gemspec ([#739](https://github.com/grosser/parallel_tests/pull/739)). + +## Fixed +- Fix bundler deprecation warning related to `bundle show`) ([#744](https://github.com/grosser/parallel_tests/pull/744)). +- Fix numerous flakey tests ([#736](https://github.com/grosser/parallel_tests/pull/736), [#741](https://github.com/grosser/parallel_tests/pull/741)). + +## 2.30.0 - 2019-12-10 + +### Added +- Support db:structure:dump and load structure in parallel ([#732](ht.tps://github.com/grosser/parallel_tests/pull/732)). +- Add note to the README about using the spring-commands-parallel-tests gem to automatically patch and enable Spring ([#731](https://github.com/grosser/parallel_tests/pull/731)). + +### Fixed +- Refactor logic in the `parallel:prepare` task ([#737](https://github.com/grosser/parallel_tests/pull/737)). +- Update README to use :sql schema format. +- Fix loading of the `version` file when using a local git repo with Bundler ([#730](https://github.com/grosser/parallel_tests/pull/730)). + +## 2.29.2 - 2019-08-06 + +### Fixed +- Eliminate some ruby warnings relating to ambigious arguments, unused variables, a redefined method, and uninitialized instance variables ([#712](https://github.com/grosser/parallel_tests/pull/712)). + +## 2.29.1 - 2019-06-13 + +### Fixed +- Fix NameError due to not requiring `shellwords` ([#707](https://github.com/grosser/parallel_tests/pull/707)). + +## 2.29.0 - 2019-05-04 + +### Added +- `--verbose-process-command`, which prints the command that will be executed by each process before it begins ([#697](https://github.com/grosser/parallel_tests/pull/697/files)). +- `--verbose-rerun-command`, which prints the command executed by that process after a process fails ([#697](https://github.com/grosser/parallel_tests/pull/697/files)). + +## 2.28.0 - 2019-02-07 + +### Added +- `exclude-pattern`, which excludes tests matching the passed in regex pattern ([#682](https://github.com/grosser/parallel_tests/pull/682), [#683](https://github.com/grosser/parallel_tests/pull/683)). + +## 2.27.1 - 2019-01-01 + +### Changed +- `simulate_output_for_ci` now outputs dots (`.`) even after the first parallel thread finishes ([#673](https://github.com/grosser/parallel_tests/pull/673)). + +### Fixed +- Typo in CLI options ([#672](https://github.com/grosser/parallel_tests/pull/672)). + +## 2.27.0 - 2018-11-09 + +### Added +- Support for new Cucumber tag expressions syntax ([#668](https://github.com/grosser/parallel_tests/pull/668)). + +## 2.26.2 - 2018-10-29 + +### Added +- `db:test:purge` is now `db:purge` so it can be used in any environment, not just the `test` environment. This change is backwards compatible. ([#665](https://github.com/grosser/parallel_tests/pull/665)). +- Tests against Rails 5.1 and 5.2 ([#663])(https://github.com/grosser/parallel_tests/pull/663)). + +## 2.26.0 - 2018-10-25 + +### Fixed +- Update formatter to use Cucumber events API instead of deprecated API ([#664](https://github.com/grosser/parallel_tests/pull/664)) + +## 2.25.0 - 2018-10-24 + +### Fixed +- Commands and their respective outputs are now grouped together when using the `verbose` and `serialize-output` flags together ([#660](https://github.com/grosser/parallel_tests/pull/660)). + +### Dependencies +- Dropped support for MiniTest 4 and Test-Unit ([#662](https://github.com/grosser/parallel_tests/pull/662)). +- Dropped support for Ruby 2.1 ([#659](https://github.com/grosser/parallel_tests/pull/659)) + +## 2.24.0 - 2018-10-24 + +### Fixed +- Improve accuracy when recording example times ([#661](https://github.com/grosser/parallel_tests/pull/661)). + +### Dependencies +- Dropped support for Ruby 2.0 ([#661](https://github.com/grosser/parallel_tests/pull/661)). + +## 2.23.0 - 2018-09-14 + +### Added +- Rake task now passes through additional arguments to the CLI ([#656](https://github.com/grosser/parallel_tests/pull/656)). + + ## Previous versions No docs yet. Contributions welcome! From 45fcdb8595a86ce1a0ee1eca872b97be3db222dd Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 Nov 2020 13:52:41 -0800 Subject: [PATCH 062/177] avoid CI warnings (#788) --- .github/workflows/test.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6ee8bd06e..43c712461 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,6 +17,8 @@ jobs: os: [ubuntu-latest, windows-latest] env: RUBYOPT: -W0 + # avoid warnings from https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ + ACTIONS_ALLOW_UNSECURE_COMMANDS: true steps: - uses: actions/checkout@master - name: Setup OS dependencies @@ -27,10 +29,7 @@ jobs: - name: Install dependencies run: | bundle install - - name: Change TMPDIR to something non symlinked - run: | - echo "::set-env name=TMPDIR::$HOME/tmp" - mkdir $HOME/tmp - name: Run test run: bundle exec rake + # TODO: this will always show green, fix once https://github.com/actions/toolkit/issues/399 is resolved continue-on-error: ${{ endsWith(matrix.ruby, 'head') }} From f646fd2e70b0ba3d0ac2c38b408e8a12c0efc513 Mon Sep 17 00:00:00 2001 From: Joshua Pinter Date: Sun, 22 Nov 2020 19:00:01 -0700 Subject: [PATCH 063/177] Colorize summarized RSpec results. (#787) RSpec colorizes its results based on if there are any failures (red), pending (yellow) or none of the above (green). The method used to summarize the results from the various threads, `summarize_results` was not doing this colorization. This commit applies the same colorization that RSpec does but does not depend on RSpec::Core for colorization. It utilizes red for failure, yellow for pending and green for success. - Entry in `CHANGELOG.md` added. - Specs added for all major scenarios: - No failures or pending. - Just pending. - Failures and pending. - Just failures. Co-authored-by: Michael Grosser Co-authored-by: Michael Grosser --- CHANGELOG.md | 2 +- lib/parallel_tests/rspec/runner.rb | 16 ++++++++ spec/parallel_tests/rspec/runner_spec.rb | 51 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a51d068b..607254235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ Add changes here in your PR ### Added -- None +- Colorize summarized RSpec results.([#787](https://github.com/grosser/parallel_tests/pull/787)). ### Fixed diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index e84c48809..c1d6b16e1 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -48,6 +48,22 @@ def command_with_seed(cmd, seed) "#{clean} --seed #{seed}" end + # Summarize results from threads and colorize results based on failure and pending counts. + # + def summarize_results(results) + sums = sum_up_results(results) + text = super + return text unless $stdout.tty? + color = + if sums['failure'].positive? + 31 # red + elsif sums['pending'].positive? + 33 # yellow + else + 32 # green + end + "\e[#{color}m#{text}\e[0m" + end private diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index 5dc013717..4fee54903 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -128,6 +128,57 @@ def call(*args) end end + describe '.summarize_results' do + + context 'not on TTY device' do + before { allow($stdout).to receive(:tty?).and_return false } + + it 'is not colourized' do + results = ParallelTests::RSpec::Runner.send(:summarize_results, ['1 example, 0 failures, 0 pendings']) + + expect(results).to eq('1 example, 0 failures, 0 pendings') + end + end + + context 'on TTY device' do + before { allow($stdout).to receive(:tty?).and_return true } + + subject(:colorized_results) { ParallelTests::RSpec::Runner.send(:summarize_results, [result_string]) } + + context 'when there are no pending or failed tests' do + let(:result_string) { '1 example, 0 failures, 0 pendings' } + + it 'is green' do + expect(colorized_results).to eq("\e[32m#{result_string}\e[0m") # 32 is green + end + end + + context 'when there is a pending test and no failed tests' do + let(:result_string) { '1 example, 0 failures, 1 pending' } + + it 'is yellow' do + expect(colorized_results).to eq("\e[33m#{result_string}\e[0m") # 33 is yellow + end + end + + context 'when there is a pending test and a failed test' do + let(:result_string) { '1 example, 1 failure, 1 pending' } + + it 'is red' do + expect(colorized_results).to eq("\e[31m#{result_string}\e[0m") # 31 is red + end + end + + context 'when there is no pending tests and a failed test' do + let(:result_string) { '1 example, 1 failure, 0 pendings' } + + it 'is red' do + expect(colorized_results).to eq("\e[31m#{result_string}\e[0m") # 31 is red + end + end + end + end + describe ".command_with_seed" do def call(args) base = "ruby -Ilib:test test/minitest/test_minitest_unit.rb" From f40dfd529dd4c7fff2a0eff8a018c84e9a321d15 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 Nov 2020 19:15:21 -0800 Subject: [PATCH 064/177] cleanup --- lib/parallel_tests/rspec/runner.rb | 2 +- spec/parallel_tests/rspec/runner_spec.rb | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index c1d6b16e1..1f66b2f28 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -51,9 +51,9 @@ def command_with_seed(cmd, seed) # Summarize results from threads and colorize results based on failure and pending counts. # def summarize_results(results) - sums = sum_up_results(results) text = super return text unless $stdout.tty? + sums = sum_up_results(results) color = if sums['failure'].positive? 31 # red diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index 4fee54903..09fa0ec47 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -129,7 +129,6 @@ def call(*args) end describe '.summarize_results' do - context 'not on TTY device' do before { allow($stdout).to receive(:tty?).and_return false } From 0ecbab094ca2e034144b4f7103c8aa6d1db1402e Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 Nov 2020 19:15:51 -0800 Subject: [PATCH 065/177] v3.4.0 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 77a55458b..e7a340356 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.3.0) + parallel_tests (3.4.0) parallel GEM @@ -54,7 +54,7 @@ GEM middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) - parallel (1.19.2) + parallel (1.20.1) power_assert (1.2.0) protobuf-cucumber (3.10.8) activesupport (>= 3.2) diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 3494c3611..969f9968a 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,3 @@ module ParallelTests - VERSION = Version = '3.3.0' + VERSION = Version = '3.4.0' end From e410e61e4804e79aa67f7b5c36ccf6248a83132c Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 Nov 2020 19:17:30 -0800 Subject: [PATCH 066/177] thx for the PR --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 72003c515..28e3534c4 100644 --- a/Readme.md +++ b/Readme.md @@ -379,6 +379,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [alboyadjian](https://github.com/alboyadjian) - [Nathan Broadbent](https://github.com/ndbroadbent) - [Vikram B Kumar](https://github.com/v-kumar) + - [https://github.com/joshuapinter](Joshua Pinter) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 117cce9f2352c98f8f9bbf8f72869ada5bd042b8 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 Nov 2020 22:55:06 -0800 Subject: [PATCH 067/177] docs (#790) --- Readme.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Readme.md b/Readme.md index 28e3534c4..1dc9b4de7 100644 --- a/Readme.md +++ b/Readme.md @@ -142,17 +142,19 @@ Add the following to your `.rspec_parallel` (or `.rspec`) : RSpec: FailuresLogger ----------------------- -Produce pasteable command-line snippets for each failed example. +Produce pastable command-line snippets for each failed example. For example: -E.g. - - rspec /path/to/my_spec.rb:123 # should do something +```bash +rspec /path/to/my_spec.rb:123 # should do something +``` -Add the following to your `.rspec_parallel` (or `.rspec`) : +Add to `.rspec_parallel` or use as CLI flag: --format progress --format ParallelTests::RSpec::FailuresLogger --out tmp/failing_specs.log +(Not needed to retry failures, for that pass [--only-failures](https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures) to rspec) + Cucumber: FailuresLogger ----------------------- From 54cc79884815427e6a13c15cb47afeb11220aced Mon Sep 17 00:00:00 2001 From: brchristian Date: Thu, 3 Dec 2020 20:50:54 -0800 Subject: [PATCH 068/177] Pluralize 'spec(s) per process' (#792) --- lib/parallel_tests/cli.rb | 12 +++++++++++- spec/integration_spec.rb | 10 +++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index c9b0bca81..7cc584d43 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -142,7 +142,17 @@ def report_number_of_tests(groups) num_processes = groups.size num_tests = groups.map(&:size).inject(0, :+) tests_per_process = (num_processes == 0 ? 0 : num_tests / num_processes) - puts "#{num_processes} processes for #{num_tests} #{name}s, ~ #{tests_per_process} #{name}s per process" + puts "#{pluralize(num_processes, 'process')} for #{pluralize(num_tests, name)}, ~ #{pluralize(tests_per_process, name)} per process" + end + + def pluralize(n, singular) + if n == 1 + "1 #{singular}" + elsif singular.end_with?('s', 'sh', 'ch', 'x', 'z') + "#{n} #{singular}es" + else + "#{n} #{singular}s" + end end #exit with correct status code so rake parallel:test && echo 123 works diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index bfb32323c..5cdb7a275 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -60,7 +60,7 @@ def self.it_fails_without_any_files(type) end end - let(:printed_commands) { "specs per process\nbundle exec rspec" } + let(:printed_commands) { /specs? per process\nbundle exec rspec/ } let(:printed_rerun) { "run the group again:\n\nbundle exec rspec" } it "runs tests in parallel" do @@ -80,7 +80,7 @@ def self.it_fails_without_any_files(type) expect(result).to include_exactly_times(/Took \d+ seconds/, 1) # parallel summary # verify empty groups are discarded. if retained then it'd say 4 processes for 2 specs - expect(result).to include '2 processes for 2 specs, ~ 1 specs per process' + expect(result).to include '2 processes for 2 specs, ~ 1 spec per process' end describe "--fail-fast" do @@ -168,7 +168,7 @@ def test_unicode write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' result = run_tests "spec --verbose", type: 'rspec', fail: true - expect(result).to include printed_commands + expect(result).to match printed_commands expect(result).to include printed_rerun expect(result).to include "bundle exec rspec spec/xxx_spec.rb" expect(result).to include "bundle exec rspec spec/xxx2_spec.rb" @@ -178,14 +178,14 @@ def test_unicode write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' result = run_tests "spec --verbose-rerun-command", type: 'rspec', fail: true expect(result).to include printed_rerun - expect(result).to_not include printed_commands + expect(result).to_not match printed_commands end it "shows only process with --verbose-process-command" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' result = run_tests "spec --verbose-process-command", type: 'rspec', fail: true expect(result).to_not include printed_rerun - expect(result).to include printed_commands + expect(result).to match printed_commands end it "fails when tests fail" do From ca3c936cf123c1abb3fe31ceed3580d9e9e17532 Mon Sep 17 00:00:00 2001 From: Dario Lombardo Date: Thu, 10 Dec 2020 01:50:02 +0100 Subject: [PATCH 069/177] readme: fix link order. (#793) --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 1dc9b4de7..c1c324308 100644 --- a/Readme.md +++ b/Readme.md @@ -381,7 +381,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [alboyadjian](https://github.com/alboyadjian) - [Nathan Broadbent](https://github.com/ndbroadbent) - [Vikram B Kumar](https://github.com/v-kumar) - - [https://github.com/joshuapinter](Joshua Pinter) + - [Joshua Pinter](https://github.com/joshuapinter) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 2a60b39c95072661e76023bb86ddf32b4d91b0fa Mon Sep 17 00:00:00 2001 From: Benjamin Quorning <22333+bquorning@users.noreply.github.com> Date: Tue, 5 Jan 2021 21:44:52 +0100 Subject: [PATCH 070/177] Remove spaces in --only-group flag documentation (#795) optparse documentation says that Array type flags are "Strings separated by ',' (e.g. 1,2,3)". And indeed `--only-group 1, 2, 3` only tests group 1. https://ruby-doc.org/stdlib-2.6.6/libdoc/optparse/rdoc/OptionParser.html --- Readme.md | 2 +- lib/parallel_tests/cli.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index c1c324308..141eaecf3 100644 --- a/Readme.md +++ b/Readme.md @@ -210,7 +210,7 @@ Options are: -i, --isolate Do not run any other tests in the group used by --single(-s). Automatically turned on if --isolate-n is set above 0. --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on. - --only-group INT[, INT] + --only-group INT[,INT] -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER'] -o, --test-options '[OPTIONS]' execute test commands with those options -t, --type [TYPE] test(default) / rspec / cucumber / spinach diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 7cc584d43..2646b103b 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -208,7 +208,7 @@ def parse_options!(argv) options[:isolate_count] = n end - opts.on("--only-group INT[, INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } + opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg.lstrip } From 86e93fd0469bfdc960af807ae4083814a63a7e84 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 16 Jan 2021 16:11:43 -0800 Subject: [PATCH 071/177] add rubocop (#796) * add rubocop * frozen --- .github/workflows/test.yml | 15 +- .rubocop.yml | 127 +++++++++ Gemfile | 2 + Gemfile.lock | 23 ++ Rakefile | 10 +- bin/parallel_cucumber | 3 +- bin/parallel_rspec | 3 +- bin/parallel_spinach | 3 +- bin/parallel_test | 3 +- lib/parallel_tests.rb | 6 +- lib/parallel_tests/cli.rb | 106 ++++---- .../cucumber/failures_logger.rb | 2 +- .../cucumber/features_with_steps.rb | 7 +- lib/parallel_tests/cucumber/runner.rb | 9 +- .../cucumber/scenario_line_logger.rb | 6 +- lib/parallel_tests/cucumber/scenarios.rb | 10 +- lib/parallel_tests/gherkin/io.rb | 5 +- lib/parallel_tests/gherkin/listener.rb | 19 +- lib/parallel_tests/gherkin/runner.rb | 37 ++- lib/parallel_tests/gherkin/runtime_logger.rb | 3 +- lib/parallel_tests/grouper.rb | 11 +- lib/parallel_tests/pids.rb | 5 +- lib/parallel_tests/railtie.rb | 1 + lib/parallel_tests/rspec/failures_logger.rb | 4 +- lib/parallel_tests/rspec/logger_base.rb | 16 +- lib/parallel_tests/rspec/runner.rb | 14 +- lib/parallel_tests/rspec/runtime_logger.rb | 22 +- lib/parallel_tests/rspec/summary_logger.rb | 5 +- lib/parallel_tests/spinach/runner.rb | 4 +- lib/parallel_tests/tasks.rb | 63 +++-- lib/parallel_tests/test/runner.rb | 59 ++-- lib/parallel_tests/test/runtime_logger.rb | 33 ++- lib/parallel_tests/version.rb | 3 +- parallel_tests.gemspec | 7 +- spec/fixtures/rails51/Gemfile | 1 + spec/fixtures/rails51/Gemfile.lock | 4 +- spec/fixtures/rails51/Rakefile | 1 + .../app/channels/application_cable/channel.rb | 1 + .../channels/application_cable/connection.rb | 1 + .../app/controllers/application_controller.rb | 1 + .../rails51/app/helpers/application_helper.rb | 1 + .../rails51/app/jobs/application_job.rb | 1 + .../rails51/app/mailers/application_mailer.rb | 1 + .../rails51/app/models/application_record.rb | 1 + spec/fixtures/rails51/app/models/user.rb | 1 + spec/fixtures/rails51/bin/bundle | 3 +- spec/fixtures/rails51/bin/rails | 1 + spec/fixtures/rails51/bin/rake | 1 + spec/fixtures/rails51/bin/setup | 6 +- spec/fixtures/rails51/bin/update | 5 +- spec/fixtures/rails51/bin/yarn | 5 +- spec/fixtures/rails51/config.ru | 1 + spec/fixtures/rails51/config/application.rb | 1 + spec/fixtures/rails51/config/boot.rb | 1 + spec/fixtures/rails51/config/environment.rb | 1 + .../config/environments/development.rb | 1 + .../rails51/config/environments/production.rb | 3 +- .../rails51/config/environments/test.rb | 1 + .../application_controller_renderer.rb | 1 + .../rails51/config/initializers/assets.rb | 1 + .../initializers/backtrace_silencers.rb | 1 + .../config/initializers/cookies_serializer.rb | 1 + .../initializers/filter_parameter_logging.rb | 1 + .../config/initializers/inflections.rb | 1 + .../rails51/config/initializers/mime_types.rb | 1 + .../config/initializers/wrap_parameters.rb | 1 + spec/fixtures/rails51/config/puma.rb | 7 +- spec/fixtures/rails51/config/routes.rb | 1 + .../db/migrate/20181024130108_create_users.rb | 1 + spec/fixtures/rails51/db/seeds.rb | 1 + .../test/application_system_test_case.rb | 1 + .../rails51/test/models/user2_test.rb | 1 + .../fixtures/rails51/test/models/user_test.rb | 1 + spec/fixtures/rails51/test/test_helper.rb | 3 +- spec/fixtures/rails52/Gemfile | 1 + spec/fixtures/rails52/Gemfile.lock | 4 +- spec/fixtures/rails52/Rakefile | 1 + .../app/channels/application_cable/channel.rb | 1 + .../channels/application_cable/connection.rb | 1 + .../app/controllers/application_controller.rb | 1 + .../rails52/app/helpers/application_helper.rb | 1 + .../rails52/app/jobs/application_job.rb | 1 + .../rails52/app/mailers/application_mailer.rb | 1 + .../rails52/app/models/application_record.rb | 1 + spec/fixtures/rails52/app/models/user.rb | 1 + spec/fixtures/rails52/bin/bundle | 1 + spec/fixtures/rails52/bin/rails | 1 + spec/fixtures/rails52/bin/rake | 1 + spec/fixtures/rails52/bin/setup | 3 +- spec/fixtures/rails52/bin/update | 3 +- spec/fixtures/rails52/bin/yarn | 5 +- spec/fixtures/rails52/config.ru | 1 + spec/fixtures/rails52/config/application.rb | 1 + spec/fixtures/rails52/config/boot.rb | 1 + spec/fixtures/rails52/config/environment.rb | 1 + .../config/environments/development.rb | 1 + .../rails52/config/environments/production.rb | 3 +- .../rails52/config/environments/test.rb | 1 + .../application_controller_renderer.rb | 1 + .../rails52/config/initializers/assets.rb | 1 + .../initializers/backtrace_silencers.rb | 1 + .../initializers/content_security_policy.rb | 1 + .../config/initializers/cookies_serializer.rb | 1 + .../initializers/filter_parameter_logging.rb | 1 + .../config/initializers/inflections.rb | 1 + .../rails52/config/initializers/mime_types.rb | 1 + .../config/initializers/wrap_parameters.rb | 1 + spec/fixtures/rails52/config/puma.rb | 7 +- spec/fixtures/rails52/config/routes.rb | 1 + .../db/migrate/20181024130151_create_users.rb | 1 + spec/fixtures/rails52/db/seeds.rb | 1 + .../test/application_system_test_case.rb | 1 + .../rails52/test/models/user2_test.rb | 1 + .../fixtures/rails52/test/models/user_test.rb | 1 + spec/fixtures/rails52/test/test_helper.rb | 1 + spec/integration_spec.rb | 45 +-- spec/parallel_tests/cli_spec.rb | 138 +++++----- .../cucumber/failure_logger_spec.rb | 36 +-- spec/parallel_tests/cucumber/runner_spec.rb | 9 +- .../parallel_tests/cucumber/scenarios_spec.rb | 107 +++++--- spec/parallel_tests/gherkin/listener_spec.rb | 62 ++--- .../gherkin/runner_behaviour.rb | 76 +++--- spec/parallel_tests/grouper_spec.rb | 35 ++- spec/parallel_tests/pids_spec.rb | 7 +- .../rspec/failures_logger_spec.rb | 15 +- spec/parallel_tests/rspec/logger_base_spec.rb | 1 + spec/parallel_tests/rspec/runner_spec.rb | 29 +- .../rspec/runtime_logger_spec.rb | 25 +- .../rspec/summary_logger_spec.rb | 15 +- spec/parallel_tests/spinach/runner_spec.rb | 5 +- spec/parallel_tests/tasks_spec.rb | 36 ++- spec/parallel_tests/test/runner_spec.rb | 257 ++++++++++-------- .../test/runtime_logger_spec.rb | 11 +- spec/parallel_tests_spec.rb | 11 +- spec/rails_spec.rb | 11 +- spec/spec_helper.rb | 69 +++-- 136 files changed, 1086 insertions(+), 688 deletions(-) create mode 100644 .rubocop.yml diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 43c712461..44579f9f4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,8 +13,13 @@ jobs: strategy: fail-fast: false matrix: - ruby: [2.7, 2.6, 2.5, 2.4, head, jruby-head] + ruby: ['2.7', '2.6', '2.5', '2.4', head, jruby-head] os: [ubuntu-latest, windows-latest] + task: [default] + include: + - ruby: '2.4' # lowest supported version + os: ubuntu-latest + task: rubocop env: RUBYOPT: -W0 # avoid warnings from https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ @@ -27,9 +32,9 @@ jobs: ruby-version: ${{ matrix.ruby }} apt-get: libsqlite3-dev - name: Install dependencies - run: | - bundle install - - name: Run test - run: bundle exec rake + run: bundle install --jobs 4 + - name: rake ${{ matrix.task }} + run: bundle exec rake ${{ matrix.task }} + # allow ruby/jruby-head to fail since they are moving targets # TODO: this will always show green, fix once https://github.com/actions/toolkit/issues/399 is resolved continue-on-error: ${{ endsWith(matrix.ruby, 'head') }} diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 000000000..059edea15 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,127 @@ +AllCops: + NewCops: enable + TargetRubyVersion: 2.4 + SuggestExtensions: false + Exclude: + - '**/vendor/bundle/**/*' + - 'spec/fixtures/*/db/schema.rb' + +Style/StringLiterals: + Enabled: false + +Style/StringLiteralsInInterpolation: + Enabled: false + +Lint/AmbiguousRegexpLiteral: + Enabled: false + +Bundler/OrderedGems: + Enabled: false + +Metrics: + Enabled: false + +Style/Documentation: + Enabled: false + +Layout/EmptyLineAfterMagicComment: + Enabled: false + +Layout/EndAlignment: + EnforcedStyleAlignWith: variable + +Layout/MultilineOperationIndentation: + Enabled: false + +Layout/MultilineMethodCallIndentation: + EnforcedStyle: indented + +Style/NumericPredicate: + EnforcedStyle: comparison + +Layout/EmptyLineAfterGuardClause: + Enabled: false + +Layout/FirstHashElementLineBreak: + Enabled: true # Opt-in + +# Opt-in +Layout/FirstMethodArgumentLineBreak: + Enabled: true # Opt-in + +Layout/FirstMethodParameterLineBreak: + Enabled: true # Opt-in + +# https://github.com/rubocop-hq/rubocop/issues/5891 +Style/SpecialGlobalVars: + Enabled: false + +Style/GlobalStdStream: + Enabled: false + +Style/WordArray: + EnforcedStyle: brackets + +Style/SymbolArray: + EnforcedStyle: brackets + +Style/DoubleNegation: + Enabled: false + +Style/NumericLiterals: + Enabled: false + +Layout/LineLength: + Enabled: false + Max: 120 + +Style/RegexpLiteral: + Enabled: false + +Style/Lambda: + EnforcedStyle: literal + +Style/IfUnlessModifier: + Enabled: false + +Style/FormatString: + Enabled: false + +Naming/VariableNumber: + Enabled: false + +Naming/MethodParameterName: + Enabled: false + +Style/GuardClause: + Enabled: false + +Lint/AssignmentInCondition: + Enabled: false + +Style/Next: + Enabled: false + +Naming/HeredocDelimiterNaming: + Enabled: false + +Style/Semicolon: + Enabled: false + +Lint/InterpolationCheck: + Enabled: false + +Style/ClassAndModuleChildren: + Enabled: false + +Style/TrivialAccessors: + Enabled: false + +Style/ClassVars: + Enabled: false + +Style/CaseEquality: + Enabled: false + +Lint/EmptyClass: + Enabled: false diff --git a/Gemfile b/Gemfile index c0f80d6f0..846a67753 100644 --- a/Gemfile +++ b/Gemfile @@ -1,3 +1,4 @@ +# frozen_string_literal: true source 'https://rubygems.org' gemspec @@ -9,3 +10,4 @@ gem 'cucumber', "~> 4.0" gem 'cuke_modeler', '~> 3.0' gem 'spinach' gem 'rake' +gem 'rubocop' diff --git a/Gemfile.lock b/Gemfile.lock index e7a340356..6e3443104 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -12,6 +12,7 @@ GEM i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) + ast (2.4.1) builder (3.2.4) bump (0.9.0) colorize (0.8.1) @@ -55,13 +56,18 @@ GEM minitest (5.5.1) multi_test (0.1.2) parallel (1.20.1) + parser (3.0.0.0) + ast (~> 2.4.1) power_assert (1.2.0) protobuf-cucumber (3.10.8) activesupport (>= 3.2) middleware thor thread_safe + rainbow (3.0.0) rake (13.0.1) + regexp_parser (2.0.3) + rexml (3.2.4) rspec (3.9.0) rspec-core (~> 3.9.0) rspec-expectations (~> 3.9.0) @@ -75,6 +81,20 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.9.0) rspec-support (3.9.3) + rubocop (1.8.1) + parallel (~> 1.10) + parser (>= 3.0.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml + rubocop-ast (>= 1.2.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 1.4.0, < 3.0) + rubocop-ast (1.4.0) + parser (>= 2.7.1.5) + rubocop-rake (0.5.1) + rubocop + ruby-progressbar (1.11.0) spinach (0.11.0) colorize gherkin-ruby (>= 0.3.2) @@ -87,6 +107,7 @@ GEM thread_safe (0.3.6) tzinfo (1.2.7) thread_safe (~> 0.1) + unicode-display_width (2.0.0) PLATFORMS ruby @@ -99,6 +120,8 @@ DEPENDENCIES parallel_tests! rake rspec (~> 3.3) + rubocop + rubocop-rake spinach test-unit diff --git a/Rakefile b/Rakefile index be9be2518..8d6df7471 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,15 @@ +# frozen_string_literal: true require 'bundler/setup' require 'bump/tasks' require 'bundler/gem_tasks' -task :default do +task default: [:spec, :rubocop] + +task :spec do sh "rspec spec/" end + +desc "Run rubocop" +task :rubocop do + sh "rubocop --parallel" +end diff --git a/bin/parallel_cucumber b/bin/parallel_cucumber index 5d24aff41..3f04d010b 100755 --- a/bin/parallel_cucumber +++ b/bin/parallel_cucumber @@ -1,7 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # enable local usage from cloned repo -root = File.expand_path("../..", __FILE__) +root = File.expand_path('..', __dir__) $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile") require "parallel_tests" diff --git a/bin/parallel_rspec b/bin/parallel_rspec index d69c8a46a..326ff8660 100755 --- a/bin/parallel_rspec +++ b/bin/parallel_rspec @@ -1,7 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # enable local usage from cloned repo -root = File.expand_path("../..", __FILE__) +root = File.expand_path('..', __dir__) $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile") require "parallel_tests" diff --git a/bin/parallel_spinach b/bin/parallel_spinach index 73b100209..13af0f139 100755 --- a/bin/parallel_spinach +++ b/bin/parallel_spinach @@ -1,7 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # enable local usage from cloned repo -root = File.expand_path("../..", __FILE__) +root = File.expand_path('..', __dir__) $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile") require "parallel_tests" diff --git a/bin/parallel_test b/bin/parallel_test index 78c167d87..4730bdd27 100755 --- a/bin/parallel_test +++ b/bin/parallel_test @@ -1,7 +1,8 @@ #!/usr/bin/env ruby +# frozen_string_literal: true # enable local usage from cloned repo -root = File.expand_path("../..", __FILE__) +root = File.expand_path('..', __dir__) $LOAD_PATH << "#{root}/lib" if File.exist?("#{root}/Gemfile") require "parallel_tests" diff --git a/lib/parallel_tests.rb b/lib/parallel_tests.rb index 6cbe9cddb..997076e9e 100644 --- a/lib/parallel_tests.rb +++ b/lib/parallel_tests.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "parallel" require "parallel_tests/railtie" if defined? Rails::Railtie require "rbconfig" @@ -17,7 +18,7 @@ def determine_number_of_processes(count) count, ENV["PARALLEL_TEST_PROCESSORS"], Parallel.processor_count - ].detect{|c| not c.to_s.strip.empty? }.to_i + ].detect { |c| !c.to_s.strip.empty? }.to_i end def with_pid_file @@ -57,7 +58,8 @@ def bundler_enabled? until !File.directory?(current) || current == previous filename = File.join(current, "Gemfile") return true if File.exist?(filename) - current, previous = File.expand_path("..", current), current + previous = current + current = File.expand_path("..", current) end false diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 2646b103b..43dd3f71b 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'optparse' require 'tempfile' require 'parallel_tests' @@ -14,7 +15,7 @@ def run(argv) ENV['DISABLE_SPRING'] ||= '1' num_processes = ParallelTests.determine_number_of_processes(options[:count]) - num_processes = num_processes * (options[:multiply] || 1) + num_processes *= (options[:multiply] || 1) options[:first_is_1] ||= first_is_1? @@ -56,12 +57,12 @@ def execute_in_parallel(items, num_processes, options) def run_tests_in_parallel(num_processes, options) test_results = nil - run_tests_proc = -> { + run_tests_proc = -> do groups = @runner.tests_in_groups(options[:files], num_processes, options) - groups.reject! &:empty? + groups.reject!(&:empty?) test_results = if options[:only_group] - groups_to_run = options[:only_group].collect{|i| groups[i - 1]}.compact + groups_to_run = options[:only_group].map { |i| groups[i - 1] }.compact report_number_of_tests(groups_to_run) unless options[:quiet] execute_in_parallel(groups_to_run, groups_to_run.size, options) do |group| run_tests(group, groups_to_run.index(group), 1, options) @@ -75,7 +76,7 @@ def run_tests_in_parallel(num_processes, options) end report_results(test_results, options) unless options[:quiet] - } + end if options[:quiet] run_tests_proc.call @@ -88,7 +89,7 @@ def run_tests_in_parallel(num_processes, options) def run_tests(group, process_number, num_processes, options) if group.empty? - {:stdout => '', :exit_status => 0, :command => '', :seed => nil} + { stdout: '', exit_status: 0, command: '', seed: nil } else @runner.run_tests(group, process_number, num_processes, options) end @@ -115,7 +116,7 @@ def lock(lockfile) end def report_results(test_results, options) - results = @runner.find_results(test_results.map { |result| result[:stdout] }*"") + results = @runner.find_results(test_results.map { |result| result[:stdout] } * "") puts "" puts @runner.summarize_results(results) @@ -140,7 +141,7 @@ def report_failure_rerun_commmand(test_results, options) def report_number_of_tests(groups) name = @runner.test_file_name num_processes = groups.size - num_tests = groups.map(&:size).inject(0, :+) + num_tests = groups.map(&:size).sum tests_per_process = (num_processes == 0 ? 0 : num_tests / num_processes) puts "#{pluralize(num_processes, 'process')} for #{pluralize(num_tests, name)}, ~ #{pluralize(tests_per_process, name)} per process" end @@ -155,7 +156,7 @@ def pluralize(n, singular) end end - #exit with correct status code so rake parallel:test && echo 123 works + # exit with correct status code so rake parallel:test && echo 123 works def any_test_failed?(test_results) test_results.any? { |result| result[:exit_status] != 0 } end @@ -163,7 +164,7 @@ def any_test_failed?(test_results) def parse_options!(argv) options = {} OptionParser.new do |opts| - opts.banner = <<-BANNER.gsub(/^ /, '') + opts.banner = <<~BANNER Run all tests in parallel, giving each process ENV['TEST_ENV_NUMBER'] ('', '2', '3', ...) [optional] Only selected files & folders: @@ -177,36 +178,35 @@ def parse_options!(argv) opts.on("-n [PROCESSES]", Integer, "How many processes to use, default: available CPUs") { |n| options[:count] = n } opts.on("-p", "--pattern [PATTERN]", "run tests matching this regex pattern") { |pattern| options[:pattern] = /#{pattern}/ } opts.on("--exclude-pattern", "--exclude-pattern [PATTERN]", "exclude tests matching this regex pattern") { |pattern| options[:exclude_pattern] = /#{pattern}/ } - opts.on("--group-by [TYPE]", <<-TEXT.gsub(/^ /, '') - group tests by: - found - order of finding files - steps - number of cucumber/spinach steps - scenarios - individual cucumber scenarios - filesize - by size of the file - runtime - info from runtime log - default - runtime when runtime log is filled otherwise filesize + opts.on( + "--group-by [TYPE]", + <<~TEXT + group tests by: + found - order of finding files + steps - number of cucumber/spinach steps + scenarios - individual cucumber scenarios + filesize - by size of the file + runtime - info from runtime log + default - runtime when runtime log is filled otherwise filesize TEXT - ) { |type| options[:group_by] = type.to_sym } - opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") { |multiply| options[:multiply] = multiply } - - opts.on("-s [PATTERN]", "--single [PATTERN]", - "Run all matching files in the same process") do |pattern| - - options[:single_process] ||= [] - options[:single_process] << /#{pattern}/ + ) { |type| options[:group_by] = type.to_sym } + opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") do |multiply| + options[:multiply] = multiply end - opts.on("-i", "--isolate", - "Do not run any other tests in the group used by --single(-s)") do |pattern| + opts.on("-s [PATTERN]", "--single [PATTERN]", "Run all matching files in the same process") do |pattern| + (options[:single_process] ||= []) << /#{pattern}/ + end + opts.on("-i", "--isolate", "Do not run any other tests in the group used by --single(-s)") do options[:isolate] = true end - opts.on("--isolate-n [PROCESSES]", + opts.on( + "--isolate-n [PROCESSES]", Integer, - "Use 'isolate' singles with number of processes, default: 1.") do |n| - options[:isolate_count] = n - end + "Use 'isolate' singles with number of processes, default: 1." + ) { |n| options[:isolate_count] = n } opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } @@ -220,18 +220,20 @@ def parse_options!(argv) abort end end - opts.on("--suffix [PATTERN]", <<-TEXT.gsub(/^ /, '') - override built in test file pattern (should match suffix): - '_spec\.rb$' - matches rspec files - '_(test|spec).rb$' - matches test or spec files + opts.on( + "--suffix [PATTERN]", + <<~TEXT + override built in test file pattern (should match suffix): + '_spec\.rb$' - matches rspec files + '_(test|spec).rb$' - matches test or spec files TEXT - ) { |pattern| options[:suffix] = /#{pattern}/ } + ) { |pattern| options[:suffix] = /#{pattern}/ } opts.on("--serialize-stdout", "Serialize stdout output, nothing will be written until everything is done") { options[:serialize_stdout] = true } opts.on("--prefix-output-with-test-env-number", "Prefixes test env number to the output when not using --serialize-stdout") { options[:prefix_output_with_test_env_number] = true } opts.on("--combine-stderr", "Combine stderr into stdout, useful in conjunction with --serialize-stdout") { options[:combine_stderr] = true } opts.on("--non-parallel", "execute same commands but do not in parallel, needs --exec") { options[:non_parallel] = true } opts.on("--no-symlinks", "Do not traverse symbolic links to find test files") { options[:symlinks] = false } - opts.on('--ignore-tags [PATTERN]', 'When counting steps ignore scenarios with tags that match this pattern') { |arg| options[:ignore_tag_pattern] = arg } + opts.on('--ignore-tags [PATTERN]', 'When counting steps ignore scenarios with tags that match this pattern') { |arg| options[:ignore_tag_pattern] = arg } opts.on("--nice", "execute test commands with low priority.") { options[:nice] = true } opts.on("--runtime-log [PATH]", "Location of previously recorded test runtimes") { |path| options[:runtime_log] = path } opts.on("--allowed-missing [INT]", Integer, "Allowed percentage of missing runtimes (default = 50)") { |percent| options[:allowed_missing_percent] = percent } @@ -242,13 +244,17 @@ def parse_options!(argv) opts.on("--verbose-process-command", "Displays only the command that will be executed by each process") { options[:verbose_process_command] = true } opts.on("--verbose-rerun-command", "When there are failures, displays the command executed by each process that failed") { options[:verbose_rerun_command] = true } opts.on("--quiet", "Print only tests output") { options[:quiet] = true } - opts.on("-v", "--version", "Show Version") { puts ParallelTests::VERSION; exit } - opts.on("-h", "--help", "Show this.") { puts opts; exit } + opts.on("-v", "--version", "Show Version") do + puts ParallelTests::VERSION + exit 0 + end + opts.on("-h", "--help", "Show this.") do + puts opts + exit 0 + end end.parse!(argv) - if options[:verbose] && options[:quiet] - raise "Both options are mutually exclusive: verbose & quiet" - end + raise "Both options are mutually exclusive: verbose & quiet" if options[:verbose] && options[:quiet] if options[:count] == 0 options.delete(:count) @@ -265,7 +271,9 @@ def parse_options!(argv) options[:group_by] ||= :filesize if options[:only_group] - raise "--group-by found and --single-process are not supported" if options[:group_by] == :found and options[:single_process] + if options[:group_by] == :found && options[:single_process] + raise "--group-by found and --single-process are not supported" + end allowed = [:filesize, :runtime, :found] if !allowed.include?(options[:group_by]) && options[:only_group] raise "--group-by #{allowed.join(" or ")} is required for --only-group" @@ -282,7 +290,7 @@ def extract_file_paths(argv) def extract_test_options(argv) dash_index = argv.index("--") || -1 - argv[dash_index+1..-1] + argv[dash_index + 1..-1] end def append_test_options(options, argv) @@ -302,7 +310,7 @@ def load_runner(type) def execute_shell_command_in_parallel(command, num_processes, options) runs = if options[:only_group] - options[:only_group].map{|g| g - 1} + options[:only_group].map { |g| g - 1 } else (0...num_processes).to_a end @@ -321,13 +329,13 @@ def execute_shell_command_in_parallel(command, num_processes, options) abort if results.any? { |r| r[:exit_status] != 0 } end - def report_time_taken - seconds = ParallelTests.delta { yield }.to_i + def report_time_taken(&block) + seconds = ParallelTests.delta(&block).to_i puts "\nTook #{seconds} seconds#{detailed_duration(seconds)}" end def detailed_duration(seconds) - parts = [ seconds / 3600, seconds % 3600 / 60, seconds % 60 ].drop_while(&:zero?) + parts = [seconds / 3600, seconds % 3600 / 60, seconds % 60].drop_while(&:zero?) return if parts.size < 2 parts = parts.map { |i| "%02d" % i }.join(':').sub(/^0/, '') " (#{parts})" diff --git a/lib/parallel_tests/cucumber/failures_logger.rb b/lib/parallel_tests/cucumber/failures_logger.rb index efbbc5abd..911ed1d49 100644 --- a/lib/parallel_tests/cucumber/failures_logger.rb +++ b/lib/parallel_tests/cucumber/failures_logger.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'cucumber/formatter/rerun' require 'parallel_tests/gherkin/io' @@ -21,7 +22,6 @@ def done end end end - end end end diff --git a/lib/parallel_tests/cucumber/features_with_steps.rb b/lib/parallel_tests/cucumber/features_with_steps.rb index 6ef359df3..bb3725209 100644 --- a/lib/parallel_tests/cucumber/features_with_steps.rb +++ b/lib/parallel_tests/cucumber/features_with_steps.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true begin gem "cuke_modeler", "~> 3.0" require 'cuke_modeler' @@ -12,7 +13,7 @@ class << self def all(tests, options) ignore_tag_pattern = options[:ignore_tag_pattern].nil? ? nil : Regexp.compile(options[:ignore_tag_pattern]) # format of hash will be FILENAME => NUM_STEPS - steps_per_file = tests.each_with_object({}) do |file,steps| + steps_per_file = tests.each_with_object({}) do |file, steps| feature = ::CukeModeler::FeatureFile.new(file).feature # skip feature if it matches tag regex @@ -20,8 +21,8 @@ def all(tests, options) # count the number of steps in the file # will only include a feature if the regex does not match - all_steps = feature.scenarios.map{|a| a.steps.count if a.tags.grep(ignore_tag_pattern).empty? }.compact - steps[file] = all_steps.inject(0,:+) + all_steps = feature.scenarios.map { |a| a.steps.count if a.tags.grep(ignore_tag_pattern).empty? }.compact + steps[file] = all_steps.sum end steps_per_file.sort_by { |_, value| -value } end diff --git a/lib/parallel_tests/cucumber/runner.rb b/lib/parallel_tests/cucumber/runner.rb index 917a0951e..b47e548da 100644 --- a/lib/parallel_tests/cucumber/runner.rb +++ b/lib/parallel_tests/cucumber/runner.rb @@ -1,10 +1,11 @@ +# frozen_string_literal: true require "parallel_tests/gherkin/runner" module ParallelTests module Cucumber class Runner < ParallelTests::Gherkin::Runner - SCENARIOS_RESULTS_BOUNDARY_REGEX = /^(Failing|Flaky) Scenarios:$/ - SCENARIO_REGEX = /^cucumber features\/.+:\d+/ + SCENARIOS_RESULTS_BOUNDARY_REGEX = /^(Failing|Flaky) Scenarios:$/.freeze + SCENARIO_REGEX = %r{^cucumber features/.+:\d+}.freeze class << self def name @@ -21,9 +22,7 @@ def summarize_results(results) scenario_groups = results.slice_before(SCENARIOS_RESULTS_BOUNDARY_REGEX).group_by(&:first) scenario_groups.each do |header, group| scenarios = group.flatten.grep(SCENARIO_REGEX) - if scenarios.any? - output << ([header] + scenarios).join("\n") - end + output << ([header] + scenarios).join("\n") if scenarios.any? end output << super diff --git a/lib/parallel_tests/cucumber/scenario_line_logger.rb b/lib/parallel_tests/cucumber/scenario_line_logger.rb index 6ac24ce80..74a99b52a 100644 --- a/lib/parallel_tests/cucumber/scenario_line_logger.rb +++ b/lib/parallel_tests/cucumber/scenario_line_logger.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ParallelTests module Cucumber module Formatters @@ -10,7 +11,7 @@ def initialize(tag_expression = nil) end def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) - scenario_tags = feature_element.tags.map { |tag| tag.name } + scenario_tags = feature_element.tags.map(&:name) scenario_tags = feature_tags + scenario_tags if feature_element.is_a?(CukeModeler::Scenario) # :Scenario test_line = feature_element.source_line @@ -36,8 +37,7 @@ def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) end end - def method_missing(*args) - end + def method_missing(*); end # # rubocop:disable Style/MissingRespondToMissing private diff --git a/lib/parallel_tests/cucumber/scenarios.rb b/lib/parallel_tests/cucumber/scenarios.rb index b7778f0d2..0b2574825 100644 --- a/lib/parallel_tests/cucumber/scenarios.rb +++ b/lib/parallel_tests/cucumber/scenarios.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'cucumber/tag_expressions/parser' require 'cucumber/runtime' require 'cucumber' @@ -16,11 +17,11 @@ module ParallelTests module Cucumber class Scenarios class << self - def all(files, options={}) + def all(files, options = {}) # Parse tag expression from given test options and ignore tag pattern. Refer here to understand how new tag expression syntax works - https://github.com/cucumber/cucumber/tree/master/tag-expressions tags = [] words = options[:test_options].to_s.shellsplit - words.each_with_index { |w,i| tags << words[i+1] if ["-t", "--tags"].include?(w) } + words.each_with_index { |w, i| tags << words[i + 1] if ["-t", "--tags"].include?(w) } if ignore = options[:ignore_tag_pattern] tags << "not (#{ignore})" end @@ -31,8 +32,7 @@ def all(files, options={}) private - def split_into_scenarios(files, tags='') - + def split_into_scenarios(files, tags = '') # Create the tag expression instance from cucumber tag expressions parser, this is needed to know if the scenario matches with the tags invoked by the request # Create the ScenarioLineLogger which will filter the scenario we want args = [] @@ -40,7 +40,7 @@ def split_into_scenarios(files, tags='') scenario_line_logger = ParallelTests::Cucumber::Formatters::ScenarioLineLogger.new(*args) # here we loop on the files map, each file will contain one or more scenario - features ||= files.map do |path| + files.each do |path| # Gather up any line numbers attached to the file path path, *test_lines = path.split(/:(?=\d+)/) test_lines.map!(&:to_i) diff --git a/lib/parallel_tests/gherkin/io.rb b/lib/parallel_tests/gherkin/io.rb index e1b59cfe5..a60f8202d 100644 --- a/lib/parallel_tests/gherkin/io.rb +++ b/lib/parallel_tests/gherkin/io.rb @@ -1,9 +1,9 @@ +# frozen_string_literal: true require 'parallel_tests' module ParallelTests module Gherkin module Io - def prepare_io(path_or_io) if path_or_io.respond_to?(:write) path_or_io @@ -24,7 +24,7 @@ def prepare_io(path_or_io) # do not let multiple processes get in each others way def lock_output - if File === @io + if @io.is_a?(File) begin @io.flock File::LOCK_EX yield @@ -35,7 +35,6 @@ def lock_output yield end end - end end end diff --git a/lib/parallel_tests/gherkin/listener.rb b/lib/parallel_tests/gherkin/listener.rb index f5a60aaa1..6a11985b3 100644 --- a/lib/parallel_tests/gherkin/listener.rb +++ b/lib/parallel_tests/gherkin/listener.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ParallelTests module Gherkin class Listener @@ -6,7 +7,8 @@ class Listener attr_writer :ignore_tag_pattern def initialize - @steps, @uris = [], [] + @steps = [] + @uris = [] @collect = {} @feature, @ignore_tag_pattern = nil reset_counters! @@ -16,7 +18,7 @@ def feature(feature) @feature = feature end - def background(*args) + def background(*) @background = 1 end @@ -31,7 +33,7 @@ def scenario_outline(outline) @outline = 1 end - def step(*args) + def step(*) return if @ignoring if @background == 1 @background_steps += 1 @@ -51,12 +53,10 @@ def uri(path) # @param [Gherkin::Formatter::Model::Examples] examples # def examples(examples) - if examples.rows.size > 0 - @collect[@uri] += (@outline_steps * examples.rows.size) - end + @collect[@uri] += (@outline_steps * examples.rows.size) unless examples.rows.empty? end - def eof(*args) + def eof(*) @collect[@uri] += (@background_steps * @scenarios) reset_counters! end @@ -67,8 +67,7 @@ def reset_counters! end # ignore lots of other possible callbacks ... - def method_missing(*args) - end + def method_missing(*); end # rubocop:disable Style/MissingRespondToMissing private @@ -79,7 +78,7 @@ def all_tags(scenario) # Set @ignoring if we should ignore this scenario/outline based on its tags def should_ignore(scenario) - @ignoring = @ignore_tag_pattern && all_tags(scenario).find{ |tag| @ignore_tag_pattern === tag.name } + @ignoring = @ignore_tag_pattern && all_tags(scenario).find { |tag| @ignore_tag_pattern === tag.name } end end end diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index 3429511fe..408e04e60 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -1,23 +1,25 @@ +# frozen_string_literal: true require "parallel_tests/test/runner" require 'shellwords' module ParallelTests module Gherkin class Runner < ParallelTests::Test::Runner - class << self def run_tests(test_files, process_number, num_processes, options) combined_scenarios = test_files if options[:group_by] == :scenarios grouped = test_files.map { |t| t.split(':') }.group_by(&:first) - combined_scenarios = grouped.map {|file,files_and_lines| "#{file}:#{files_and_lines.map(&:last).join(':')}" } + combined_scenarios = grouped.map do |file, files_and_lines| + "#{file}:#{files_and_lines.map(&:last).join(':')}" + end end sanitized_test_files = combined_scenarios.map { |val| WINDOWS ? "\"#{val}\"" : Shellwords.escape(val) } options[:env] ||= {} - options[:env] = options[:env].merge({'AUTOTEST' => '1'}) if $stdout.tty? # display color when we are in a terminal + options[:env] = options[:env].merge({ 'AUTOTEST' => '1' }) if $stdout.tty? cmd = [ executable, @@ -44,16 +46,16 @@ def line_is_result?(line) # 1 scenario (1 failed) # 1 step (1 failed) def summarize_results(results) - sort_order = %w[scenario step failed flaky undefined skipped pending passed] + sort_order = ['scenario', 'step', 'failed', 'flaky', 'undefined', 'skipped', 'pending', 'passed'] - %w[scenario step].map do |group| + ['scenario', 'step'].map do |group| group_results = results.grep(/^\d+ #{group}/) next if group_results.empty? sums = sum_up_results(group_results) sums = sums.sort_by { |word, _| sort_order.index(word) || 999 } sums.map! do |word, number| - plural = "s" if word == group and number != 1 + plural = "s" if (word == group) && (number != 1) "#{number} #{word}#{plural}" end "#{sums[0]} (#{sums[1..-1].join(", ")})" @@ -61,7 +63,7 @@ def summarize_results(results) end def cucumber_opts(given) - if given =~ /--profile/ or given =~ /(^|\s)-p / + if given =~ (/--profile/) || given =~ (/(^|\s)-p /) given else [given, profile_from_config].compact.join(" ") @@ -71,15 +73,11 @@ def cucumber_opts(given) def profile_from_config # copied from https://github.com/cucumber/cucumber/blob/master/lib/cucumber/cli/profile_loader.rb#L85 config = Dir.glob("{,.config/,config/}#{name}{.yml,.yaml}").first - if config && File.read(config) =~ /^parallel:/ - "--profile parallel" - end + "--profile parallel" if config && File.read(config) =~ /^parallel:/ end - def tests_in_groups(tests, num_groups, options={}) - if options[:group_by] == :scenarios - @test_file_name = "scenario" - end + def tests_in_groups(tests, num_groups, options = {}) + @test_file_name = "scenario" if options[:group_by] == :scenarios method = "by_#{options[:group_by]}" if Grouper.respond_to?(method) Grouper.send(method, find_tests(tests, options), num_groups, options) @@ -88,7 +86,6 @@ def tests_in_groups(tests, num_groups, options={}) end end - def runtime_logging "--format ParallelTests::Gherkin::RuntimeLogger --out #{runtime_log}" end @@ -98,18 +95,16 @@ def runtime_log end def determine_executable - case - when File.exist?("bin/#{name}") + if File.exist?("bin/#{name}") ParallelTests.with_ruby_binary("bin/#{name}") - when ParallelTests.bundler_enabled? + elsif ParallelTests.bundler_enabled? "bundle exec #{name}" - when File.file?("script/#{name}") + elsif File.file?("script/#{name}") ParallelTests.with_ruby_binary("script/#{name}") else - "#{name}" + name.to_s end end - end end end diff --git a/lib/parallel_tests/gherkin/runtime_logger.rb b/lib/parallel_tests/gherkin/runtime_logger.rb index b1b0d4ce2..d8a7d2894 100644 --- a/lib/parallel_tests/gherkin/runtime_logger.rb +++ b/lib/parallel_tests/gherkin/runtime_logger.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'parallel_tests/gherkin/io' module ParallelTests @@ -19,7 +20,7 @@ def initialize(config) config.on_event :test_run_finished do |_| lock_output do - @io.puts @example_times.map { |file, time| "#{file}:#{time}" } + @io.puts(@example_times.map { |file, time| "#{file}:#{time}" }) end end end diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index de0d1babc..ab6706c2b 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ParallelTests class Grouper class << self @@ -6,13 +7,13 @@ def by_steps(tests, num_groups, options) in_even_groups_by_size(features_with_steps, num_groups) end - def by_scenarios(tests, num_groups, options={}) + def by_scenarios(tests, num_groups, options = {}) scenarios = group_by_scenarios(tests, options) in_even_groups_by_size(scenarios, num_groups) end - def in_even_groups_by_size(items, num_groups, options= {}) - groups = Array.new(num_groups) { {:items => [], :size => 0} } + def in_even_groups_by_size(items, num_groups, options = {}) + groups = Array.new(num_groups) { { items: [], size: 0 } } # add all files that should run in a single process to one group single_process_patterns = options[:single_process] || [] @@ -56,7 +57,7 @@ def isolate_count(options) end def largest_first(files) - files.sort_by{|_item, size| size }.reverse + files.sort_by { |_item, size| size }.reverse end def smallest_group(groups) @@ -73,7 +74,7 @@ def group_by_features_with_steps(tests, options) ParallelTests::Cucumber::FeaturesWithSteps.all(tests, options) end - def group_by_scenarios(tests, options={}) + def group_by_scenarios(tests, options = {}) require 'parallel_tests/cucumber/scenarios' ParallelTests::Cucumber::Scenarios.all(tests, options) end diff --git a/lib/parallel_tests/pids.rb b/lib/parallel_tests/pids.rb index eb6b4c43a..45834cbc1 100644 --- a/lib/parallel_tests/pids.rb +++ b/lib/parallel_tests/pids.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'json' module ParallelTests @@ -52,8 +53,8 @@ def save sync { IO.write(file_path, pids.to_json) } end - def sync - mutex.synchronize { yield } + def sync(&block) + mutex.synchronize(&block) end end end diff --git a/lib/parallel_tests/railtie.rb b/lib/parallel_tests/railtie.rb index 1b1b9e103..c0c798714 100644 --- a/lib/parallel_tests/railtie.rb +++ b/lib/parallel_tests/railtie.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # rake tasks for Rails 3+ module ParallelTests class Railtie < ::Rails::Railtie diff --git a/lib/parallel_tests/rspec/failures_logger.rb b/lib/parallel_tests/rspec/failures_logger.rb index d3752245f..7047d43db 100644 --- a/lib/parallel_tests/rspec/failures_logger.rb +++ b/lib/parallel_tests/rspec/failures_logger.rb @@ -1,10 +1,10 @@ +# frozen_string_literal: true require 'parallel_tests/rspec/logger_base' require 'parallel_tests/rspec/runner' class ParallelTests::RSpec::FailuresLogger < ParallelTests::RSpec::LoggerBase if RSPEC_2 - def dump_failures(*args) - end + def dump_failures(*args); end else RSpec::Core::Formatters.register self, :dump_summary end diff --git a/lib/parallel_tests/rspec/logger_base.rb b/lib/parallel_tests/rspec/logger_base.rb index 768208487..ab1356bb8 100644 --- a/lib/parallel_tests/rspec/logger_base.rb +++ b/lib/parallel_tests/rspec/logger_base.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ParallelTests module RSpec end @@ -13,26 +14,27 @@ def initialize(*args) @output ||= args[0] - if String === @output # a path ? + case @output + when String # a path ? FileUtils.mkdir_p(File.dirname(@output)) - File.open(@output, 'w'){} # overwrite previous results + File.open(@output, 'w') {} # overwrite previous results @output = File.open(@output, 'a') - elsif File === @output # close and restart in append mode + when File # close and restart in append mode @output.close @output = File.open(@output.path, 'a') end end - #stolen from Rspec - def close(*args) - @output.close if (IO === @output) & (@output != $stdout) + # stolen from Rspec + def close(*) + @output.close if (IO === @output) & (@output != $stdout) end protected # do not let multiple processes get in each others way def lock_output - if File === @output + if @output.is_a?(File) begin @output.flock File::LOCK_EX yield diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index 1f66b2f28..794cd063a 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "parallel_tests/test/runner" module ParallelTests @@ -12,10 +13,9 @@ def run_tests(test_files, process_number, num_processes, options) end def determine_executable - case - when File.exist?("bin/rspec") + if File.exist?("bin/rspec") ParallelTests.with_ruby_binary("bin/rspec") - when ParallelTests.bundler_enabled? + elsif ParallelTests.bundler_enabled? "bundle exec rspec" else "rspec" @@ -23,7 +23,7 @@ def determine_executable end def runtime_log - 'tmp/parallel_runtime_rspec.log' + "tmp/parallel_runtime_rspec.log" end def test_file_name @@ -55,9 +55,9 @@ def summarize_results(results) return text unless $stdout.tty? sums = sum_up_results(results) color = - if sums['failure'].positive? + if sums['failure'] > 0 31 # red - elsif sums['pending'].positive? + elsif sums['pending'] > 0 33 # yellow else 32 # green @@ -77,7 +77,7 @@ def color end def spec_opts - options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect{|f| File.file?(f) } + options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect { |f| File.file?(f) } return unless options_file "-O #{options_file}" end diff --git a/lib/parallel_tests/rspec/runtime_logger.rb b/lib/parallel_tests/rspec/runtime_logger.rb index d09f74b09..14f9b883b 100644 --- a/lib/parallel_tests/rspec/runtime_logger.rb +++ b/lib/parallel_tests/rspec/runtime_logger.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'parallel_tests' require 'parallel_tests/rspec/logger_base' @@ -8,9 +9,7 @@ def initialize(*args) @group_nesting = 0 end - unless RSPEC_2 - RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump - end + RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump unless RSPEC_2 def example_group_started(example_group) @time = ParallelTests.now if @group_nesting == 0 @@ -27,16 +26,19 @@ def example_group_finished(notification) super if defined?(super) end - def dump_summary(*args);end - def dump_failures(*args);end - def dump_failure(*args);end - def dump_pending(*args);end + def dump_summary(*); end + + def dump_failures(*); end + + def dump_failure(*); end + + def dump_pending(*); end - def start_dump(*args) - return unless ENV['TEST_ENV_NUMBER'] #only record when running in parallel + def start_dump(*) + return unless ENV['TEST_ENV_NUMBER'] # only record when running in parallel lock_output do @example_times.each do |file, time| - relative_path = file.sub(/^#{Regexp.escape Dir.pwd}\//,'').sub(/^\.\//, "") + relative_path = file.sub(%r{^#{Regexp.escape Dir.pwd}/}, '').sub(%r{^\./}, "") @output.puts "#{relative_path}:#{time > 0 ? time : 0}" end end diff --git a/lib/parallel_tests/rspec/summary_logger.rb b/lib/parallel_tests/rspec/summary_logger.rb index fa3b73ac3..339a60134 100644 --- a/lib/parallel_tests/rspec/summary_logger.rb +++ b/lib/parallel_tests/rspec/summary_logger.rb @@ -1,9 +1,8 @@ +# frozen_string_literal: true require 'parallel_tests/rspec/failures_logger' class ParallelTests::RSpec::SummaryLogger < ParallelTests::RSpec::LoggerBase - unless RSPEC_2 - RSpec::Core::Formatters.register self, :dump_failures - end + RSpec::Core::Formatters.register self, :dump_failures unless RSPEC_2 def dump_failures(*args) lock_output { super } diff --git a/lib/parallel_tests/spinach/runner.rb b/lib/parallel_tests/spinach/runner.rb index 09caa7cda..b57eeb4c9 100644 --- a/lib/parallel_tests/spinach/runner.rb +++ b/lib/parallel_tests/spinach/runner.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "parallel_tests/gherkin/runner" module ParallelTests @@ -9,10 +10,9 @@ def name end def runtime_logging - #Not Yet Supported + # Not Yet Supported "" end - end end end diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 406fece48..e5b1d86e5 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'rake' require 'shellwords' @@ -27,12 +28,13 @@ def purge_before_load end end - def run_in_parallel(cmd, options={}) + def run_in_parallel(cmd, options = {}) load_lib count = " -n #{options[:count]}" unless options[:count].to_s.empty? # Using the relative path to find the binary allow to run a specific version of it - executable = File.expand_path("../../../bin/parallel_test", __FILE__) - command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} --exec '#{cmd}'#{count}#{' --non-parallel' if options[:non_parallel]}" + executable = File.expand_path('../../bin/parallel_test', __dir__) + non_parallel = (options[:non_parallel] ? ' --non-parallel' : '') + command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} --exec '#{cmd}'#{count}#{non_parallel}" abort unless system(command) end @@ -50,12 +52,12 @@ def run_in_parallel(cmd, options={}) # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0 def suppress_output(command, ignore_regex) activate_pipefail = "set -o pipefail" - remove_ignored_lines = %Q{(grep -v "#{ignore_regex}" || test 1)} + remove_ignored_lines = %{(grep -v "#{ignore_regex}" || test 1)} if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1") # We need to shell escape single quotes (' becomes '"'"') because # run_in_parallel wraps command in single quotes - %Q{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'} + %{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'} else command end @@ -83,7 +85,7 @@ def parse_args(args) # parallel:spec[2,models,options] # parallel:spec[,models,options] count = args.shift if args.first.to_s =~ /^\d*$/ - num_processes = count.to_i unless count.to_s.empty? + num_processes = (count.to_s.empty? ? nil : Integer(count)) pattern = args.shift options = args.shift pass_through = args.shift @@ -96,26 +98,28 @@ def parse_args(args) namespace :parallel do desc "Setup test databases via db:setup --> parallel:setup[num_cpus]" - task :setup, :count do |_,args| + task :setup, :count do |_, args| command = "#{ParallelTests::Tasks.rake_bin} db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}" ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end desc "Create test databases via db:create --> parallel:create[num_cpus]" - task :create, :count do |_,args| + task :create, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + "#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + ) end desc "Drop test databases via db:drop --> parallel:drop[num_cpus]" - task :drop, :count do |_,args| + task :drop, :count do |_, args| ParallelTests::Tasks.run_in_parallel( "#{ParallelTests::Tasks.rake_bin} db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} " \ - "DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args) + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args + ) end desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]" - task(:prepare, [:count]) do |_,args| + task(:prepare, [:count]) do |_, args| ParallelTests::Tasks.check_for_pending_migrations if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format) # fast: dump once, load in parallel @@ -128,7 +132,7 @@ def parse_args(args) Rake::Task["parallel:load_#{type}"].invoke(args[:count]) else # slow: dump and load in in serial - args = args.to_hash.merge(:non_parallel => true) # normal merge returns nil + args = args.to_hash.merge(non_parallel: true) # normal merge returns nil task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{task_name}", args) next @@ -137,20 +141,22 @@ def parse_args(args) # when dumping/resetting takes too long desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]" - task :migrate, :count do |_,args| + task :migrate, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + "#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + ) end desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]" - task :rollback, :count do |_,args| + task :rollback, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + "#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + ) end # just load the schema (good for integration server <-> no development db) desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" - task :load_schema, :count do |_,args| + task :load_schema, :count do |_, args| command = "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ "db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1" ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) @@ -158,28 +164,31 @@ def parse_args(args) # load the structure from the structure.sql file desc "Load structure for test databases via db:structure:load --> parallel:load_structure[num_cpus]" - task :load_structure, :count do |_,args| + task :load_structure, :count do |_, args| ParallelTests::Tasks.run_in_parallel( "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ - "db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args) + "db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args + ) end desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]" - task :seed, :count do |_,args| + task :seed, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args) + "#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + ) end desc "Launch given rake command in parallel" task :rake, :command, :count do |_, args| ParallelTests::Tasks.run_in_parallel( "RAILS_ENV=#{ParallelTests::Tasks.rails_env} #{ParallelTests::Tasks.rake_bin} " \ - "#{args.command}", args) + "#{args.command}", args + ) end ['test', 'spec', 'features', 'features-spinach'].each do |type| desc "Run #{type} in parallel with parallel:#{type}[num_cpus]" - task type, [:count, :pattern, :options, :pass_through] do |t, args| + task type, [:count, :pattern, :options, :pass_through] do |_t, args| ParallelTests::Tasks.check_for_pending_migrations ParallelTests::Tasks.load_lib @@ -188,12 +197,10 @@ def parse_args(args) 'spec' => 'rspec', 'test' => 'test', 'features' => 'cucumber', - 'features-spinach' => 'spinach', + 'features-spinach' => 'spinach' }[type] - if test_framework == 'spinach' - type = 'features' - end + type = 'features' if test_framework == 'spinach' # Using the relative path to find the binary allow to run a specific version of it executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index fac956751..92e1d7628 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'parallel_tests' module ParallelTests @@ -32,7 +33,7 @@ def line_is_result?(line) # --- usually used by other runners # finds all tests and partitions them into groups - def tests_in_groups(tests, num_groups, options={}) + def tests_in_groups(tests, num_groups, options = {}) tests = tests_with_size(tests, options) Grouper.in_even_groups_by_size(tests, num_groups, options) end @@ -46,10 +47,17 @@ def tests_with_size(tests, options) when :filesize sort_by_filesize(tests) when :runtime - sort_by_runtime(tests, runtimes(tests, options), options.merge(allowed_missing: (options[:allowed_missing_percent] || 50) / 100.0)) + sort_by_runtime( + tests, runtimes(tests, options), + options.merge(allowed_missing: (options[:allowed_missing_percent] || 50) / 100.0) + ) when nil # use recorded test runtime if we got enough data - runtimes = runtimes(tests, options) rescue [] + runtimes = begin + runtimes(tests, options) + rescue StandardError + [] + end if runtimes.size * 1.5 > tests.size puts "Using recorded test runtime" sort_by_runtime(tests, runtimes) @@ -67,7 +75,7 @@ def execute_command(cmd, process_number, num_processes, options) env = (options[:env] || {}).merge( "TEST_ENV_NUMBER" => test_env_number(process_number, options).to_s, "PARALLEL_TEST_GROUPS" => num_processes.to_s, - "PARALLEL_PID_FILE" => ParallelTests.pid_file_path, + "PARALLEL_PID_FILE" => ParallelTests.pid_file_path ) cmd = "nice #{cmd}" if options[:nice] cmd = "#{cmd} 2>&1" if options[:combine_stderr] @@ -86,13 +94,11 @@ def execute_command_and_capture_output(env, cmd, options) end ParallelTests.pids.delete(pid) if pid exitstatus = $?.exitstatus - seed = output[/seed (\d+)/,1] + seed = output[/seed (\d+)/, 1] - if report_process_command?(options) && options[:serialize_stdout] - output = [cmd, output].join("\n") - end + output = [cmd, output].join("\n") if report_process_command?(options) && options[:serialize_stdout] - {:stdout => output, :exit_status => exitstatus, :command => cmd, :seed => seed} + { stdout: output, exit_status: exitstatus, command: cmd, seed: seed } end def find_results(test_output) @@ -104,7 +110,7 @@ def find_results(test_output) end.compact end - def test_env_number(process_number, options={}) + def test_env_number(process_number, options = {}) if process_number == 0 && !options[:first_is_1] '' else @@ -114,7 +120,7 @@ def test_env_number(process_number, options={}) def summarize_results(results) sums = sum_up_results(results) - sums.sort.map{|word, number| "#{number} #{word}#{'s' if number != 1}" }.join(', ') + sums.sort.map { |word, number| "#{number} #{word}#{'s' if number != 1}" }.join(', ') end # remove old seed and add new seed @@ -134,19 +140,18 @@ def determine_executable end def sum_up_results(results) - results = results.join(' ').gsub(/s\b/,'') # combine and singularize results + results = results.join(' ').gsub(/s\b/, '') # combine and singularize results counts = results.scan(/(\d+) (\w+)/) - counts.inject(Hash.new(0)) do |sum, (number, word)| + counts.each_with_object(Hash.new(0)) do |(number, word), sum| sum[word] += number.to_i - sum end end # read output of the process and print it in chunks - def capture_output(out, env, options={}) - result = "" - loop do - begin + def capture_output(out, env, options = {}) + result = +"" + begin + loop do read = out.readpartial(1000000) # read whatever chunk we can get if Encoding.default_internal read = read.force_encoding(Encoding.default_internal) @@ -159,11 +164,13 @@ def capture_output(out, env, options={}) $stdout.flush end end - end rescue EOFError + rescue EOFError + nil + end result end - def sort_by_runtime(tests, runtimes, options={}) + def sort_by_runtime(tests, runtimes, options = {}) allowed_missing = options[:allowed_missing] || 1.0 allowed_missing = tests.size * allowed_missing @@ -178,9 +185,7 @@ def sort_by_runtime(tests, runtimes, options={}) [test, time] end - if options[:verbose] - puts "Runtime found for #{tests.count(&:last)} of #{tests.size} tests" - end + puts "Runtime found for #{tests.count(&:last)} of #{tests.size} tests" if options[:verbose] set_unknown_runtime tests, options end @@ -190,7 +195,7 @@ def runtimes(tests, options) lines = File.read(log).split("\n") lines.each_with_object({}) do |line, times| test, _, time = line.rpartition(':') - next unless test and time + next unless test && time times[test] = time.to_f if tests.include?(test) end end @@ -217,7 +222,7 @@ def find_tests(tests, options = {}) end.uniq end - def files_in_folder(folder, options={}) + def files_in_folder(folder, options = {}) pattern = if options[:symlinks] == false # not nil or true "**/*" else @@ -225,7 +230,7 @@ def files_in_folder(folder, options={}) # http://stackoverflow.com/questions/357754/can-i-traverse-symlinked-directories-in-ruby-with-a-glob "**{,/*/**}/*" end - Dir[File.join(folder, pattern)].uniq + Dir[File.join(folder, pattern)].uniq.sort end private @@ -236,7 +241,7 @@ def set_unknown_runtime(tests, options) known, unknown = tests.partition(&:last) return if unknown.empty? unknown_runtime = options[:unknown_runtime] || - (known.empty? ? 1 : known.map!(&:last).inject(:+) / known.size) # average + (known.empty? ? 1 : known.map!(&:last).sum / known.size) # average unknown.each { |set| set[1] = unknown_runtime } end diff --git a/lib/parallel_tests/test/runtime_logger.rb b/lib/parallel_tests/test/runtime_logger.rb index 883e6ca38..095208d2f 100644 --- a/lib/parallel_tests/test/runtime_logger.rb +++ b/lib/parallel_tests/test/runtime_logger.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'parallel_tests' require 'parallel_tests/test/runner' @@ -22,7 +23,7 @@ def unique_log separator = "\n" groups = logfile.read.split(separator).map { |line| line.split(":") }.group_by(&:first) lines = groups.map do |file, times| - time = "%.2f" % times.map(&:last).map(&:to_f).inject(:+) + time = "%.2f" % times.map(&:last).map(&:to_f).sum "#{file}:#{time}" end logfile.rewind @@ -34,7 +35,7 @@ def unique_log private def with_locked_log - File.open(logfile, File::RDWR|File::CREAT) do |logfile| + File.open(logfile, File::RDWR | File::CREAT) do |logfile| logfile.flock(File::LOCK_EX) yield logfile end @@ -59,7 +60,7 @@ def log(test, time) end def message(test, delta) - return unless method = test.public_instance_methods(true).detect { |method| method =~ /^test_/ } + return unless method = test.public_instance_methods(true).detect { |m| m =~ /^test_/ } filename = test.instance_method(method).source_location.first.sub("#{Dir.pwd}/", "") "#{filename}:#{delta}" end @@ -74,22 +75,26 @@ def logfile if defined?(Minitest::Runnable) # Minitest 5 class << Minitest::Runnable - prepend(Module.new do - def run(*) - ParallelTests::Test::RuntimeLogger.log_test_run(self) do - super + prepend( + Module.new do + def run(*) + ParallelTests::Test::RuntimeLogger.log_test_run(self) do + super + end end end - end) + ) end class << Minitest - prepend(Module.new do - def run(*args) - result = super - ParallelTests::Test::RuntimeLogger.unique_log - result + prepend( + Module.new do + def run(*args) + result = super + ParallelTests::Test::RuntimeLogger.unique_log + result + end end - end) + ) end end diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 969f9968a..71723fadf 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ParallelTests - VERSION = Version = '3.4.0' + VERSION = '3.4.0' end diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 8bbbd9843..4b329e94f 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -1,3 +1,4 @@ +# frozen_string_literal: true name = "parallel_tests" require_relative "lib/#{name}/version" @@ -7,10 +8,10 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.email = "michael@grosser.it" s.homepage = "https://github.com/grosser/#{name}" s.metadata = { - "bug_tracker_uri" => "https://github.com/grosser/#{name}/issues", + "bug_tracker_uri" => "https://github.com/grosser/#{name}/issues", "documentation_uri" => "https://github.com/grosser/#{name}/blob/v#{s.version}/Readme.md", - "source_code_uri" => "https://github.com/grosser/#{name}/tree/v#{s.version}", - "wiki_uri" => "https://github.com/grosser/#{name}/wiki", + "source_code_uri" => "https://github.com/grosser/#{name}/tree/v#{s.version}", + "wiki_uri" => "https://github.com/grosser/#{name}/wiki" } s.files = Dir["{lib,bin}/**/*"] + ["Readme.md"] s.license = "MIT" diff --git a/spec/fixtures/rails51/Gemfile b/spec/fixtures/rails51/Gemfile index 21ae41534..b55c480eb 100644 --- a/spec/fixtures/rails51/Gemfile +++ b/spec/fixtures/rails51/Gemfile @@ -1,3 +1,4 @@ +# frozen_string_literal: true source 'https://rubygems.org' gem 'rails', '5.1.6' diff --git a/spec/fixtures/rails51/Gemfile.lock b/spec/fixtures/rails51/Gemfile.lock index 8733a076b..fe7ad4b23 100644 --- a/spec/fixtures/rails51/Gemfile.lock +++ b/spec/fixtures/rails51/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.32.0) + parallel_tests (3.4.0) parallel GEM @@ -65,7 +65,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) - parallel (1.19.1) + parallel (1.20.1) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) diff --git a/spec/fixtures/rails51/Rakefile b/spec/fixtures/rails51/Rakefile index e85f91391..84f2bc394 100644 --- a/spec/fixtures/rails51/Rakefile +++ b/spec/fixtures/rails51/Rakefile @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. diff --git a/spec/fixtures/rails51/app/channels/application_cable/channel.rb b/spec/fixtures/rails51/app/channels/application_cable/channel.rb index d67269728..51e3e936b 100644 --- a/spec/fixtures/rails51/app/channels/application_cable/channel.rb +++ b/spec/fixtures/rails51/app/channels/application_cable/channel.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/spec/fixtures/rails51/app/channels/application_cable/connection.rb b/spec/fixtures/rails51/app/channels/application_cable/connection.rb index 0ff5442f4..fa70319da 100644 --- a/spec/fixtures/rails51/app/channels/application_cable/connection.rb +++ b/spec/fixtures/rails51/app/channels/application_cable/connection.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/spec/fixtures/rails51/app/controllers/application_controller.rb b/spec/fixtures/rails51/app/controllers/application_controller.rb index 1c07694e9..6d369f832 100644 --- a/spec/fixtures/rails51/app/controllers/application_controller.rb +++ b/spec/fixtures/rails51/app/controllers/application_controller.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class ApplicationController < ActionController::Base protect_from_forgery with: :exception end diff --git a/spec/fixtures/rails51/app/helpers/application_helper.rb b/spec/fixtures/rails51/app/helpers/application_helper.rb index de6be7945..71249b93b 100644 --- a/spec/fixtures/rails51/app/helpers/application_helper.rb +++ b/spec/fixtures/rails51/app/helpers/application_helper.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true module ApplicationHelper end diff --git a/spec/fixtures/rails51/app/jobs/application_job.rb b/spec/fixtures/rails51/app/jobs/application_job.rb index a009ace51..32fe70b8e 100644 --- a/spec/fixtures/rails51/app/jobs/application_job.rb +++ b/spec/fixtures/rails51/app/jobs/application_job.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true class ApplicationJob < ActiveJob::Base end diff --git a/spec/fixtures/rails51/app/mailers/application_mailer.rb b/spec/fixtures/rails51/app/mailers/application_mailer.rb index 286b2239d..24289009a 100644 --- a/spec/fixtures/rails51/app/mailers/application_mailer.rb +++ b/spec/fixtures/rails51/app/mailers/application_mailer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' diff --git a/spec/fixtures/rails51/app/models/application_record.rb b/spec/fixtures/rails51/app/models/application_record.rb index 10a4cba84..767a072b5 100644 --- a/spec/fixtures/rails51/app/models/application_record.rb +++ b/spec/fixtures/rails51/app/models/application_record.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end diff --git a/spec/fixtures/rails51/app/models/user.rb b/spec/fixtures/rails51/app/models/user.rb index 379658a50..b161db0c3 100644 --- a/spec/fixtures/rails51/app/models/user.rb +++ b/spec/fixtures/rails51/app/models/user.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true class User < ApplicationRecord end diff --git a/spec/fixtures/rails51/bin/bundle b/spec/fixtures/rails51/bin/bundle index 66e9889e8..74a18868b 100755 --- a/spec/fixtures/rails51/bin/bundle +++ b/spec/fixtures/rails51/bin/bundle @@ -1,3 +1,4 @@ #!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__) +# frozen_string_literal: true +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/spec/fixtures/rails51/bin/rails b/spec/fixtures/rails51/bin/rails index 073966023..dd027b406 100755 --- a/spec/fixtures/rails51/bin/rails +++ b/spec/fixtures/rails51/bin/rails @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/spec/fixtures/rails51/bin/rake b/spec/fixtures/rails51/bin/rake index 17240489f..609af7470 100755 --- a/spec/fixtures/rails51/bin/rake +++ b/spec/fixtures/rails51/bin/rake @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/spec/fixtures/rails51/bin/setup b/spec/fixtures/rails51/bin/setup index 78c4e861d..4c1bacf0f 100755 --- a/spec/fixtures/rails51/bin/setup +++ b/spec/fixtures/rails51/bin/setup @@ -1,10 +1,11 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require 'pathname' require 'fileutils' -include FileUtils +include FileUtils # rubocop:disable Style/MixinUsage # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") @@ -21,7 +22,6 @@ chdir APP_ROOT do # Install JavaScript dependencies if using Yarn # system('bin/yarn') - # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') # cp 'config/database.yml.sample', 'config/database.yml' diff --git a/spec/fixtures/rails51/bin/update b/spec/fixtures/rails51/bin/update index a8e4462f2..1594fcbcb 100755 --- a/spec/fixtures/rails51/bin/update +++ b/spec/fixtures/rails51/bin/update @@ -1,10 +1,11 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require 'pathname' require 'fileutils' -include FileUtils +include FileUtils # rubocop:disable Style/MixinUsage # path to your application root. -APP_ROOT = Pathname.new File.expand_path('../../', __FILE__) +APP_ROOT = Pathname.new File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") diff --git a/spec/fixtures/rails51/bin/yarn b/spec/fixtures/rails51/bin/yarn index c2bacef83..0d571d110 100755 --- a/spec/fixtures/rails51/bin/yarn +++ b/spec/fixtures/rails51/bin/yarn @@ -1,11 +1,12 @@ #!/usr/bin/env ruby +# frozen_string_literal: true VENDOR_PATH = File.expand_path('..', __dir__) Dir.chdir(VENDOR_PATH) do begin exec "yarnpkg #{ARGV.join(" ")}" rescue Errno::ENOENT - $stderr.puts "Yarn executable was not detected in the system." - $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + warn "Yarn executable was not detected in the system." + warn "Download Yarn at https://yarnpkg.com/en/docs/install" exit 1 end end diff --git a/spec/fixtures/rails51/config.ru b/spec/fixtures/rails51/config.ru index f7ba0b527..7eae2644f 100644 --- a/spec/fixtures/rails51/config.ru +++ b/spec/fixtures/rails51/config.ru @@ -1,3 +1,4 @@ +# frozen_string_literal: true # This file is used by Rack-based servers to start the application. require_relative 'config/environment' diff --git a/spec/fixtures/rails51/config/application.rb b/spec/fixtures/rails51/config/application.rb index 34adb6653..7cec4d3ec 100644 --- a/spec/fixtures/rails51/config/application.rb +++ b/spec/fixtures/rails51/config/application.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative 'boot' require 'rails/all' diff --git a/spec/fixtures/rails51/config/boot.rb b/spec/fixtures/rails51/config/boot.rb index 30f5120df..9be337a42 100644 --- a/spec/fixtures/rails51/config/boot.rb +++ b/spec/fixtures/rails51/config/boot.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/spec/fixtures/rails51/config/environment.rb b/spec/fixtures/rails51/config/environment.rb index 426333bb4..12ea62f88 100644 --- a/spec/fixtures/rails51/config/environment.rb +++ b/spec/fixtures/rails51/config/environment.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Load the Rails application. require_relative 'application' diff --git a/spec/fixtures/rails51/config/environments/development.rb b/spec/fixtures/rails51/config/environments/development.rb index 55d8c9e7b..8a4e13721 100644 --- a/spec/fixtures/rails51/config/environments/development.rb +++ b/spec/fixtures/rails51/config/environments/development.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/spec/fixtures/rails51/config/environments/production.rb b/spec/fixtures/rails51/config/environments/production.rb index 44d16152f..ff1eda28e 100644 --- a/spec/fixtures/rails51/config/environments/production.rb +++ b/spec/fixtures/rails51/config/environments/production.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -52,7 +53,7 @@ config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store diff --git a/spec/fixtures/rails51/config/environments/test.rb b/spec/fixtures/rails51/config/environments/test.rb index 8e5cbde53..b0c64d7a2 100644 --- a/spec/fixtures/rails51/config/environments/test.rb +++ b/spec/fixtures/rails51/config/environments/test.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/spec/fixtures/rails51/config/initializers/application_controller_renderer.rb b/spec/fixtures/rails51/config/initializers/application_controller_renderer.rb index 89d2efab2..f4556db39 100644 --- a/spec/fixtures/rails51/config/initializers/application_controller_renderer.rb +++ b/spec/fixtures/rails51/config/initializers/application_controller_renderer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/spec/fixtures/rails51/config/initializers/assets.rb b/spec/fixtures/rails51/config/initializers/assets.rb index 4b828e80c..b6970c9e6 100644 --- a/spec/fixtures/rails51/config/initializers/assets.rb +++ b/spec/fixtures/rails51/config/initializers/assets.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. diff --git a/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb b/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb index 59385cdf3..d0f0d3b5d 100644 --- a/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb +++ b/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/spec/fixtures/rails51/config/initializers/cookies_serializer.rb b/spec/fixtures/rails51/config/initializers/cookies_serializer.rb index 5a6a32d37..2a7295959 100644 --- a/spec/fixtures/rails51/config/initializers/cookies_serializer.rb +++ b/spec/fixtures/rails51/config/initializers/cookies_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb b/spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb index 4a994e1e7..b7fe1231f 100644 --- a/spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb +++ b/spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/spec/fixtures/rails51/config/initializers/inflections.rb b/spec/fixtures/rails51/config/initializers/inflections.rb index ac033bf9d..aa7435fbc 100644 --- a/spec/fixtures/rails51/config/initializers/inflections.rb +++ b/spec/fixtures/rails51/config/initializers/inflections.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/spec/fixtures/rails51/config/initializers/mime_types.rb b/spec/fixtures/rails51/config/initializers/mime_types.rb index dc1899682..6e1d16f02 100644 --- a/spec/fixtures/rails51/config/initializers/mime_types.rb +++ b/spec/fixtures/rails51/config/initializers/mime_types.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/spec/fixtures/rails51/config/initializers/wrap_parameters.rb b/spec/fixtures/rails51/config/initializers/wrap_parameters.rb index bbfc3961b..18c382529 100644 --- a/spec/fixtures/rails51/config/initializers/wrap_parameters.rb +++ b/spec/fixtures/rails51/config/initializers/wrap_parameters.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/spec/fixtures/rails51/config/puma.rb b/spec/fixtures/rails51/config/puma.rb index 1e19380dc..3ea935c19 100644 --- a/spec/fixtures/rails51/config/puma.rb +++ b/spec/fixtures/rails51/config/puma.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true # Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers: a minimum and maximum. # Any libraries that use thread pools should be configured to match # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) threads threads_count, threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch("PORT", 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV") { "development" } +environment ENV.fetch("RAILS_ENV", "development") # Specifies the number of `workers` to boot in clustered mode. # Workers are forked webserver processes. If using threads and workers together diff --git a/spec/fixtures/rails51/config/routes.rb b/spec/fixtures/rails51/config/routes.rb index 787824f88..6bf1218e2 100644 --- a/spec/fixtures/rails51/config/routes.rb +++ b/spec/fixtures/rails51/config/routes.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb b/spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb index db0e1e373..2b5b822b5 100644 --- a/spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb +++ b/spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CreateUsers < ActiveRecord::Migration[5.1] def change create_table :users do |t| diff --git a/spec/fixtures/rails51/db/seeds.rb b/spec/fixtures/rails51/db/seeds.rb index 1beea2acc..8744e3c59 100644 --- a/spec/fixtures/rails51/db/seeds.rb +++ b/spec/fixtures/rails51/db/seeds.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). # diff --git a/spec/fixtures/rails51/test/application_system_test_case.rb b/spec/fixtures/rails51/test/application_system_test_case.rb index d19212abd..93fada67a 100644 --- a/spec/fixtures/rails51/test/application_system_test_case.rb +++ b/spec/fixtures/rails51/test/application_system_test_case.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase diff --git a/spec/fixtures/rails51/test/models/user2_test.rb b/spec/fixtures/rails51/test/models/user2_test.rb index 7a61183d6..bcebe28c8 100644 --- a/spec/fixtures/rails51/test/models/user2_test.rb +++ b/spec/fixtures/rails51/test/models/user2_test.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'test_helper' class User2Test < ActiveSupport::TestCase diff --git a/spec/fixtures/rails51/test/models/user_test.rb b/spec/fixtures/rails51/test/models/user_test.rb index 45a5ff8dc..045d9e148 100644 --- a/spec/fixtures/rails51/test/models/user_test.rb +++ b/spec/fixtures/rails51/test/models/user_test.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'test_helper' class UserTest < ActiveSupport::TestCase diff --git a/spec/fixtures/rails51/test/test_helper.rb b/spec/fixtures/rails51/test/test_helper.rb index 92e39b2d7..562b8c129 100644 --- a/spec/fixtures/rails51/test/test_helper.rb +++ b/spec/fixtures/rails51/test/test_helper.rb @@ -1,5 +1,6 @@ +# frozen_string_literal: true ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../../config/environment', __FILE__) +require File.expand_path('../config/environment', __dir__) require 'rails/test_help' class ActiveSupport::TestCase diff --git a/spec/fixtures/rails52/Gemfile b/spec/fixtures/rails52/Gemfile index 1caed7b40..34b52d996 100644 --- a/spec/fixtures/rails52/Gemfile +++ b/spec/fixtures/rails52/Gemfile @@ -1,3 +1,4 @@ +# frozen_string_literal: true source 'https://rubygems.org' gem 'rails', '5.2.1' diff --git a/spec/fixtures/rails52/Gemfile.lock b/spec/fixtures/rails52/Gemfile.lock index 1044f004f..16f228f8a 100644 --- a/spec/fixtures/rails52/Gemfile.lock +++ b/spec/fixtures/rails52/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (2.32.0) + parallel_tests (3.4.0) parallel GEM @@ -72,7 +72,7 @@ GEM nio4r (2.3.1) nokogiri (1.8.5) mini_portile2 (~> 2.3.0) - parallel (1.19.1) + parallel (1.20.1) rack (2.0.5) rack-test (1.1.0) rack (>= 1.0, < 3) diff --git a/spec/fixtures/rails52/Rakefile b/spec/fixtures/rails52/Rakefile index e85f91391..84f2bc394 100644 --- a/spec/fixtures/rails52/Rakefile +++ b/spec/fixtures/rails52/Rakefile @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. diff --git a/spec/fixtures/rails52/app/channels/application_cable/channel.rb b/spec/fixtures/rails52/app/channels/application_cable/channel.rb index d67269728..51e3e936b 100644 --- a/spec/fixtures/rails52/app/channels/application_cable/channel.rb +++ b/spec/fixtures/rails52/app/channels/application_cable/channel.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/spec/fixtures/rails52/app/channels/application_cable/connection.rb b/spec/fixtures/rails52/app/channels/application_cable/connection.rb index 0ff5442f4..fa70319da 100644 --- a/spec/fixtures/rails52/app/channels/application_cable/connection.rb +++ b/spec/fixtures/rails52/app/channels/application_cable/connection.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/spec/fixtures/rails52/app/controllers/application_controller.rb b/spec/fixtures/rails52/app/controllers/application_controller.rb index 09705d12a..e0491348f 100644 --- a/spec/fixtures/rails52/app/controllers/application_controller.rb +++ b/spec/fixtures/rails52/app/controllers/application_controller.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true class ApplicationController < ActionController::Base end diff --git a/spec/fixtures/rails52/app/helpers/application_helper.rb b/spec/fixtures/rails52/app/helpers/application_helper.rb index de6be7945..71249b93b 100644 --- a/spec/fixtures/rails52/app/helpers/application_helper.rb +++ b/spec/fixtures/rails52/app/helpers/application_helper.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true module ApplicationHelper end diff --git a/spec/fixtures/rails52/app/jobs/application_job.rb b/spec/fixtures/rails52/app/jobs/application_job.rb index a009ace51..32fe70b8e 100644 --- a/spec/fixtures/rails52/app/jobs/application_job.rb +++ b/spec/fixtures/rails52/app/jobs/application_job.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true class ApplicationJob < ActiveJob::Base end diff --git a/spec/fixtures/rails52/app/mailers/application_mailer.rb b/spec/fixtures/rails52/app/mailers/application_mailer.rb index 286b2239d..24289009a 100644 --- a/spec/fixtures/rails52/app/mailers/application_mailer.rb +++ b/spec/fixtures/rails52/app/mailers/application_mailer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' diff --git a/spec/fixtures/rails52/app/models/application_record.rb b/spec/fixtures/rails52/app/models/application_record.rb index 10a4cba84..767a072b5 100644 --- a/spec/fixtures/rails52/app/models/application_record.rb +++ b/spec/fixtures/rails52/app/models/application_record.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end diff --git a/spec/fixtures/rails52/app/models/user.rb b/spec/fixtures/rails52/app/models/user.rb index 379658a50..b161db0c3 100644 --- a/spec/fixtures/rails52/app/models/user.rb +++ b/spec/fixtures/rails52/app/models/user.rb @@ -1,2 +1,3 @@ +# frozen_string_literal: true class User < ApplicationRecord end diff --git a/spec/fixtures/rails52/bin/bundle b/spec/fixtures/rails52/bin/bundle index f19acf5b5..74a18868b 100755 --- a/spec/fixtures/rails52/bin/bundle +++ b/spec/fixtures/rails52/bin/bundle @@ -1,3 +1,4 @@ #!/usr/bin/env ruby +# frozen_string_literal: true ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) load Gem.bin_path('bundler', 'bundle') diff --git a/spec/fixtures/rails52/bin/rails b/spec/fixtures/rails52/bin/rails index 073966023..dd027b406 100755 --- a/spec/fixtures/rails52/bin/rails +++ b/spec/fixtures/rails52/bin/rails @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/spec/fixtures/rails52/bin/rake b/spec/fixtures/rails52/bin/rake index 17240489f..609af7470 100755 --- a/spec/fixtures/rails52/bin/rake +++ b/spec/fixtures/rails52/bin/rake @@ -1,4 +1,5 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/spec/fixtures/rails52/bin/setup b/spec/fixtures/rails52/bin/setup index 94fd4d797..e876cef46 100755 --- a/spec/fixtures/rails52/bin/setup +++ b/spec/fixtures/rails52/bin/setup @@ -1,6 +1,7 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require 'fileutils' -include FileUtils +include FileUtils # rubocop:disable Style/MixinUsage # path to your application root. APP_ROOT = File.expand_path('..', __dir__) diff --git a/spec/fixtures/rails52/bin/update b/spec/fixtures/rails52/bin/update index 58bfaed51..4cc53024e 100755 --- a/spec/fixtures/rails52/bin/update +++ b/spec/fixtures/rails52/bin/update @@ -1,6 +1,7 @@ #!/usr/bin/env ruby +# frozen_string_literal: true require 'fileutils' -include FileUtils +include FileUtils # rubocop:disable Style/MixinUsage # path to your application root. APP_ROOT = File.expand_path('..', __dir__) diff --git a/spec/fixtures/rails52/bin/yarn b/spec/fixtures/rails52/bin/yarn index 460dd565b..d5619dbd6 100755 --- a/spec/fixtures/rails52/bin/yarn +++ b/spec/fixtures/rails52/bin/yarn @@ -1,11 +1,12 @@ #!/usr/bin/env ruby +# frozen_string_literal: true APP_ROOT = File.expand_path('..', __dir__) Dir.chdir(APP_ROOT) do begin exec "yarnpkg", *ARGV rescue Errno::ENOENT - $stderr.puts "Yarn executable was not detected in the system." - $stderr.puts "Download Yarn at https://yarnpkg.com/en/docs/install" + warn "Yarn executable was not detected in the system." + warn "Download Yarn at https://yarnpkg.com/en/docs/install" exit 1 end end diff --git a/spec/fixtures/rails52/config.ru b/spec/fixtures/rails52/config.ru index f7ba0b527..7eae2644f 100644 --- a/spec/fixtures/rails52/config.ru +++ b/spec/fixtures/rails52/config.ru @@ -1,3 +1,4 @@ +# frozen_string_literal: true # This file is used by Rack-based servers to start the application. require_relative 'config/environment' diff --git a/spec/fixtures/rails52/config/application.rb b/spec/fixtures/rails52/config/application.rb index b4cdc5aab..5cccc17df 100644 --- a/spec/fixtures/rails52/config/application.rb +++ b/spec/fixtures/rails52/config/application.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require_relative 'boot' require 'rails/all' diff --git a/spec/fixtures/rails52/config/boot.rb b/spec/fixtures/rails52/config/boot.rb index 30f5120df..9be337a42 100644 --- a/spec/fixtures/rails52/config/boot.rb +++ b/spec/fixtures/rails52/config/boot.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/spec/fixtures/rails52/config/environment.rb b/spec/fixtures/rails52/config/environment.rb index 426333bb4..12ea62f88 100644 --- a/spec/fixtures/rails52/config/environment.rb +++ b/spec/fixtures/rails52/config/environment.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Load the Rails application. require_relative 'application' diff --git a/spec/fixtures/rails52/config/environments/development.rb b/spec/fixtures/rails52/config/environments/development.rb index 366e75ad7..a61361fe5 100644 --- a/spec/fixtures/rails52/config/environments/development.rb +++ b/spec/fixtures/rails52/config/environments/development.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/spec/fixtures/rails52/config/environments/production.rb b/spec/fixtures/rails52/config/environments/production.rb index 38b6ae6b8..fb40a27a5 100644 --- a/spec/fixtures/rails52/config/environments/production.rb +++ b/spec/fixtures/rails52/config/environments/production.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -54,7 +55,7 @@ config.log_level = :debug # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] + config.log_tags = [:request_id] # Use a different cache store in production. # config.cache_store = :mem_cache_store diff --git a/spec/fixtures/rails52/config/environments/test.rb b/spec/fixtures/rails52/config/environments/test.rb index 0a38fd3ce..79de6da35 100644 --- a/spec/fixtures/rails52/config/environments/test.rb +++ b/spec/fixtures/rails52/config/environments/test.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/spec/fixtures/rails52/config/initializers/application_controller_renderer.rb b/spec/fixtures/rails52/config/initializers/application_controller_renderer.rb index 89d2efab2..f4556db39 100644 --- a/spec/fixtures/rails52/config/initializers/application_controller_renderer.rb +++ b/spec/fixtures/rails52/config/initializers/application_controller_renderer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/spec/fixtures/rails52/config/initializers/assets.rb b/spec/fixtures/rails52/config/initializers/assets.rb index 4b828e80c..b6970c9e6 100644 --- a/spec/fixtures/rails52/config/initializers/assets.rb +++ b/spec/fixtures/rails52/config/initializers/assets.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Version of your assets, change this if you want to expire all your assets. diff --git a/spec/fixtures/rails52/config/initializers/backtrace_silencers.rb b/spec/fixtures/rails52/config/initializers/backtrace_silencers.rb index 59385cdf3..d0f0d3b5d 100644 --- a/spec/fixtures/rails52/config/initializers/backtrace_silencers.rb +++ b/spec/fixtures/rails52/config/initializers/backtrace_silencers.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/spec/fixtures/rails52/config/initializers/content_security_policy.rb b/spec/fixtures/rails52/config/initializers/content_security_policy.rb index d3bcaa5ec..497f5667c 100644 --- a/spec/fixtures/rails52/config/initializers/content_security_policy.rb +++ b/spec/fixtures/rails52/config/initializers/content_security_policy.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Define an application-wide content security policy diff --git a/spec/fixtures/rails52/config/initializers/cookies_serializer.rb b/spec/fixtures/rails52/config/initializers/cookies_serializer.rb index 5a6a32d37..2a7295959 100644 --- a/spec/fixtures/rails52/config/initializers/cookies_serializer.rb +++ b/spec/fixtures/rails52/config/initializers/cookies_serializer.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb b/spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb index 4a994e1e7..b7fe1231f 100644 --- a/spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb +++ b/spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/spec/fixtures/rails52/config/initializers/inflections.rb b/spec/fixtures/rails52/config/initializers/inflections.rb index ac033bf9d..aa7435fbc 100644 --- a/spec/fixtures/rails52/config/initializers/inflections.rb +++ b/spec/fixtures/rails52/config/initializers/inflections.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/spec/fixtures/rails52/config/initializers/mime_types.rb b/spec/fixtures/rails52/config/initializers/mime_types.rb index dc1899682..6e1d16f02 100644 --- a/spec/fixtures/rails52/config/initializers/mime_types.rb +++ b/spec/fixtures/rails52/config/initializers/mime_types.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/spec/fixtures/rails52/config/initializers/wrap_parameters.rb b/spec/fixtures/rails52/config/initializers/wrap_parameters.rb index bbfc3961b..18c382529 100644 --- a/spec/fixtures/rails52/config/initializers/wrap_parameters.rb +++ b/spec/fixtures/rails52/config/initializers/wrap_parameters.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/spec/fixtures/rails52/config/puma.rb b/spec/fixtures/rails52/config/puma.rb index a5eccf816..d05463a09 100644 --- a/spec/fixtures/rails52/config/puma.rb +++ b/spec/fixtures/rails52/config/puma.rb @@ -1,19 +1,20 @@ +# frozen_string_literal: true # Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers: a minimum and maximum. # Any libraries that use thread pools should be configured to match # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) threads threads_count, threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +port ENV.fetch("PORT", 3000) # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV") { "development" } +environment ENV.fetch("RAILS_ENV", "development") # Specifies the number of `workers` to boot in clustered mode. # Workers are forked webserver processes. If using threads and workers together diff --git a/spec/fixtures/rails52/config/routes.rb b/spec/fixtures/rails52/config/routes.rb index 787824f88..6bf1218e2 100644 --- a/spec/fixtures/rails52/config/routes.rb +++ b/spec/fixtures/rails52/config/routes.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true Rails.application.routes.draw do # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb b/spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb index ad388a546..55b4dfea6 100644 --- a/spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb +++ b/spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true class CreateUsers < ActiveRecord::Migration[5.2] def change create_table :users do |t| diff --git a/spec/fixtures/rails52/db/seeds.rb b/spec/fixtures/rails52/db/seeds.rb index 1beea2acc..8744e3c59 100644 --- a/spec/fixtures/rails52/db/seeds.rb +++ b/spec/fixtures/rails52/db/seeds.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). # diff --git a/spec/fixtures/rails52/test/application_system_test_case.rb b/spec/fixtures/rails52/test/application_system_test_case.rb index d19212abd..93fada67a 100644 --- a/spec/fixtures/rails52/test/application_system_test_case.rb +++ b/spec/fixtures/rails52/test/application_system_test_case.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase diff --git a/spec/fixtures/rails52/test/models/user2_test.rb b/spec/fixtures/rails52/test/models/user2_test.rb index 7a61183d6..bcebe28c8 100644 --- a/spec/fixtures/rails52/test/models/user2_test.rb +++ b/spec/fixtures/rails52/test/models/user2_test.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'test_helper' class User2Test < ActiveSupport::TestCase diff --git a/spec/fixtures/rails52/test/models/user_test.rb b/spec/fixtures/rails52/test/models/user_test.rb index 45a5ff8dc..045d9e148 100644 --- a/spec/fixtures/rails52/test/models/user_test.rb +++ b/spec/fixtures/rails52/test/models/user_test.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'test_helper' class UserTest < ActiveSupport::TestCase diff --git a/spec/fixtures/rails52/test/test_helper.rb b/spec/fixtures/rails52/test/test_helper.rb index 3ab84e3d1..58af4446f 100644 --- a/spec/fixtures/rails52/test/test_helper.rb +++ b/spec/fixtures/rails52/test/test_helper.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true ENV['RAILS_ENV'] ||= 'test' require_relative '../config/environment' require 'rails/test_help' diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 5cdb7a275..1892adca6 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'spec_helper' describe 'CLI' do @@ -25,7 +26,7 @@ def read(file) end def bin_folder - "#{File.expand_path(File.dirname(__FILE__))}/../bin" + "#{__dir__}/../bin" end def executable(options = {}) @@ -97,7 +98,7 @@ def run_tests(test_option: nil) before do write 'spec/xxx1_spec.rb', 'describe("T1"){it("E1"){puts "YE" + "S"; sleep 0.5; expect(1).to eq(2)}}' # group 1 executed - write 'spec/xxx2_spec.rb', 'describe("T2"){it("E2"){sleep 1; puts "OK"}}' # group 2 executed + write 'spec/xxx2_spec.rb', 'describe("T2"){it("E2"){sleep 1; puts "OK"}}' # group 2 executed write 'spec/xxx3_spec.rb', 'describe("T3"){it("E3"){puts "NO3"}}' # group 1 skipped write 'spec/xxx4_spec.rb', 'describe("T4"){it("E4"){puts "NO4"}}' # group 2 skipped write 'spec/xxx5_spec.rb', 'describe("T5"){it("E5"){puts "NO5"}}' # group 1 skipped @@ -153,7 +154,7 @@ def test_unicode # Need to tell Ruby to default to utf-8 to simulate environments where # this is set. (Otherwise, it defaults to nil and the undefined conversion # issue doesn't come up.) - result = run_tests('test', fail: true, export: {'RUBYOPT' => 'Eutf-8:utf-8'}) + result = run_tests('test', fail: true, export: { 'RUBYOPT' => 'Eutf-8:utf-8' }) expect(result).to include('¯\_(ツ)_/¯') end @@ -210,14 +211,14 @@ def test_unicode it "can show simulated output when serializing stdout" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 0.5; puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST2"}}' - result = run_tests "spec", type: 'rspec', add: "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01'} + result = run_tests "spec", type: 'rspec', add: "--serialize-stdout", export: { 'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01' } expect(result).to match(/\.{4}.*TEST1.*\.{4}.*TEST2/m) end it "can show simulated output preceded by command when serializing stdout with verbose option" do - write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST1"}}' - result = run_tests "spec --verbose", type: 'rspec', add: "--serialize-stdout", export: {'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02'} - expect(result).to match(/\.{5}.*\nbundle exec rspec spec\/xxx_spec\.rb\nTEST1/m) + write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 1.5; puts "TEST1"}}' + result = run_tests "spec --verbose", type: 'rspec', add: "--serialize-stdout", export: { 'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02' } + expect(result).to match(/\.{5}.*\nbundle exec rspec spec\/xxx_spec\.rb\n.*^TEST1/m) end it "can serialize stdout and stderr" do @@ -232,17 +233,17 @@ def test_unicode context "with given commands" do it "can exec given commands with ENV['TEST_ENV_NUMBER']" do result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4` - expect(result.gsub('"', '').split('').sort).to eq(%w[0 2 3 4]) + expect(result.gsub('"', '').split('').sort).to eq(['0', '2', '3', '4']) end it "can exec given command non-parallel" do result = `#{executable} -e 'ruby -e "sleep(rand(10)/100.0); puts ENV[:TEST_ENV_NUMBER.to_s].inspect"' -n 4 --non-parallel` - expect(result.split(/\n+/)).to eq(%w["" "2" "3" "4"]) + expect(result.split(/\n+/)).to eq(['""', '"2"', '"3"', '"4"']) end it "can exec given command with a restricted set of groups" do result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4 --only-group 1,3` - expect(result.gsub('"', '').split('').sort).to eq(%w[0 3]) + expect(result.gsub('"', '').split('').sort).to eq(['0', '3']) end it "can serialize stdout" do @@ -297,7 +298,7 @@ def test_unicode it "can enable spring" do write "spec/xxx_spec.rb", 'puts "SPRING: #{ENV["DISABLE_SPRING"]}"' - result = run_tests("spec", processes: 2, type: 'rspec', export: {"DISABLE_SPRING" => "0"}) + result = run_tests("spec", processes: 2, type: 'rspec', export: { "DISABLE_SPRING" => "0" }) expect(result).to include "SPRING: 0" end @@ -339,7 +340,7 @@ def test_unicode write "spec/x#{i}_spec.rb", "puts %{ENV-\#{ENV['TEST_ENV_NUMBER']}-}" end result = run_tests( - "spec", export: {"PARALLEL_TEST_PROCESSORS" => processes.to_s}, processes: processes, type: 'rspec' + "spec", export: { "PARALLEL_TEST_PROCESSORS" => processes.to_s }, processes: processes, type: 'rspec' ) expect(result.scan(/ENV-.?-/)).to match_array(["ENV--", "ENV-2-", "ENV-3-", "ENV-4-", "ENV-5-"]) end @@ -452,18 +453,18 @@ def test_unicode log = "tmp/parallel_runtime_cucumber.log" write(log, "x") - 2.times { |i| + 2.times do |i| # needs sleep so that runtime loggers dont overwrite each other initially write "features/good#{i}.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit" - } + end run_tests "features", type: "cucumber" expect(read(log).gsub(/\.\d+/, '').split("\n")).to match_array(["features/good0.feature:0", "features/good1.feature:0"]) end it "runs each feature once when there are more processes then features (issue #89)" do - 2.times { |i| + 2.times do |i| write "features/good#{i}.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" - } + end result = run_tests "features", type: "cucumber", add: '-n 3' expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end @@ -547,14 +548,14 @@ class A < Spinach::FeatureSteps it "runs tests which outputs accented characters" do write "features/good1.feature", "Feature: a\n Scenario: xxx\n Given I print accented characters" write "features/steps/a.rb", "#encoding: utf-8\nclass A < Spinach::FeatureSteps\nGiven 'I print accented characters' do\n puts \"I tu też\" \n end\nend" - result = run_tests "features", type: "spinach", add: 'features/good1.feature' #, :add => '--pattern good' + result = run_tests "features", type: "spinach", add: 'features/good1.feature' # , :add => '--pattern good' expect(result).to include('I tu też') end it "passes TEST_ENV_NUMBER when running with pattern (issue #86)" do write "features/good1.feature", "Feature: a\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" write "features/good2.feature", "Feature: a\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" - write "features/b.feature", "Feature: b\n Scenario: xxx\n Given I FAIL" #Expect this not to be run + write "features/b.feature", "Feature: b\n Scenario: xxx\n Given I FAIL" # Expect this not to be run result = run_tests "features", type: "spinach", add: '--pattern good' @@ -568,18 +569,18 @@ class A < Spinach::FeatureSteps log = "tmp/parallel_runtime_spinach.log" write(log, "x") - 2.times { |i| + 2.times do |i| # needs sleep so that runtime loggers dont overwrite each other initially write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit" - } + end run_tests "features", type: "spinach" expect(read(log).gsub(/\.\d+/, '').split("\n")).to match_array(["features/good0.feature:0", "features/good1.feature:0"]) end it "runs each feature once when there are more processes then features (issue #89)" do - 2.times { |i| + 2.times do |i| write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n" - } + end result = run_tests "features", type: "spinach", add: '-n 3' expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 7be6f4c8e..6a3d52109 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" require "parallel_tests/cli" require "parallel_tests/rspec/runner" @@ -6,7 +7,7 @@ subject { ParallelTests::CLI.new } describe "#parse_options" do - let(:defaults){ {:files => ["test"]} } + let(:defaults) { { files: ["test"] } } def call(*args) subject.send(:parse_options!, *args) @@ -26,19 +27,19 @@ def call(*args) end it "parses excludes pattern" do - expect(call(["test", "--exclude-pattern", "spec/"])).to eq(defaults.merge(:exclude_pattern => /spec\//)) + expect(call(["test", "--exclude-pattern", "spec/"])).to eq(defaults.merge(exclude_pattern: /spec\//)) end it "parses regular count" do - expect(call(["test", "-n3"])).to eq(defaults.merge(:count => 3)) + expect(call(["test", "-n3"])).to eq(defaults.merge(count: 3)) end it "parses count 0 as non-parallel" do - expect(call(["test", "-n0"])).to eq(defaults.merge(:non_parallel => true)) + expect(call(["test", "-n0"])).to eq(defaults.merge(non_parallel: true)) end it "parses non-parallel as non-parallel" do - expect(call(["test", "--non-parallel"])).to eq(defaults.merge(:non_parallel => true)) + expect(call(["test", "--non-parallel"])).to eq(defaults.merge(non_parallel: true)) end it "finds the correct type when multiple are given" do @@ -47,11 +48,11 @@ def call(*args) end it "parses nice as nice" do - expect(call(["test", "--nice"])).to eq(defaults.merge(:nice => true)) + expect(call(["test", "--nice"])).to eq(defaults.merge(nice: true)) end it "parses --verbose" do - expect(call(["test", "--verbose"])).to eq(defaults.merge(:verbose => true)) + expect(call(["test", "--verbose"])).to eq(defaults.merge(verbose: true)) end it "parses --verbose-process-command" do @@ -67,7 +68,7 @@ def call(*args) end it "parses --quiet" do - expect(call(["test", "--quiet"])).to eq(defaults.merge(:quiet => true)) + expect(call(["test", "--quiet"])).to eq(defaults.merge(quiet: true)) end it "fails if both --verbose and --quiet are present" do @@ -75,12 +76,12 @@ def call(*args) end it "parses --suffix" do - expect(call(["test", "--suffix", "_(test|spec).rb$"])).to eq(defaults.merge(:suffix => /_(test|spec).rb$/)) + expect(call(["test", "--suffix", "_(test|spec).rb$"])).to eq(defaults.merge(suffix: /_(test|spec).rb$/)) end it "parses --first-is-1" do - expect(call(["test", "--first-is-1"])). - to eq(defaults.merge(:first_is_1 => true)) + expect(call(["test", "--first-is-1"])) + .to eq(defaults.merge(first_is_1: true)) end context "parse only-group" do @@ -93,17 +94,17 @@ def call(*args) end it "raise error when group_by isn't filesize" do - expect{ + expect do call(["test", "--only-group", '1', '--group-by', 'steps']) - }.to raise_error(RuntimeError) + end.to raise_error(RuntimeError) end it "with multiple groups" do - expect(call(["test", "--only-group", '4,5'])).to eq(defaults.merge(only_group: [4,5], group_by: :filesize)) + expect(call(["test", "--only-group", '4,5'])).to eq(defaults.merge(only_group: [4, 5], group_by: :filesize)) end it "with a single group" do - expect(call(["test", "--only-group", '4'])).to eq(defaults.merge(:only_group => [4], group_by: :filesize)) + expect(call(["test", "--only-group", '4'])).to eq(defaults.merge(only_group: [4], group_by: :filesize)) end end @@ -129,38 +130,38 @@ def call(*args) context "when the -- option separator is used" do it "interprets arguments as files/directories" do - expect(call(%w(-- test))).to eq( files: %w(test)) - expect(call(%w(-- ./test))).to eq( files: %w(test)) - expect(call(%w(-- test test2))).to eq( files: %w(test test2)) - expect(call(%w(-- --foo test))).to eq( files: %w(--foo test)) - expect(call(%w(-- test --foo test2))).to eq( files: %w(test --foo test2)) + expect(call(['--', 'test'])).to eq(files: ['test']) + expect(call(['--', './test'])).to eq(files: ['test']) + expect(call(['--', 'test', 'test2'])).to eq(files: ['test', 'test2']) + expect(call(['--', '--foo', 'test'])).to eq(files: ['--foo', 'test']) + expect(call(['--', 'test', '--foo', 'test2'])).to eq(files: ['test', '--foo', 'test2']) end it "corectly handles arguments with spaces" do - expect(call(['--', 'file name with space'])).to eq( files: ['file name with space']) + expect(call(['--', 'file name with space'])).to eq(files: ['file name with space']) end context "when the -o options has also been given" do it "merges the options together" do - expect(call(%w(-o '-f' -- test --foo test2))).to eq( files: %w(test --foo test2), test_options: "'-f'") + expect(call(['-o', "'-f'", '--', 'test', '--foo', 'test2'])).to eq(files: ['test', '--foo', 'test2'], test_options: "'-f'") end end context "when a second -- option separator is used" do it "interprets the first set as test_options" do - expect(call(%w(-- -r foo -- test))).to eq( files: %w(test), test_options: '-r foo') - expect(call(%w(-- -r foo -- test test2))).to eq( files: %w(test test2), test_options: '-r foo') - expect(call(%w(-- -r foo -o out.log -- test test2))).to eq( files: %w(test test2), test_options: '-r foo -o out.log') + expect(call(['--', '-r', 'foo', '--', 'test'])).to eq(files: ['test'], test_options: '-r foo') + expect(call(['--', '-r', 'foo', '--', 'test', 'test2'])).to eq(files: ['test', 'test2'], test_options: '-r foo') + expect(call(['--', '-r', 'foo', '-o', 'out.log', '--', 'test', 'test2'])).to eq(files: ['test', 'test2'], test_options: '-r foo -o out.log') end context "when existing test_options have previously been given" do it "appends the new options" do - expect(call(%w(-o '-f' -- -r foo.rb -- test))).to eq( files: %w(test), test_options: "'-f' -r foo.rb") + expect(call(['-o', "'-f'", '--', '-r', 'foo.rb', '--', 'test'])).to eq(files: ['test'], test_options: "'-f' -r foo.rb") end it "corectly handles argument values with spaces" do argv = ["-o 'path with spaces1'", '--', '--out', 'path with spaces2', '--', 'foo'] expected_test_options = "'path with spaces1' --out path\\ with\\ spaces2" - expect(call(argv)).to eq( files: %w(foo), test_options: expected_test_options) + expect(call(argv)).to eq(files: ['foo'], test_options: expected_test_options) end end end @@ -184,31 +185,32 @@ def call(*args) end it "fails to load unfindable runner" do - expect{ + expect do expect(subject.send(:load_runner, "foo")).to eq(ParallelTests::RSpec::Runner) - }.to raise_error(LoadError) + end.to raise_error(LoadError) end end describe ".report_failure_rerun_commmand" do - let(:single_failed_command) { [{exit_status: 1, command: 'foo', seed: nil, output: 'blah'}] } + let(:single_failed_command) { [{ exit_status: 1, command: 'foo', seed: nil, output: 'blah' }] } it "prints nothing if there are no failures" do expect($stdout).not_to receive(:puts) - subject.send(:report_failure_rerun_commmand, + subject.send( + :report_failure_rerun_commmand, [ - {exit_status: 0, command: 'foo', seed: nil, output: 'blah'} + { exit_status: 0, command: 'foo', seed: nil, output: 'blah' } ], - {verbose: true} + { verbose: true } ) end def self.it_prints_nothing_about_rerun_commands(options) it 'prints nothing about rerun commands' do - expect { + expect do subject.send(:report_failure_rerun_commmand, single_failed_command, options) - }.to_not output(/Use the following command to run the group again/).to_stdout + end.to_not output(/Use the following command to run the group again/).to_stdout end end @@ -223,43 +225,45 @@ def self.it_prints_nothing_about_rerun_commands(options) context "with verbose rerun" do it "prints command if there is a failure" do - expect { + expect do subject.send(:report_failure_rerun_commmand, single_failed_command, verbose_rerun_command: true) - }.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout + end.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout end end context 'with verbose' do it "prints a message and the command if there is a failure" do - expect { + expect do subject.send(:report_failure_rerun_commmand, single_failed_command, verbose: true) - }.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout + end.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout end it "prints multiple commands if there are multiple failures" do - expect { - subject.send(:report_failure_rerun_commmand, + expect do + subject.send( + :report_failure_rerun_commmand, [ - {exit_status: 1, command: 'foo', seed: nil, output: 'blah'}, - {exit_status: 1, command: 'bar', seed: nil, output: 'blah'}, - {exit_status: 1, command: 'baz', seed: nil, output: 'blah'}, + { exit_status: 1, command: 'foo', seed: nil, output: 'blah' }, + { exit_status: 1, command: 'bar', seed: nil, output: 'blah' }, + { exit_status: 1, command: 'baz', seed: nil, output: 'blah' } ], - {verbose: true} + { verbose: true } ) - }.to output(/foo\nbar\nbaz/).to_stdout + end.to output(/foo\nbar\nbaz/).to_stdout end it "only includes failures" do - expect { - subject.send(:report_failure_rerun_commmand, + expect do + subject.send( + :report_failure_rerun_commmand, [ - {exit_status: 1, command: 'foo --color', seed: nil, output: 'blah'}, - {exit_status: 0, command: 'bar', seed: nil, output: 'blah'}, - {exit_status: 1, command: 'baz', seed: nil, output: 'blah'}, + { exit_status: 1, command: 'foo --color', seed: nil, output: 'blah' }, + { exit_status: 0, command: 'bar', seed: nil, output: 'blah' }, + { exit_status: 1, command: 'baz', seed: nil, output: 'blah' } ], - {verbose: true} + { verbose: true } ) - }.to output(/foo --color\nbaz/).to_stdout + end.to output(/foo --color\nbaz/).to_stdout end it "prints the command with the seed added by the runner" do @@ -267,13 +271,13 @@ def self.it_prints_nothing_about_rerun_commands(options) seed = 555 subject.instance_variable_set(:@runner, ParallelTests::Test::Runner) - expect(ParallelTests::Test::Runner).to receive(:command_with_seed).with(command, seed). - and_return("my seeded command result --seed #{seed}") + expect(ParallelTests::Test::Runner).to receive(:command_with_seed).with(command, seed) + .and_return("my seeded command result --seed #{seed}") single_failed_command[0].merge!(seed: seed, command: command) - expect { + expect do subject.send(:report_failure_rerun_commmand, single_failed_command, verbose: true) - }.to output(/my seeded command result --seed 555/).to_stdout + end.to output(/my seeded command result --seed 555/).to_stdout end end end @@ -297,19 +301,21 @@ def self.it_prints_nothing_about_rerun_commands(options) describe "#run_tests_in_parallel" do context "specific groups to run" do - let(:results){ {:stdout => "", :exit_status => 0} } - let(:common_options) { + let(:results) { { stdout: "", exit_status: 0 } } + let(:common_options) do { files: ["test"], group_by: :filesize, first_is_1: false } - } + end before do allow(subject).to receive(:puts) expect(subject).to receive(:load_runner).with("my_test_runner").and_return(ParallelTests::MyTestRunner::Runner) allow(ParallelTests::MyTestRunner::Runner).to receive(:test_file_name).and_return("test") - expect(ParallelTests::MyTestRunner::Runner).to receive(:tests_in_groups).and_return([ - ['aaa','bbb'], - ['ccc', 'ddd'], - ['eee', 'fff'] - ]) + expect(ParallelTests::MyTestRunner::Runner).to receive(:tests_in_groups).and_return( + [ + ['aaa', 'bbb'], + ['ccc', 'ddd'], + ['eee', 'fff'] + ] + ) expect(subject).to receive(:report_results).and_return(nil) end @@ -338,7 +344,7 @@ def self.it_prints_nothing_about_rerun_commands(options) it "run twice with multiple groups" do skip "fails on jruby" if RUBY_PLATFORM == "java" - options = common_options.merge(count: 3, only_group: [2,3]) + options = common_options.merge(count: 3, only_group: [2, 3]) expect(subject).to receive(:run_tests).once.with(['ccc', 'ddd'], 0, 1, options).and_return(results) expect(subject).to receive(:run_tests).once.with(['eee', 'fff'], 1, 1, options).and_return(results) subject.run(['test', '-n', '3', '--only-group', '2,3', '-t', 'my_test_runner']) diff --git a/spec/parallel_tests/cucumber/failure_logger_spec.rb b/spec/parallel_tests/cucumber/failure_logger_spec.rb index 82b7c452b..bded42186 100644 --- a/spec/parallel_tests/cucumber/failure_logger_spec.rb +++ b/spec/parallel_tests/cucumber/failure_logger_spec.rb @@ -1,9 +1,9 @@ +# frozen_string_literal: true require 'spec_helper' require 'parallel_tests/gherkin/io' require 'parallel_tests/cucumber/failures_logger' describe ParallelTests::Cucumber::FailuresLogger do - before do @output = OutputLogger.new([]) allow(@output).to receive(:write) @@ -14,9 +14,9 @@ @logger2 = ParallelTests::Cucumber::FailuresLogger.new(config) @logger3 = ParallelTests::Cucumber::FailuresLogger.new(config) - @feature1 = double('feature', :file => "feature/path/to/feature1.feature") - @feature2 = double('feature', :file => "feature/path/to/feature2.feature") - @feature3 = double('feature', :file => "feature/path/to/feature3.feature") + @feature1 = double('feature', file: "feature/path/to/feature1.feature") + @feature2 = double('feature', file: "feature/path/to/feature2.feature") + @feature3 = double('feature', file: "feature/path/to/feature3.feature") @logger1.instance_variable_set("@failures", { @feature1.file => [1, 2, 3] }) @logger2.instance_variable_set("@failures", { @feature2.file => [2, 4, 6] }) @@ -24,22 +24,22 @@ end it "should produce a list of lines for failing scenarios" do - @logger1.done() - @logger2.done() - @logger3.done() + @logger1.done + @logger2.done + @logger3.done output_file_contents = @output.output.join("\n").concat("\n") - expect(output_file_contents).to eq < "-t @colours") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @colours") expect(scenarios.length).to eq 7 end it 'Single Scenario Tag: white' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t @white") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @white") expect(scenarios.length).to eq 2 end it 'Multiple Scenario Tags 1: black && white' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@black and @white'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@black and @white'") expect(scenarios.length).to eq 1 end it 'Multiple Scenario Tags 2: black || white scenarios' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@black or @white'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@black or @white'") expect(scenarios.length).to eq 3 end it 'Scenario Outline Tag: red' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t @red") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @red") expect(scenarios.length).to eq 4 end it 'Example Tag: blue' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t @blue") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @blue") expect(scenarios.length).to eq 3 end it 'Multiple Example Tags 1: blue && green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@blue and @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@blue and @green'") expect(scenarios.length).to eq 1 end it 'Multiple Example Tags 2: blue || green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@blue or @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@blue or @green'") expect(scenarios.length).to eq 4 end it 'Single Negative Feature Tag: !colours' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not @colours'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @colours'") expect(scenarios.length).to eq 0 end it 'Single Negative Scenario Tag: !black' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not @black'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @black'") expect(scenarios.length).to eq 5 end it 'Multiple Negative Scenario Tags And: !(black && white)' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not (@black and @white)'") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "-t 'not (@black and @white)'" + ) expect(scenarios.length).to eq 6 end it 'Multiple Negative Scenario Tags Or: !(black || red)' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not (@black or @red)'") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "-t 'not (@black or @red)'" + ) expect(scenarios.length).to eq 1 end it 'Negative Scenario Outline Tag: !red' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not @red'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @red'") expect(scenarios.length).to eq 3 end it 'Negative Example Tag: !blue' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not @blue'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @blue'") expect(scenarios.length).to eq 4 end it 'Multiple Negative Example Tags 1: !blue && !green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not @blue and not @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "-t 'not @blue and not @green'" + ) expect(scenarios.length).to eq 3 end it 'Multiple Negative Example Tags 2: !blue || !green) ' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t 'not @blue or not @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "-t 'not @blue or not @green'" + ) expect(scenarios.length).to eq 6 end it 'Scenario and Example Mixed Tags: black || green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@black or @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@black or @green'") expect(scenarios.length).to eq 4 end it 'Positive and Negative Mixed Tags: red && !blue' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@red and not @blue'") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "-t '@red and not @blue'" + ) expect(scenarios.length).to eq 1 end it 'Multiple Positive and Negative Mixed Tags: (white && black) || (red && !blue)' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "--tags '(not @white and @black) or (@red and not @green)'") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "--tags '(not @white and @black) or (@red and not @green)'" + ) expect(scenarios.length).to eq 3 end it 'Ignore Tag Pattern Feature: colours' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :ignore_tag_pattern => "@colours") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], ignore_tag_pattern: "@colours") expect(scenarios.length).to eq 0 end it 'Ignore Tag Pattern Scenario: black' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :ignore_tag_pattern => "@black") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], ignore_tag_pattern: "@black") expect(scenarios.length).to eq 5 end it 'Ignore Tag Pattern Scenario Outline: red' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :ignore_tag_pattern => "@red") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], ignore_tag_pattern: "@red") expect(scenarios.length).to eq 3 end it 'Ignore Tag Pattern Example: green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :ignore_tag_pattern => "@green") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], ignore_tag_pattern: "@green") expect(scenarios.length).to eq 5 end it 'Ignore Tag Pattern Multiple Tags: black || red' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :ignore_tag_pattern => "@black or @red") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], ignore_tag_pattern: "@black or @red") expect(scenarios.length).to eq 1 end it 'Scenario Mixed tags: black && !blue with Ignore Tag Pattern Multiple Tags: red || white' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], :test_options => "-t '@black and not @blue'", :ignore_tag_pattern => "@red or @white") + scenarios = ParallelTests::Cucumber::Scenarios.all( + [feature_file.path], + test_options: "-t '@black and not @blue'", ignore_tag_pattern: "@red or @white" + ) expect(scenarios.length).to eq 1 end end -end \ No newline at end of file +end diff --git a/spec/parallel_tests/gherkin/listener_spec.rb b/spec/parallel_tests/gherkin/listener_spec.rb index 9969bac87..d2a01bcce 100644 --- a/spec/parallel_tests/gherkin/listener_spec.rb +++ b/spec/parallel_tests/gherkin/listener_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'parallel_tests/gherkin/listener' describe ParallelTests::Gherkin::Listener do @@ -8,89 +9,88 @@ end it "returns steps count" do - 3.times {@listener.step(nil)} - expect(@listener.collect).to eq({"feature_file" => 3}) + 3.times { @listener.step(nil) } + expect(@listener.collect).to eq({ "feature_file" => 3 }) end it "counts background steps separately" do @listener.background("background") - 5.times {@listener.step(nil)} - expect(@listener.collect).to eq({"feature_file" => 0}) + 5.times { @listener.step(nil) } + expect(@listener.collect).to eq({ "feature_file" => 0 }) @listener.scenario("scenario") - 2.times {@listener.step(nil)} - expect(@listener.collect).to eq({"feature_file" => 2}) + 2.times { @listener.step(nil) } + expect(@listener.collect).to eq({ "feature_file" => 2 }) @listener.scenario("scenario") - expect(@listener.collect).to eq({"feature_file" => 2}) + expect(@listener.collect).to eq({ "feature_file" => 2 }) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 12}) + expect(@listener.collect).to eq({ "feature_file" => 12 }) end it "counts scenario outlines steps separately" do @listener.scenario_outline("outline") - 5.times {@listener.step(nil)} - @listener.examples(double('examples', :rows => Array.new(3))) - expect(@listener.collect).to eq({"feature_file" => 15}) + 5.times { @listener.step(nil) } + @listener.examples(double('examples', rows: Array.new(3))) + expect(@listener.collect).to eq({ "feature_file" => 15 }) @listener.scenario("scenario") - 2.times {@listener.step(nil)} - expect(@listener.collect).to eq({"feature_file" => 17}) + 2.times { @listener.step(nil) } + expect(@listener.collect).to eq({ "feature_file" => 17 }) @listener.scenario("scenario") - expect(@listener.collect).to eq({"feature_file" => 17}) + expect(@listener.collect).to eq({ "feature_file" => 17 }) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 17}) + expect(@listener.collect).to eq({ "feature_file" => 17 }) end it 'counts scenarios that should not be ignored' do @listener.ignore_tag_pattern = nil - @listener.scenario( double('scenario', :tags =>[ double('tag', :name => '@WIP' )]) ) + @listener.scenario(double('scenario', tags: [double('tag', name: '@WIP')])) @listener.step(nil) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 1}) + expect(@listener.collect).to eq({ "feature_file" => 1 }) @listener.ignore_tag_pattern = /@something_other_than_WIP/ - @listener.scenario( double('scenario', :tags =>[ double('tag', :name => '@WIP' )]) ) + @listener.scenario(double('scenario', tags: [double('tag', name: '@WIP')])) @listener.step(nil) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 2}) + expect(@listener.collect).to eq({ "feature_file" => 2 }) end it 'does not count scenarios that should be ignored' do @listener.ignore_tag_pattern = /@WIP/ - @listener.scenario( double('scenario', :tags =>[ double('tag', :name => '@WIP' )])) + @listener.scenario(double('scenario', tags: [double('tag', name: '@WIP')])) @listener.step(nil) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 0}) + expect(@listener.collect).to eq({ "feature_file" => 0 }) end it 'counts outlines that should not be ignored' do @listener.ignore_tag_pattern = nil - @listener.scenario_outline( double('scenario', :tags =>[ double('tag', :name => '@WIP' )]) ) + @listener.scenario_outline(double('scenario', tags: [double('tag', name: '@WIP')])) @listener.step(nil) - @listener.examples(double('examples', :rows => Array.new(3))) + @listener.examples(double('examples', rows: Array.new(3))) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 3}) + expect(@listener.collect).to eq({ "feature_file" => 3 }) @listener.ignore_tag_pattern = /@something_other_than_WIP/ - @listener.scenario_outline( double('scenario', :tags =>[ double('tag', :name => '@WIP' )]) ) + @listener.scenario_outline(double('scenario', tags: [double('tag', name: '@WIP')])) @listener.step(nil) - @listener.examples(double('examples', :rows => Array.new(3))) + @listener.examples(double('examples', rows: Array.new(3))) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 6}) + expect(@listener.collect).to eq({ "feature_file" => 6 }) end it 'does not count outlines that should be ignored' do @listener.ignore_tag_pattern = /@WIP/ - @listener.scenario_outline( double('scenario', :tags =>[ double('tag', :name => '@WIP' )]) ) + @listener.scenario_outline(double('scenario', tags: [double('tag', name: '@WIP')])) @listener.step(nil) - @listener.examples(double('examples', :rows => Array.new(3))) + @listener.examples(double('examples', rows: Array.new(3))) @listener.eof - expect(@listener.collect).to eq({"feature_file" => 0}) + expect(@listener.collect).to eq({ "feature_file" => 0 }) end - end end diff --git a/spec/parallel_tests/gherkin/runner_behaviour.rb b/spec/parallel_tests/gherkin/runner_behaviour.rb index 546bb3347..f8b6eaad1 100644 --- a/spec/parallel_tests/gherkin/runner_behaviour.rb +++ b/spec/parallel_tests/gherkin/runner_behaviour.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" require "parallel_tests/gherkin/runner" @@ -10,25 +11,25 @@ end def call(*args) - runner_class().run_tests(*args) + runner_class.run_tests(*args) end it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec' - should_run_with(/script\/custom_rspec/) + should_run_with(%r{script/custom_rspec}) call(['xxx'], 1, 22, {}) end it "permits setting env options" do - expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, b, c, options| + expect(ParallelTests::Test::Runner).to receive(:execute_command) do |_, _, _, options| expect(options[:env]["TEST"]).to eq("ME") end - call(['xxx'], 1, 22, {:env => {'TEST' => 'ME'}}) + call(['xxx'], 1, 22, { env: { 'TEST' => 'ME' } }) end it "runs bundle exec {runner_name} when on bundler 0.9" do allow(ParallelTests).to receive(:bundler_enabled?).and_return true - should_run_with %r{bundle exec #{runner_name}} + should_run_with /bundle exec #{runner_name}/ call(['xxx'], 1, 22, {}) end @@ -39,7 +40,7 @@ def call(*args) it "runs {runner_name} by default" do allow(File).to receive(:file?).with("script/#{runner_name}").and_return false - should_run_with %r{^#{runner_name}} + should_run_with /^#{runner_name}/ call(['xxx'], 1, 22, {}) end @@ -51,14 +52,14 @@ def call(*args) it "uses options passed in" do should_run_with %r{script/#{runner_name} .*-p default} - call(['xxx'], 1, 22, :test_options => '-p default') + call(['xxx'], 1, 22, test_options: '-p default') end it "sanitizes dangerous file runner_names" do if ParallelTests::WINDOWS - should_run_with %r{"xx x"} + should_run_with /"xx x"/ else - should_run_with %r{xx\\ x} + should_run_with /xx\\ x/ end call(['xx x'], 1, 22, {}) @@ -78,7 +79,7 @@ def call(*args) should_run_with %r{script/#{runner_name} .*foo bar --profile parallel xxx} end - call(['xxx'], 1, 22, :test_options => 'foo bar') + call(['xxx'], 1, 22, test_options: 'foo bar') end it "uses given profile via --profile" do @@ -88,7 +89,7 @@ def call(*args) should_run_with %r{script/#{runner_name} .*--profile foo xxx$} end - call(['xxx'], 1, 22, :test_options => '--profile foo') + call(['xxx'], 1, 22, test_options: '--profile foo') end it "uses given profile via -p" do @@ -98,7 +99,7 @@ def call(*args) should_run_with %r{script/#{runner_name} .*-p foo xxx$} end - call(['xxx'], 1, 22, :test_options => '-p foo') + call(['xxx'], 1, 22, test_options: '-p foo') end end @@ -107,11 +108,11 @@ def call(*args) should_run_with %r{script/#{runner_name} .*foo bar} expect(Dir).to receive(:glob).and_return ["config/#{runner_name}.yml"] expect(File).to receive(:read).with("config/#{runner_name}.yml").and_return file_contents - call(['xxx'], 1, 22, :test_options => 'foo bar') + call(['xxx'], 1, 22, test_options: 'foo bar') end it "does not use the parallel profile if config/{runner_name}.yml does not exist" do - should_run_with %r{script/#{runner_name}} # TODO this test looks useless... + should_run_with %r{script/#{runner_name}} # TODO: this test looks useless... expect(Dir).to receive(:glob).and_return [] call(['xxx'], 1, 22, {}) end @@ -120,33 +121,33 @@ def call(*args) describe :line_is_result? do it "should match lines with only one scenario" do line = "1 scenario (1 failed)" - expect(runner_class().line_is_result?(line)).to be_truthy + expect(runner_class.line_is_result?(line)).to be_truthy end it "should match lines with multiple scenarios" do line = "2 scenarios (1 failed, 1 passed)" - expect(runner_class().line_is_result?(line)).to be_truthy + expect(runner_class.line_is_result?(line)).to be_truthy end it "should match lines with only one step" do line = "1 step (1 failed)" - expect(runner_class().line_is_result?(line)).to be_truthy + expect(runner_class.line_is_result?(line)).to be_truthy end it "should match lines with multiple steps" do line = "5 steps (1 failed, 4 passed)" - expect(runner_class().line_is_result?(line)).to be_truthy + expect(runner_class.line_is_result?(line)).to be_truthy end it "should not match other lines" do line = ' And I should have "2" emails # features/step_definitions/user_steps.rb:25' - expect(runner_class().line_is_result?(line)).to be_falsey + expect(runner_class.line_is_result?(line)).to be_falsey end end describe :find_results do it "finds multiple results in test output" do - output = <<-EOF.gsub(/^ /, "") + output = <<~EOF And I should not see "/en/" # features/step_definitions/webrat_steps.rb:87 7 scenarios (3 failed, 4 passed) @@ -164,18 +165,27 @@ def call(*args) 1 scenario (1 passed) 1 step (1 passed) EOF - expect(runner_class.find_results(output)).to eq(["7 scenarios (3 failed, 4 passed)", "33 steps (3 failed, 2 skipped, 28 passed)", "4 scenarios (4 passed)", "40 steps (40 passed)", "1 scenario (1 passed)", "1 step (1 passed)"]) + expect(runner_class.find_results(output)).to eq( + [ + "7 scenarios (3 failed, 4 passed)", + "33 steps (3 failed, 2 skipped, 28 passed)", + "4 scenarios (4 passed)", + "40 steps (40 passed)", + "1 scenario (1 passed)", "1 step (1 passed)" + ] + ) end end describe :summarize_results do def call(*args) - runner_class().summarize_results(*args) + runner_class.summarize_results(*args) end it "sums up results for scenarios and steps separately from each other" do results = [ - "7 scenarios (2 failed, 1 flaky, 4 passed)", "33 steps (3 failed, 2 skipped, 28 passed)", + "7 scenarios (2 failed, 1 flaky, 4 passed)", + "33 steps (3 failed, 2 skipped, 28 passed)", "4 scenarios (4 passed)", "40 steps (40 passed)", "1 scenario (1 passed)", "1 step (1 passed)" ] @@ -205,14 +215,14 @@ def call(*args) describe 'grouping by scenarios for cucumber' do def call(*args) - runner_class().send(:run_tests, *args) + runner_class.send(:run_tests, *args) end it 'groups cucumber invocation by feature files to achieve correct cucumber hook behaviour' do - test_files = %w(features/a.rb:23 features/a.rb:44 features/b.rb:12) + test_files = ['features/a.rb:23', 'features/a.rb:44', 'features/b.rb:12'] - expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a,b,c,d| - argv = a.split(" ").last(2) + expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _b, _c, _d| + argv = a.split.last(2) if ParallelTests::WINDOWS expect(argv).to eq(['"features/a.rb:23:44"', '"features/b.rb:12"']) @@ -221,7 +231,7 @@ def call(*args) end end - call(test_files, 1, 2, { :group_by => :scenarios }) + call(test_files, 1, 2, { group_by: :scenarios }) end end @@ -231,10 +241,12 @@ def call(*args) end it "doesn't find bakup files with the same name as test files" do - with_files(['a/x.feature','a/x.feature.bak']) do |root| - expect(call(["#{root}/"])).to eq([ - "#{root}/a/x.feature", - ]) + with_files(['a/x.feature', 'a/x.feature.bak']) do |root| + expect(call(["#{root}/"])).to eq( + [ + "#{root}/a/x.feature" + ] + ) end end end diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index ee571a364..4937c23ea 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'spec_helper' require 'parallel_tests/grouper' require 'parallel_tests/cucumber/scenarios' @@ -6,7 +7,7 @@ describe ParallelTests::Grouper do describe '.by_steps' do def write(file, content) - File.open(file,'w'){|f| f.write content } + File.open(file, 'w') { |f| f.write content } end it "sorts features by steps" do @@ -14,23 +15,28 @@ def write(file, content) result = Dir.mktmpdir do |dir| tmpdir = dir write("#{dir}/a.feature", "Feature: xxx\n Scenario: xxx\n Given something") - write("#{dir}/b.feature", "Feature: xxx\n Scenario: xxx\n Given something\n Scenario: yyy\n Given something") + write( + "#{dir}/b.feature", + "Feature: xxx\n Scenario: xxx\n Given something\n Scenario: yyy\n Given something" + ) write("#{dir}/c.feature", "Feature: xxx\n Scenario: xxx\n Given something") ParallelTests::Grouper.by_steps(["#{dir}/a.feature", "#{dir}/b.feature", "#{dir}/c.feature"], 2, {}) end # testing inside mktmpdir is always green - expect(result).to match_array([ - ["#{tmpdir}/a.feature", "#{tmpdir}/c.feature"], - ["#{tmpdir}/b.feature"] - ]) + expect(result).to match_array( + [ + ["#{tmpdir}/a.feature", "#{tmpdir}/c.feature"], + ["#{tmpdir}/b.feature"] + ] + ) end end describe '.in_even_groups_by_size' do - let(:files_with_size){ {"1" => 1, "2" => 2, "3" => 3, "4" => 4, "5" => 5} } + let(:files_with_size) { { "1" => 1, "2" => 2, "3" => 3, "4" => 4, "5" => 5 } } - def call(num_groups, options={}) + def call(num_groups, options = {}) ParallelTests::Grouper.in_even_groups_by_size(files_with_size, num_groups, options) end @@ -51,25 +57,24 @@ def call(num_groups, options={}) end it "groups single items into first group" do - expect(call(2, :single_process => [/1|2|3|4/])).to eq([["1", "2", "3", "4"], ["5"]]) + expect(call(2, single_process: [/1|2|3|4/])).to eq([["1", "2", "3", "4"], ["5"]]) end it "groups single items into specified isolation groups" do - expect(call(3, :single_process => [/1|2|3|4/], :isolate_count => 2)).to eq([["1", "4"], ["2", "3"], ["5"]]) + expect(call(3, single_process: [/1|2|3|4/], isolate_count: 2)).to eq([["1", "4"], ["2", "3"], ["5"]]) end it "groups single items with others if there are too few" do - expect(call(2, :single_process => [/1/])).to eq([["1", "3", "4"], ["2", "5"]]) + expect(call(2, single_process: [/1/])).to eq([["1", "3", "4"], ["2", "5"]]) end it "groups must abort when isolate_count is out of bounds" do - expect { - call(3, :single_process => [/1/], :isolate_count => 3) - }.to raise_error( + expect do + call(3, single_process: [/1/], isolate_count: 3) + end.to raise_error( "Number of isolated processes must be less than total the number of processes" ) end - end describe '.by_scenarios' do diff --git a/spec/parallel_tests/pids_spec.rb b/spec/parallel_tests/pids_spec.rb index f6f88eaa3..c3ceb6d03 100644 --- a/spec/parallel_tests/pids_spec.rb +++ b/spec/parallel_tests/pids_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'spec_helper' RSpec.describe ParallelTests::Pids do @@ -13,15 +14,15 @@ describe '#add' do specify do subject.add(789) - expect(subject.all).to eq ([123, 456, 789]) + expect(subject.all).to eq([123, 456, 789]) end end - + describe '#delete' do specify do subject.add(101) subject.delete(123) - expect(subject.all).to eq ([456, 101]) + expect(subject.all).to eq([456, 101]) end end diff --git a/spec/parallel_tests/rspec/failures_logger_spec.rb b/spec/parallel_tests/rspec/failures_logger_spec.rb index 5f25a39b2..ebe840e14 100644 --- a/spec/parallel_tests/rspec/failures_logger_spec.rb +++ b/spec/parallel_tests/rspec/failures_logger_spec.rb @@ -1,13 +1,16 @@ +# frozen_string_literal: true require 'spec_helper' describe ParallelTests::RSpec::FailuresLogger do - let(:output){ OutputLogger.new([]) } - let(:logger){ ParallelTests::RSpec::FailuresLogger.new(output) } + let(:output) { OutputLogger.new([]) } + let(:logger) { ParallelTests::RSpec::FailuresLogger.new(output) } it "prints failures" do - logger.dump_summary(double(:failed_examples => [1], :colorized_rerun_commands => "HEYHO")) - expect(output.output).to eq([ - "HEYHO\n" - ]) + logger.dump_summary(double(failed_examples: [1], colorized_rerun_commands: "HEYHO")) + expect(output.output).to eq( + [ + "HEYHO\n" + ] + ) end end diff --git a/spec/parallel_tests/rspec/logger_base_spec.rb b/spec/parallel_tests/rspec/logger_base_spec.rb index bcb9307e3..6052dc6f5 100644 --- a/spec/parallel_tests/rspec/logger_base_spec.rb +++ b/spec/parallel_tests/rspec/logger_base_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'spec_helper' describe ParallelTests::RSpec::LoggerBase do diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index 09fa0ec47..58312433a 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" require "parallel_tests/rspec/runner" @@ -18,22 +19,22 @@ def call(*args) it "runs command using nice when specifed" do ParallelTests.with_pid_file do - expect(ParallelTests::Test::Runner).to receive(:execute_command_and_capture_output)do |a,b,c| - expect(b).to match(%r{^nice rspec}) + expect(ParallelTests::Test::Runner).to receive(:execute_command_and_capture_output) do |_a, b, _c| + expect(b).to match(/^nice rspec/) end - call('xxx', 1, 22, :nice => true) + call('xxx', 1, 22, nice: true) end end it "runs with color when called from cmdline" do - should_run_with %r{ --tty} + should_run_with(/ --tty/) expect($stdout).to receive(:tty?).and_return true call('xxx', 1, 22, {}) end it "runs without color when not called from cmdline" do - should_not_run_with %r{ --tty} + should_not_run_with(/ --tty/) expect($stdout).to receive(:tty?).and_return false call('xxx', 1, 22, {}) end @@ -51,7 +52,7 @@ def call(*args) end it "uses -O spec/parallel_spec.opts with rspec2" do - skip if RUBY_PLATFORM == "java" # FIXME not sure why, but fails on travis + skip if RUBY_PLATFORM == "java" # FIXME: not sure why, but fails on travis expect(File).to receive(:file?).with('spec/parallel_spec.opts').and_return true allow(ParallelTests).to receive(:bundler_enabled?).and_return true @@ -62,13 +63,13 @@ def call(*args) end it "uses options passed in" do - should_run_with %r{rspec -f n} - call('xxx', 1, 22, :test_options => '-f n') + should_run_with /rspec -f n/ + call('xxx', 1, 22, test_options: '-f n') end it "returns the output" do - expect(ParallelTests::RSpec::Runner).to receive(:execute_command).and_return :x => 1 - expect(call('xxx', 1, 22, {})).to eq({:x => 1}) + expect(ParallelTests::RSpec::Runner).to receive(:execute_command).and_return x: 1 + expect(call('xxx', 1, 22, {})).to eq({ x: 1 }) end end @@ -89,7 +90,7 @@ def call(*args) 1 example, 1 failure, 1 pending OUT - expect(call(output)).to eq(['0 examples, 0 failures, 0 pending','1 example, 1 failure, 1 pending']) + expect(call(output)).to eq(['0 examples, 0 failures, 0 pending', '1 example, 1 failure, 1 pending']) end it "does not mistakenly count 'pending' failures as real failures" do @@ -120,10 +121,8 @@ def call(*args) end it "doesn't find bakup files with the same name as test files" do - with_files(['a/x_spec.rb','a/x_spec.rb.bak']) do |root| - expect(call(["#{root}/"])).to eq([ - "#{root}/a/x_spec.rb", - ]) + with_files(['a/x_spec.rb', 'a/x_spec.rb.bak']) do |root| + expect(call(["#{root}/"])).to eq(["#{root}/a/x_spec.rb"]) end end end diff --git a/spec/parallel_tests/rspec/runtime_logger_spec.rb b/spec/parallel_tests/rspec/runtime_logger_spec.rb index fee4c2877..2332d40b1 100644 --- a/spec/parallel_tests/rspec/runtime_logger_spec.rb +++ b/spec/parallel_tests/rspec/runtime_logger_spec.rb @@ -1,33 +1,32 @@ +# frozen_string_literal: true require 'spec_helper' describe ParallelTests::RSpec::RuntimeLogger do before do # pretend we run in parallel or the logger will log nothing ENV['TEST_ENV_NUMBER'] = '' - @clean_output = %r{^spec/foo.rb:[-\.e\d]+$}m + @clean_output = %r{^spec/foo.rb:[-.e\d]+$}m end - def log_for_a_file(options={}) + def log_for_a_file(_options = {}) Tempfile.open('xxx') do |temp| temp.close - f = File.open(temp.path,'w') + f = File.open(temp.path, 'w') logger = if block_given? yield(f) else ParallelTests::RSpec::RuntimeLogger.new(f) end - example = double(:file_path => "#{Dir.pwd}/spec/foo.rb") - unless ParallelTests::RSpec::RuntimeLogger::RSPEC_2 - example = double(:group => example) - end + example = double(file_path: "#{Dir.pwd}/spec/foo.rb") + example = double(group: example) unless ParallelTests::RSpec::RuntimeLogger::RSPEC_2 logger.example_group_started example logger.example_group_finished example logger.start_dump - #f.close + # f.close return File.read(f.path) end end @@ -89,7 +88,10 @@ def write(file, content) RUBY end - system({'TEST_ENV_NUMBER' => '1'}, "rspec spec -I #{Bundler.root.join("lib")} --format ParallelTests::RSpec::RuntimeLogger --out runtime.log 2>&1") || raise("nope") + system( + { 'TEST_ENV_NUMBER' => '1' }, + "rspec spec -I #{Bundler.root.join("lib")} --format ParallelTests::RSpec::RuntimeLogger --out runtime.log 2>&1" + ) || raise("nope") result = File.read("runtime.log") expect(result).to match(%r{^spec/a_spec.rb:0.5}) @@ -118,7 +120,10 @@ def write(file, content) end RUBY - system({'TEST_ENV_NUMBER' => '1'}, "rspec spec -I #{Bundler.root.join("lib")} --format ParallelTests::RSpec::RuntimeLogger --out runtime.log 2>&1") || raise("nope") + system( + { 'TEST_ENV_NUMBER' => '1' }, + "rspec spec -I #{Bundler.root.join("lib")} --format ParallelTests::RSpec::RuntimeLogger --out runtime.log 2>&1" + ) || raise("nope") result = File.read("runtime.log") expect(result).to include "a_spec.rb:1.5" diff --git a/spec/parallel_tests/rspec/summary_logger_spec.rb b/spec/parallel_tests/rspec/summary_logger_spec.rb index 6857baefe..43813e105 100644 --- a/spec/parallel_tests/rspec/summary_logger_spec.rb +++ b/spec/parallel_tests/rspec/summary_logger_spec.rb @@ -1,13 +1,16 @@ +# frozen_string_literal: true require 'spec_helper' describe ParallelTests::RSpec::SummaryLogger do - let(:output){ OutputLogger.new([]) } - let(:logger){ ParallelTests::RSpec::SummaryLogger.new(output) } + let(:output) { OutputLogger.new([]) } + let(:logger) { ParallelTests::RSpec::SummaryLogger.new(output) } it "prints failing examples" do - logger.dump_failures(double(:failure_notifications => [1], :fully_formatted_failed_examples => "HEYHO")) - expect(output.output).to eq([ - "HEYHO\n" - ]) + logger.dump_failures(double(failure_notifications: [1], fully_formatted_failed_examples: "HEYHO")) + expect(output.output).to eq( + [ + "HEYHO\n" + ] + ) end end diff --git a/spec/parallel_tests/spinach/runner_spec.rb b/spec/parallel_tests/spinach/runner_spec.rb index f71b67a14..61430d6d5 100644 --- a/spec/parallel_tests/spinach/runner_spec.rb +++ b/spec/parallel_tests/spinach/runner_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" require "parallel_tests/gherkin/runner_behaviour" require "parallel_tests/spinach/runner" @@ -6,7 +7,7 @@ test_tests_in_groups(ParallelTests::Spinach::Runner, ".feature") it_should_behave_like 'gherkin runners' do - let(:runner_name) {'spinach'} - let(:runner_class){ParallelTests::Spinach::Runner} + let(:runner_name) { 'spinach' } + let(:runner_class) { ParallelTests::Spinach::Runner } end end diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index 0ab65b6b0..688ae5151 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -1,36 +1,43 @@ +# frozen_string_literal: true require 'spec_helper' require 'parallel_tests/tasks' describe ParallelTests::Tasks do describe ".parse_args" do it "should return the count" do - args = {:count => 2} + args = { count: 2 } expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "", "", ""]) end it "should default to the prefix" do - args = {:count => "models"} + args = { count: "models" } expect(ParallelTests::Tasks.parse_args(args)).to eq([nil, "models", "", ""]) end it "should return the count and pattern" do - args = {:count => 2, :pattern => "models"} + args = { count: 2, pattern: "models" } expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "models", "", ""]) end it "should return the count, pattern, and options" do - args = {:count => 2, :pattern => "plain", :options => "-p default"} + args = { count: 2, pattern: "plain", options: "-p default" } expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default", ""]) end it "should return the count, pattern, and options" do - args = {:count => 2, :pattern => "plain", :options => "-p default --group-by steps"} + args = { count: 2, pattern: "plain", options: "-p default --group-by steps" } expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default --group-by steps", ""]) end it "should return the count, pattern, test options, and pass-through options" do - args = {:count => 2, :pattern => "plain", :options => "-p default --group-by steps", :pass_through => "--runtime-log /path/to/log"} - expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default --group-by steps", "--runtime-log /path/to/log"]) + args = { + count: 2, pattern: "plain", options: "-p default --group-by steps", + pass_through: "--runtime-log /path/to/log" + } + expect(ParallelTests::Tasks.parse_args(args)).to eq( + [2, "plain", "-p default --group-by steps", + "--runtime-log /path/to/log"] + ) end end @@ -46,7 +53,7 @@ end describe ".run_in_parallel" do - let(:full_path){ File.expand_path("../../../bin/parallel_test", __FILE__) } + let(:full_path) { File.expand_path('../../bin/parallel_test', __dir__) } it "has the executable" do expect(File.file?(full_path)).to eq(true) @@ -60,17 +67,17 @@ it "runs command with :count option" do expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo' -n 123$/).and_return true - ParallelTests::Tasks.run_in_parallel("echo", :count => 123) + ParallelTests::Tasks.run_in_parallel("echo", count: 123) end it "runs without -n with blank :count option" do expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo'$/).and_return true - ParallelTests::Tasks.run_in_parallel("echo", :count => "") + ParallelTests::Tasks.run_in_parallel("echo", count: "") end it "runs command with :non_parallel option" do expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo' --non-parallel$/).and_return true - ParallelTests::Tasks.run_in_parallel("echo", :non_parallel => true) + ParallelTests::Tasks.run_in_parallel("echo", non_parallel: true) end it "runs aborts if the command fails" do @@ -91,7 +98,7 @@ def call(command, grep) context "with pipefail supported" do before :all do - if not system("/bin/bash", "-c", "set -o pipefail 2>/dev/null && test 1") + unless system("/bin/bash", "-c", "set -o pipefail 2>/dev/null && test 1") skip "pipefail is not supported on your system" end end @@ -115,7 +122,10 @@ def call(command, grep) context "without pipefail supported" do before do - expect(ParallelTests::Tasks).to receive(:system).with('/bin/bash', '-c', 'set -o pipefail 2>/dev/null && test 1').and_return false + expect(ParallelTests::Tasks).to receive(:system).with( + '/bin/bash', '-c', + 'set -o pipefail 2>/dev/null && test 1' + ).and_return false end it "should not filter and succeed" do diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 34b1778eb..20b150ec9 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" require "parallel_tests/test/runner" @@ -12,22 +13,22 @@ def call(*args) it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec' - expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a,b,c,d| + expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _, _, _d| expect(a).to include("script/custom_rspec") end call(['xxx'], 1, 22, {}) end it "uses options" do - expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a,b,c,d| - expect(a).to match(%r{ruby -Itest .* -- -v}) + expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _, _, _d| + expect(a).to match(/ruby -Itest .* -- -v/) end - call(['xxx'], 1, 22, :test_options => '-v') + call(['xxx'], 1, 22, test_options: '-v') end it "returns the output" do - expect(ParallelTests::Test::Runner).to receive(:execute_command).and_return({:x => 1}) - expect(call(['xxx'], 1, 22, {})).to eq({:x => 1}) + expect(ParallelTests::Test::Runner).to receive(:execute_command).and_return(x: 1) + expect(call(['xxx'], 1, 22, {})).to eq({ x: 1 }) end end @@ -55,7 +56,7 @@ def call(*args) it "sorts by runtime when runtime is available" do expect(ParallelTests::Test::Runner).to receive(:puts).with("Using recorded test runtime") - expect(ParallelTests::Test::Runner).to receive(:runtimes).and_return({"a" => 1, "b" => 1, "c" => 3}) + expect(ParallelTests::Test::Runner).to receive(:runtimes).and_return("a" => 1, "b" => 1, "c" => 3) expect(call(["a", "b", "c"], 2)).to eq([["c"], ["a", "b"]]) end @@ -103,7 +104,12 @@ def call(*args) it "groups when test name contains colons" do File.write("tmp/parallel_runtime_test.log", "ccc[1:2:3]:1\nbbb[1:2:3]:2\naaa[1:2:3]:3") - expect(call(["aaa[1:2:3]", "bbb[1:2:3]", "ccc[1:2:3]"], 2, group_by: :runtime)).to match_array([["aaa[1:2:3]"], ["bbb[1:2:3]", "ccc[1:2:3]"]]) + expect( + call( + ["aaa[1:2:3]", "bbb[1:2:3]", "ccc[1:2:3]"], 2, + group_by: :runtime + ) + ).to match_array([["aaa[1:2:3]"], ["bbb[1:2:3]", "ccc[1:2:3]"]]) end it "groups when not even statistic" do @@ -118,21 +124,25 @@ def call(*args) it "groups with unknown-runtime for missing" do File.write("tmp/parallel_runtime_test.log", "xxx:123\nbbb:10\nccc:1") - expect(call(["aaa", "bbb", "ccc", "ddd"], 2, group_by: :runtime, unknown_runtime: 0.0)).to eq([["bbb"], ["aaa", "ccc", "ddd"]]) + expect( + call(["aaa", "bbb", "ccc", "ddd"], 2, group_by: :runtime, unknown_runtime: 0.0) + ).to eq([["bbb"], ["aaa", "ccc", "ddd"]]) end it "groups by single_process pattern and then via size" do - expect(ParallelTests::Test::Runner).to receive(:runtimes). - and_return({"aaa" => 5, "bbb" => 2, "ccc" => 1, "ddd" => 1}) + expect(ParallelTests::Test::Runner).to receive(:runtimes) + .and_return({ "aaa" => 5, "bbb" => 2, "ccc" => 1, "ddd" => 1 }) result = call(["aaa", "aaa2", "bbb", "ccc", "ddd"], 3, single_process: [/^a.a/], group_by: :runtime) expect(result).to eq([["aaa", "aaa2"], ["bbb"], ["ccc", "ddd"]]) end it "groups by size and adds isolated separately" do skip if RUBY_PLATFORM == "java" - expect(ParallelTests::Test::Runner).to receive(:runtimes). - and_return({"aaa" => 0, "bbb" => 3, "ccc" => 1, "ddd" => 2}) - result = call(["aaa", "bbb", "ccc", "ddd", "eee"], 3, isolate: true, single_process: [/^aaa/], group_by: :runtime) + expect(ParallelTests::Test::Runner).to receive(:runtimes) + .and_return({ "aaa" => 0, "bbb" => 3, "ccc" => 1, "ddd" => 2 }) + result = call( + ["aaa", "bbb", "ccc", "ddd", "eee"], 3, isolate: true, single_process: [/^aaa/], group_by: :runtime + ) isolated, *groups = result expect(isolated).to eq(["aaa"]) @@ -149,9 +159,11 @@ def call(*args) it "groups by size and use specified number of isolation groups" do skip if RUBY_PLATFORM == "java" - expect(ParallelTests::Test::Runner).to receive(:runtimes). - and_return({"aaa1" => 1, "aaa2" => 3, "aaa3" => 2, "bbb" => 3, "ccc" => 1, "ddd" => 2}) - result = call(["aaa1", "aaa2", "aaa3", "bbb", "ccc", "ddd", "eee"], 4, isolate_count: 2, single_process: [/^aaa/], group_by: :runtime) + expect(ParallelTests::Test::Runner).to receive(:runtimes) + .and_return({ "aaa1" => 1, "aaa2" => 3, "aaa3" => 2, "bbb" => 3, "ccc" => 1, "ddd" => 2 }) + result = call( + ["aaa1", "aaa2", "aaa3", "bbb", "ccc", "ddd", "eee"], 4, isolate_count: 2, single_process: [/^aaa/], group_by: :runtime + ) isolated_1, isolated_2, *groups = result expect(isolated_1).to eq(["aaa2"]) @@ -175,35 +187,44 @@ def call(*args) end it "finds multiple results in test output" do - output = < false).sort).to eq([ - "#{root}/b/b_test.rb", - ]) + expect(call(["#{root}/b"], symlinks: false).sort).to eq(["#{root}/b/b_test.rb"]) end end it "finds test files nested in different folders" do - with_files(['a/a_test.rb','b/b_test.rb', 'c/c_test.rb']) do |root| - expect(call(["#{root}/a", "#{root}/b"]).sort).to eq([ - "#{root}/a/a_test.rb", - "#{root}/b/b_test.rb", - ]) + with_files(['a/a_test.rb', 'b/b_test.rb', 'c/c_test.rb']) do |root| + expect(call(["#{root}/a", "#{root}/b"]).sort).to eq( + [ + "#{root}/a/a_test.rb", + "#{root}/b/b_test.rb" + ] + ) end end it "only finds tests in folders" do with_files(['a/a_test.rb', 'a/test.rb', 'a/test_helper.rb']) do |root| - expect(call(["#{root}/a"]).sort).to eq([ - "#{root}/a/a_test.rb" - ]) + expect(call(["#{root}/a"]).sort).to eq( + [ + "#{root}/a/a_test.rb" + ] + ) end end it "finds tests in nested folders" do with_files(['a/b/c/d/a_test.rb']) do |root| - expect(call(["#{root}/a"]).sort).to eq([ - "#{root}/a/b/c/d/a_test.rb" - ]) + expect(call(["#{root}/a"]).sort).to eq( + [ + "#{root}/a/b/c/d/a_test.rb" + ] + ) end end it "does not expand paths" do with_files(['a/x_test.rb']) do |root| Dir.chdir root do - expect(call(['a']).sort).to eq([ - "a/x_test.rb" - ]) + expect(call(['a']).sort).to eq( + [ + "a/x_test.rb" + ] + ) end end end it "finds test files in folders by pattern" do - with_files(['a/x_test.rb','a/y_test.rb','a/z_test.rb']) do |root| + with_files(['a/x_test.rb', 'a/y_test.rb', 'a/z_test.rb']) do |root| Dir.chdir root do - expect(call(["a"], :pattern => /^a\/(y|z)_test/).sort).to eq([ - "a/y_test.rb", - "a/z_test.rb", - ]) + expect(call(["a"], pattern: %r{^a/(y|z)_test}).sort).to eq( + [ + "a/y_test.rb", + "a/z_test.rb" + ] + ) end end end it "finds test files in folders using suffix and overriding built in suffix" do - with_files(['a/x_test.rb','a/y_test.rb','a/z_other.rb','a/x_different.rb']) do |root| + with_files(['a/x_test.rb', 'a/y_test.rb', 'a/z_other.rb', 'a/x_different.rb']) do |root| Dir.chdir root do - expect(call(["a"], :suffix => /_(test|other)\.rb$/).sort).to eq([ - "a/x_test.rb", - "a/y_test.rb", - "a/z_other.rb", - ]) + expect(call(["a"], suffix: /_(test|other)\.rb$/).sort).to eq( + [ + "a/x_test.rb", + "a/y_test.rb", + "a/z_other.rb" + ] + ) end end end it "doesn't find bakup files with the same name as test files" do - with_files(['a/x_test.rb','a/x_test.rb.bak']) do |root| - expect(call(["#{root}/"])).to eq([ - "#{root}/a/x_test.rb", - ]) + with_files(['a/x_test.rb', 'a/x_test.rb.bak']) do |root| + expect(call(["#{root}/"])).to eq( + [ + "#{root}/a/x_test.rb" + ] + ) end end it "finds minispec files" do with_files(['a/x_spec.rb']) do |root| - expect(call(["#{root}/"])).to eq([ - "#{root}/a/x_spec.rb", - ]) + expect(call(["#{root}/"])).to eq( + [ + "#{root}/a/x_spec.rb" + ] + ) end end @@ -327,7 +362,7 @@ def call(*args) end it "discards duplicates" do - expect(call(['baz','baz'])).to eq(['baz']) + expect(call(['baz', 'baz'])).to eq(['baz']) end end @@ -337,19 +372,19 @@ def call(*args) end it "adds results" do - expect(call(['1 foo 3 bar','2 foo 5 bar'])).to eq('8 bars, 3 foos') + expect(call(['1 foo 3 bar', '2 foo 5 bar'])).to eq('8 bars, 3 foos') end it "adds results with braces" do - expect(call(['1 foo(s) 3 bar(s)','2 foo 5 bar'])).to eq('8 bars, 3 foos') + expect(call(['1 foo(s) 3 bar(s)', '2 foo 5 bar'])).to eq('8 bars, 3 foos') end it "adds same results with plurals" do - expect(call(['1 foo 3 bar','2 foos 5 bar'])).to eq('8 bars, 3 foos') + expect(call(['1 foo 3 bar', '2 foos 5 bar'])).to eq('8 bars, 3 foos') end it "adds non-similar results" do - expect(call(['1 xxx 2 yyy','1 xxx 2 zzz'])).to eq('2 xxxs, 2 yyys, 2 zzzs') + expect(call(['1 xxx 2 yyy', '1 xxx 2 zzz'])).to eq('2 xxxs, 2 yyys, 2 zzzs') end it "does not pluralize 1" do @@ -365,11 +400,13 @@ def call(*args) let(:new_line_char) { Gem.win_platform? ? "\r\n" : "\n" } def capture_output - $stdout, $stderr = StringIO.new, StringIO.new + $stdout = StringIO.new + $stderr = StringIO.new yield [$stdout.string, $stderr.string] ensure - $stdout, $stderr = STDOUT, STDERR + $stdout = STDOUT + $stderr = STDERR end def run_with_file(content) @@ -420,10 +457,12 @@ def run_with_file(content) skip "hangs on normal ruby, works on jruby" unless RUBY_PLATFORM == "java" run_with_file("$stdin.read; puts 123") do |path| result = call("ruby #{path}", 1, 2, {}) - expect(result).to include({ - :stdout => "123\n", - :exit_status => 0 - }) + expect(result).to include( + { + stdout: "123\n", + exit_status: 0 + } + ) end end @@ -438,7 +477,7 @@ def run_with_file(content) it "prints output while running" do skip "too slow" if RUBY_PLATFORM == " java" run_with_file("$stdout.sync = true; puts 123; sleep 0.1; print 345; sleep 0.1; puts 567") do |path| - received = "" + received = +"" allow($stdout).to receive(:print) do |x| received << x.strip end @@ -461,7 +500,7 @@ def run_with_file(content) it "does not print to stdout with :serialize_stdout" do run_with_file("puts 123") do |path| expect($stdout).not_to receive(:print) - result = call("ruby #{path}", 1, 4, :serialize_stdout => true) + result = call("ruby #{path}", 1, 4, serialize_stdout: true) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 0 end @@ -470,7 +509,7 @@ def run_with_file(content) it "adds test env number to stdout with :prefix_output_with_test_env_number" do run_with_file("puts 123") do |path| expect($stdout).to receive(:print).with("[TEST GROUP 2] 123#{new_line_char}") - result = call("ruby #{path}", 1, 4, :prefix_output_with_test_env_number => true) + result = call("ruby #{path}", 1, 4, prefix_output_with_test_env_number: true) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 0 end @@ -479,7 +518,7 @@ def run_with_file(content) it "does not add test env number to stdout without :prefix_output_with_test_env_number" do run_with_file("puts 123") do |path| expect($stdout).to receive(:print).with("123#{new_line_char}") - result = call("ruby #{path}", 1, 4, :prefix_output_with_test_env_number => false) + result = call("ruby #{path}", 1, 4, prefix_output_with_test_env_number: false) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 0 end @@ -497,27 +536,25 @@ def run_with_file(content) skip "open3" _out, err = run_with_file("puts 123 ; $stderr.puts 345 ; exit 5") do |path| result = call("ruby #{path}", 1, 4, {}) - expect(result).to include({ - :stdout => "123\n", - :exit_status => 5 - }) + expect(result).to include( + stdout: "123\n", + exit_status: 5 + ) end expect(err).to eq("345\n") end it "uses a lower priority process when the nice option is used", unless: Gem.win_platform? do priority_cmd = "puts Process.getpriority(Process::PRIO_PROCESS, 0)" - priority_without_nice = run_with_file(priority_cmd){ |cmd| call("ruby #{cmd}", 1, 4, {}) }.first.to_i - priority_with_nice = run_with_file(priority_cmd){ |cmd| call("ruby #{cmd}", 1, 4, :nice => true) }.first.to_i + priority_without_nice = run_with_file(priority_cmd) { |cmd| call("ruby #{cmd}", 1, 4, {}) }.first.to_i + priority_with_nice = run_with_file(priority_cmd) { |cmd| call("ruby #{cmd}", 1, 4, nice: true) }.first.to_i expect(priority_without_nice).to be < priority_with_nice end it "returns command used" do run_with_file("puts 123; exit 5") do |path| result = call("ruby #{path}", 1, 4, {}) - expect(result).to include({ - :command => "ruby #{path}" - }) + expect(result).to include(command: "ruby #{path}") end end @@ -525,18 +562,14 @@ def run_with_file(content) it "includes seed when provided" do run_with_file("puts 'Run options: --seed 555'") do |path| result = call("ruby #{path}", 1, 4, {}) - expect(result).to include({ - :seed => "555" - }) + expect(result).to include(seed: "555") end end it "seed is nil when not provided" do run_with_file("puts 555") do |path| result = call("ruby #{path}", 1, 4, {}) - expect(result).to include({ - :seed => nil - }) + expect(result).to include(seed: nil) end end end diff --git a/spec/parallel_tests/test/runtime_logger_spec.rb b/spec/parallel_tests/test/runtime_logger_spec.rb index 209734714..ad856bb51 100644 --- a/spec/parallel_tests/test/runtime_logger_spec.rb +++ b/spec/parallel_tests/test/runtime_logger_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'spec_helper' describe ParallelTests::Test::RuntimeLogger do @@ -40,10 +41,12 @@ def test_foo # log looking good ? lines = File.read("tmp/parallel_runtime_test.log").split("\n").sort.map { |x| x.sub(/\d$/, "") } - expect(lines).to eq([ - "test/0_test.rb:0.7", - "test/1_test.rb:0.7", - ]) + expect(lines).to eq( + [ + "test/0_test.rb:0.7", + "test/1_test.rb:0.7" + ] + ) end end end diff --git a/spec/parallel_tests_spec.rb b/spec/parallel_tests_spec.rb index 6ffa3a870..265fda709 100644 --- a/spec/parallel_tests_spec.rb +++ b/spec/parallel_tests_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" describe ParallelTests do @@ -75,8 +76,8 @@ def call(count) example.run end end - - def with_running_processes(count, wait=0.2) + + def with_running_processes(count, wait = 0.2) count.times { |x| ParallelTests.pids.add(x) } sleep 0.1 yield @@ -102,7 +103,7 @@ def with_running_processes(count, wait=0.2) ENV["TEST_ENV_NUMBER"] = "2" counter = 0 allow(ParallelTests).to receive(:sleep) do - sleep 0.1; + sleep 0.1 ParallelTests.pids.delete(1) if counter > 3 counter += 1 end @@ -120,14 +121,14 @@ def with_running_processes(count, wait=0.2) example.run end end - + it "is 0 for nothing" do expect(ParallelTests.number_of_running_processes).to eq(0) end it "is 2 when 2 are running" do wait = 0.2 - 2.times { |x| ParallelTests.pids.add(123) } + 2.times { |_x| ParallelTests.pids.add(123) } sleep wait / 2 expect(ParallelTests.number_of_running_processes).to eq(2) sleep wait diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index dec26360e..0e43f1760 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -1,9 +1,10 @@ +# frozen_string_literal: true require 'spec_helper' describe 'rails' do let(:test_timeout) { 800 } # this can take very long on fresh bundle ... - def sh(command, options={}) + def sh(command, options = {}) result = '' IO.popen(options.fetch(:environment, {}), command, err: [:child, :out]) do |io| result = io.read @@ -13,11 +14,9 @@ def sh(command, options={}) end # TODO: rails 6 - %w(rails51 rails52).each do |rails| + ['rails51', 'rails52'].each do |rails| it "can create and run #{rails}" do - if RUBY_PLATFORM == "java" - skip 'rails fixtures are not set up for java' - end + skip 'rails fixtures are not set up for java' if RUBY_PLATFORM == "java" Dir.chdir("spec/fixtures/#{rails}") do Bundler.with_unbundled_env do @@ -33,7 +32,7 @@ def sh(command, options={}) # Also test the case where the DBs need to be dropped sh "bundle exec rake parallel:drop parallel:create" sh "bundle exec rake parallel:prepare" - sh "bundle exec rails runner User.create", environment: {'RAILS_ENV' => 'test'} # pollute the db + sh "bundle exec rails runner User.create", environment: { 'RAILS_ENV' => 'test' } # pollute the db out = sh "bundle exec rake parallel:prepare parallel:test" expect(out).to match(/ 2 (tests|runs)/) end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 2251a749d..aeec78d56 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'bundler/setup' require 'tempfile' require 'tmpdir' @@ -16,11 +17,13 @@ def strip_heredoc OutputLogger = Struct.new(:output) do attr_reader :flock, :flush - def puts(s=nil) - self.output << "#{s}\n" + + def puts(s = nil) + output << "#{s}\n" end - def print(s=nil) - self.output << "#{s}" + + def print(s = nil) + output << s.to_s end end @@ -49,13 +52,13 @@ def with_files(files) end def should_run_with(regex) - expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, b, c, d| + expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _b, _c, _d| expect(a).to match(regex) end end def should_not_run_with(regex) - expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, b, c, d| + expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _b, _c, _d| expect(a).to_not match(regex) end end @@ -71,14 +74,14 @@ def test_tests_in_groups(klass, suffix) before do FileUtils.mkdir test_root - @files = [0,1,2,3,4,5,6,7].map { |i| "#{test_root}/x#{i}#{suffix}" } + @files = [0, 1, 2, 3, 4, 5, 6, 7].map { |i| "#{test_root}/x#{i}#{suffix}" } @files.each { |file| File.write(file, 'x' * 100) } FileUtils.mkdir_p File.dirname(log) end - def setup_runtime_log - File.open(log,'w') do |f| - @files[1..-1].each{|file| f.puts "#{file}:#{@files.index(file)}"} + def setup_runtime_log # rubocop:disable Lint/NestedMethodDefinition + File.open(log, 'w') do |f| + @files[1..-1].each { |file| f.puts "#{file}:#{@files.index(file)}" } f.puts "#{@files[0]}:10" end end @@ -87,12 +90,12 @@ def setup_runtime_log list_of_files = Dir["#{test_root}/**/*#{suffix}"] result = list_of_files.dup klass.send(:sort_by_filesize, result) - expect(result).to match_array(list_of_files.map{ |file| [file, File.stat(file).size]}) + expect(result).to match_array(list_of_files.map { |file| [file, File.stat(file).size] }) end it "finds all tests" do found = klass.tests_in_groups([test_root], 1) - all = [ Dir["#{test_root}/**/*#{suffix}"] ] + all = [Dir["#{test_root}/**/*#{suffix}"]] expect(found.flatten - all.flatten).to eq([]) end @@ -108,7 +111,7 @@ def setup_runtime_log it 'should partition correctly with an uneven group size' do groups = klass.tests_in_groups([test_root], 3) - expect(groups.map {|g| size_of(g) }).to match_array([300, 300, 200]) + expect(groups.map { |g| size_of(g) }).to match_array([300, 300, 200]) end it "partitions by runtime when runtime-data is available" do @@ -118,22 +121,22 @@ def setup_runtime_log groups = klass.tests_in_groups([test_root], 2) expect(groups.size).to eq(2) # 10 + 1 + 3 + 5 = 19 - expect(groups[0]).to eq([@files[0],@files[1],@files[3],@files[5]]) + expect(groups[0]).to eq([@files[0], @files[1], @files[3], @files[5]]) # 2 + 4 + 6 + 7 = 19 - expect(groups[1]).to eq([@files[2],@files[4],@files[6],@files[7]]) + expect(groups[1]).to eq([@files[2], @files[4], @files[6], @files[7]]) end it 'partitions from custom runtime-data location' do allow(klass).to receive(:puts) - log.replace('tmp/custom_runtime.log') + allow_any_instance_of(klass).to receive(:runtime_log).and_return('tmp/custom_runtime.log') setup_runtime_log groups = klass.tests_in_groups([test_root], 2, runtime_log: log) expect(groups.size).to eq(2) # 10 + 1 + 3 + 5 = 19 - expect(groups[0]).to eq([@files[0],@files[1],@files[3],@files[5]]) + expect(groups[0]).to eq([@files[0], @files[1], @files[3], @files[5]]) # 2 + 4 + 6 + 7 = 19 - expect(groups[1]).to eq([@files[2],@files[4],@files[6],@files[7]]) + expect(groups[1]).to eq([@files[2], @files[4], @files[6], @files[7]]) end it "alpha-sorts partitions when runtime-data is available" do @@ -150,15 +153,15 @@ def setup_runtime_log it "partitions by round-robin when not sorting" do files = ["file1.rb", "file2.rb", "file3.rb", "file4.rb"] expect(klass).to receive(:find_tests).and_return(files) - groups = klass.tests_in_groups(files, 2, :group_by => :found).sort + groups = klass.tests_in_groups(files, 2, group_by: :found).sort expect(groups[0]).to eq(["file1.rb", "file3.rb"]) expect(groups[1]).to eq(["file2.rb", "file4.rb"]) end it "alpha-sorts partitions when not sorting by runtime" do - 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] + files = ['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'] expect(klass).to receive(:find_tests).and_return(files) - groups = klass.tests_in_groups(files, 2, :group_by => :found).sort + groups = klass.tests_in_groups(files, 2, group_by: :found).sort expect(groups[0]).to eq(groups[0].sort) expect(groups[1]).to eq(groups[1].sort) end @@ -172,18 +175,22 @@ def setup_runtime_log end failure_message do |actual| - "expected the following string:\n" + - '""""' + "\n" + actual + "\n" + '""""' + "\n" + - (expected.is_a?(String) ? "to contain '#{expected}'" : "to match /#{expected}/") + - " #{times} time(s), but it " + (expected.is_a?(String) ? "appears" : "matches") + - " #{actual.scan(expected).size} time(s)\n" + action = (expected.is_a?(String) ? "to contain '#{expected}'" : "to match /#{expected}/") + outcome = (expected.is_a?(String) ? "appears" : "matches") + <<~FAILURE + expected the following string: + """" + #{actual} + """" + #{action} #{times} time(s), but it #{outcome} #{actual.scan(expected).size} time(s) + FAILURE end end TestTookTooLong = Class.new(Timeout::Error) RSpec.configure do |config| - config.filter_run :focus => true + config.filter_run focus: true config.run_all_when_everything_filtered = true config.include SpecHelper config.extend SharedExamples @@ -192,7 +199,13 @@ def setup_runtime_log # sometimes stuff hangs -> do not hang everything # NOTE: the timeout error can sometimes swallow errors, comment it out if you run into trouble - config.include(Module.new {def test_timeout;30;end }) + config.include( + Module.new do + def test_timeout + 30 + end + end + ) config.around do |example| Timeout.timeout(test_timeout, TestTookTooLong, &example) end From be7a35a2bc1fa259057144217bbfd5e78b0ae369 Mon Sep 17 00:00:00 2001 From: Jay Shah Date: Thu, 28 Jan 2021 16:18:45 -0800 Subject: [PATCH 072/177] update readme to remove incorrect command about running after migrations and add correct command (#798) --- Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Readme.md b/Readme.md index 141eaecf3..09e71b05d 100644 --- a/Readme.md +++ b/Readme.md @@ -37,6 +37,9 @@ test: ### Copy development schema (repeat after migrations) rake parallel:prepare +### Run migrations in additional database(s) (repeat after migrations) + rake parallel:migrate + ### Setup environment from scratch (create db and loads schema, useful for CI) rake parallel:setup From c081333c8a16226549f98658dffcb0ed2a4d3a0a Mon Sep 17 00:00:00 2001 From: Phileas Lebada Date: Fri, 12 Feb 2021 18:42:46 +0100 Subject: [PATCH 073/177] Fix broken link after updating title (#800) * Fix broken link after updating title I've added GitLab support to the wiki page and adjusted the title. * Add explanation outside wiki-link --- Readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Readme.md b/Readme.md index 09e71b05d..2f1cf56c4 100644 --- a/Readme.md +++ b/Readme.md @@ -287,7 +287,7 @@ TIPS `export PARALLEL_TEST_FIRST_IS_1=true` will provide the same result - [email_spec and/or action_mailer_cache_delivery](https://github.com/grosser/parallel_tests/wiki) - [zeus-parallel_tests](https://github.com/sevos/zeus-parallel_tests) - - [Distributed parallel test (e.g. Travis Support)](https://github.com/grosser/parallel_tests/wiki/Distributed-Parallel-Tests-and-Travis-Support) + - [Distributed Parallel Tests on CI systems)](https://github.com/grosser/parallel_tests/wiki/Distributed-Parallel-Tests-on-CI-systems) learn how `parallel_tests` can run on distributed servers such as Travis and GitLab-CI. Also shows you how to use parallel_tests without adding `TEST_ENV_NUMBER`-backends - [Capybara setup](https://github.com/grosser/parallel_tests/wiki) - [Sphinx setup](https://github.com/grosser/parallel_tests/wiki) - [Capistrano setup](https://github.com/grosser/parallel_tests/wiki/Remotely-with-capistrano) let your tests run on a big box instead of your laptop From 4326db8022676ee7675297bd5041eb2c4aa30e30 Mon Sep 17 00:00:00 2001 From: Zach Attas Date: Wed, 24 Feb 2021 10:21:45 -0600 Subject: [PATCH 074/177] Specify groups argument (#797) --- CHANGELOG.md | 2 +- Readme.md | 9 +++++ lib/parallel_tests/cli.rb | 22 ++++++++++++ lib/parallel_tests/grouper.rb | 46 ++++++++++++++++++++++++ spec/parallel_tests/cli_spec.rb | 10 ++++++ spec/parallel_tests/grouper_spec.rb | 48 +++++++++++++++++++++++++ spec/parallel_tests/test/runner_spec.rb | 22 ++++++++++++ 7 files changed, 158 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 607254235..aec5ee869 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -Add changes here in your PR +- Add support for specifying exactly how isolated processes run tests with 'specify-groups' option. ### Breaking Changes diff --git a/Readme.md b/Readme.md index 2f1cf56c4..a6195e2a2 100644 --- a/Readme.md +++ b/Readme.md @@ -213,6 +213,15 @@ Options are: -i, --isolate Do not run any other tests in the group used by --single(-s). Automatically turned on if --isolate-n is set above 0. --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on. + --specify-groups [SPECS] Use 'specify-groups' if you want to specify multiple specs running in multiple + processes in a specific formation. Commas indicate specs in the same process, + pipes indicate specs in a new process. Cannot use with --single, --isolate, or + --isolate-n. Ex. + Ex. + $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' + Process 1 will contain 1_spec.rb and 2_spec.rb + Process 2 will contain 3_spec.rb + Process 3 will contain all other specs --only-group INT[,INT] -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER'] -o, --test-options '[OPTIONS]' execute test commands with those options diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 43dd3f71b..c955571f1 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -208,6 +208,23 @@ def parse_options!(argv) "Use 'isolate' singles with number of processes, default: 1." ) { |n| options[:isolate_count] = n } + gap = "\s" * 37 + opts.on( + "--specify-groups [SPECS]", + <<~TEXT + Use 'specify-groups' if you want to specify multiple specs running in multiple + #{gap}processes in a specific formation. Commas indicate specs in the same process, + #{gap}pipes indicate specs in a new process. Cannot use with --single, --isolate, or + #{gap}--isolate-n. Ex. + #{gap}$ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' + #{gap}\s\sProcess 1 will contain 1_spec.rb and 2_spec.rb + #{gap}\s\sProcess 2 will contain 3_spec.rb + #{gap}\s\sProcess 3 will contain all other specs + TEXT + ) do |groups| + options[:specify_groups] = groups + end + opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } @@ -279,6 +296,11 @@ def parse_options!(argv) raise "--group-by #{allowed.join(" or ")} is required for --only-group" end + not_allowed_with_specify_groups = [:single_process, :isolate, :isolate_count] + if options[:specify_groups] && (options.keys & not_allowed_with_specify_groups).any? + raise "Can't pass --specify-groups with any of these keys: --single, --isolate, or --isolate-n" + end + options end diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index ab6706c2b..ae37ccb52 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -15,6 +15,7 @@ def by_scenarios(tests, num_groups, options = {}) def in_even_groups_by_size(items, num_groups, options = {}) groups = Array.new(num_groups) { { items: [], size: 0 } } + return specify_groups(items, num_groups, options, groups) if options[:specify_groups] # add all files that should run in a single process to one group single_process_patterns = options[:single_process] || [] @@ -28,6 +29,10 @@ def in_even_groups_by_size(items, num_groups, options = {}) raise 'Number of isolated processes must be less than total the number of processes' end + if isolate_count >= num_groups + raise 'Number of isolated processes must be less than total the number of processes' + end + if isolate_count >= 1 # add all files that should run in a multiple isolated processes to their own groups group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)]) @@ -46,6 +51,47 @@ def in_even_groups_by_size(items, num_groups, options = {}) private + def specify_groups(items, num_groups, options, groups) + specify_test_process_groups = options[:specify_groups].split('|') + if specify_test_process_groups.count > num_groups + raise 'Number of processes separated by pipe must be less than or equal to the total number of processes' + end + + all_specified_tests = specify_test_process_groups.map { |group| group.split(',') }.flatten + specified_items_found, items = items.partition { |item, _size| all_specified_tests.include?(item) } + + specified_specs_not_found = all_specified_tests - specified_items_found.map(&:first) + if specified_specs_not_found.any? + raise "Could not find #{specified_specs_not_found} from --specify-groups in the main selected files & folders" + end + + if specify_test_process_groups.count == num_groups && items.flatten.any? + raise( + "The number of groups in --specify-groups matches the number of groups from -n but there were other specs " \ + "found in the main selected files & folders not specified in --specify-groups. Make sure -n is larger than the " \ + "number of processes in --specify-groups if there are other specs that need to be run. The specs that aren't run: " \ + "#{items.map(&:first)}" + ) + end + + # First order the specify_groups into the main groups array + specify_test_process_groups.each_with_index do |specify_test_process, i| + groups[i] = specify_test_process.split(',') + end + + # Return early here as we've processed the specify_groups tests and those exactly match the items passed in + return groups if specify_test_process_groups.count == num_groups + + # Now sort the rest of the items into the main groups array + remaining_groups = groups[specify_test_process_groups.count..-1] + group_features_by_size(items_to_group(items), remaining_groups) + # Don't sort all the groups, only sort the ones not specified in specify_groups + sorted_groups = remaining_groups.map { |g| g[:items].sort } + groups[specify_test_process_groups.count..-1] = sorted_groups + + groups + end + def isolate_count(options) if options[:isolate_count] && options[:isolate_count] > 1 options[:isolate_count] diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 6a3d52109..d01a33c8d 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -128,6 +128,16 @@ def call(*args) end end + context "specify groups" do + it "groups can be just one string" do + expect(call(["test", "--specify-groups", 'test'])).to eq(defaults.merge(specify_groups: 'test')) + end + + it "groups can be a string separated by commas and pipes" do + expect(call(["test", "--specify-groups", 'test1,test2|test3'])).to eq(defaults.merge(specify_groups: 'test1,test2|test3')) + end + end + context "when the -- option separator is used" do it "interprets arguments as files/directories" do expect(call(['--', 'test'])).to eq(files: ['test']) diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index 4937c23ea..b71f7241f 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -75,6 +75,54 @@ def call(num_groups, options = {}) "Number of isolated processes must be less than total the number of processes" ) end + + it "groups specify_groups as specified when specify_groups is just one spec" do + expect(call(3, specify_groups: '1')).to eq([["1"], ["2", "5"], ["3", "4"]]) + end + + it "groups specify_groups as specified when specify_groups is just multiple specs in one process" do + expect(call(3, specify_groups: '3,1')).to eq([["3", "1"], ["5"], ["2", "4"]]) + end + + it "groups specify_groups as specified when specify_groups is multiple specs" do + expect(call(3, specify_groups: '1,2|4')).to eq([["1", "2"], ["4"], ["3", "5"]]) + end + + it "specify_groups aborts when number of specs separated by pipe is out of bounds" do + expect do + call(3, specify_groups: '1|2|3|4') + end.to raise_error( + "Number of processes separated by pipe must be less than or equal to the total number of processes" + ) + end + + it "specify_groups aborts when spec passed in doesnt match existing specs" do + expect do + call(3, specify_groups: '1|2|6') + end.to raise_error( + "Could not find [\"6\"] from --specify-groups in the main selected files & folders" + ) + end + + it "specify_groups aborts when spec passed in doesnt match existing specs again" do + expect do + call(3, specify_groups: '1,6|2') + end.to raise_error( + "Could not find [\"6\"] from --specify-groups in the main selected files & folders" + ) + end + + it "specify_groups aborts when number of specs is equal to number passed in" do + expect do + call(3, specify_groups: '1|2|3') + end.to raise_error( + "The number of groups in --specify-groups matches the number of groups from -n but there were other specs found in the main selected files & folders not specified in --specify-groups. Make sure -n is larger than the number of processes in --specify-groups if there are other specs that need to be run. The specs that aren't run: [\"4\", \"5\"]" + ) + end + + it "specify_groups does not abort when the every single spec is specified in it" do + expect(call(3, specify_groups: '1,2|3,4|5')).to eq([["1", "2"], ["3", "4"], ["5"]]) + end end describe '.by_scenarios' do diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 20b150ec9..1b40e79a2 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -178,6 +178,28 @@ def call(*args) expect(valid_combinations).to include(actual) end + + it 'groups by size and uses specified groups of specs in specific order in specific processes' do + skip if RUBY_PLATFORM == "java" + expect(ParallelTests::Test::Runner).to receive(:runtimes) + .and_return({ "aaa1" => 1, "aaa2" => 1, "aaa3" => 2, "bbb" => 3, "ccc" => 1, "ddd" => 2, "eee" => 1 }) + result = call( + ["aaa1", "aaa2", "aaa3", "bbb", "ccc", "ddd", "eee"], 4, specify_groups: 'aaa2,aaa1|bbb', group_by: :runtime + ) + + specify_groups_1, specify_groups_2, *groups = result + expect(specify_groups_1).to eq(["aaa2", "aaa1"]) + expect(specify_groups_2).to eq(["bbb"]) + actual = groups.map(&:to_set).to_set + + # both eee and ccs are the same size, so either can be in either group + valid_combinations = [ + [["aaa3", "ccc"], ["ddd", "eee"]].map(&:to_set).to_set, + [["aaa3", "eee"], ["ddd", "ccc"]].map(&:to_set).to_set + ] + + expect(valid_combinations).to include(actual) + end end end From 8589347ca298914e3abc779a568faf44de0c4b34 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Wed, 24 Feb 2021 09:41:32 -0800 Subject: [PATCH 075/177] formatting and cleanup for specify groups (#804) --- lib/parallel_tests/cli.rb | 45 ++++++++++++++--------------- lib/parallel_tests/grouper.rb | 22 ++++++++------ spec/integration_spec.rb | 10 +++++++ spec/parallel_tests/grouper_spec.rb | 8 ++--- 4 files changed, 47 insertions(+), 38 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index c955571f1..7083bdd53 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -162,6 +162,7 @@ def any_test_failed?(test_results) end def parse_options!(argv) + newline_padding = " " * 37 options = {} OptionParser.new do |opts| opts.banner = <<~BANNER @@ -180,14 +181,14 @@ def parse_options!(argv) opts.on("--exclude-pattern", "--exclude-pattern [PATTERN]", "exclude tests matching this regex pattern") { |pattern| options[:exclude_pattern] = /#{pattern}/ } opts.on( "--group-by [TYPE]", - <<~TEXT + <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") group tests by: - found - order of finding files - steps - number of cucumber/spinach steps - scenarios - individual cucumber scenarios - filesize - by size of the file - runtime - info from runtime log - default - runtime when runtime log is filled otherwise filesize + found - order of finding files + steps - number of cucumber/spinach steps + scenarios - individual cucumber scenarios + filesize - by size of the file + runtime - info from runtime log + default - runtime when runtime log is filled otherwise filesize TEXT ) { |type| options[:group_by] = type.to_sym } opts.on("-m [FLOAT]", "--multiply-processes [FLOAT]", Float, "use given number as a multiplier of processes to run") do |multiply| @@ -208,22 +209,19 @@ def parse_options!(argv) "Use 'isolate' singles with number of processes, default: 1." ) { |n| options[:isolate_count] = n } - gap = "\s" * 37 opts.on( "--specify-groups [SPECS]", - <<~TEXT + <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") Use 'specify-groups' if you want to specify multiple specs running in multiple - #{gap}processes in a specific formation. Commas indicate specs in the same process, - #{gap}pipes indicate specs in a new process. Cannot use with --single, --isolate, or - #{gap}--isolate-n. Ex. - #{gap}$ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' - #{gap}\s\sProcess 1 will contain 1_spec.rb and 2_spec.rb - #{gap}\s\sProcess 2 will contain 3_spec.rb - #{gap}\s\sProcess 3 will contain all other specs + processes in a specific formation. Commas indicate specs in the same process, + pipes indicate specs in a new process. Cannot use with --single, --isolate, or + --isolate-n. Ex. + $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' + Process 1 will contain 1_spec.rb and 2_spec.rb + Process 2 will contain 3_spec.rb + Process 3 will contain all other specs TEXT - ) do |groups| - options[:specify_groups] = groups - end + ) { |groups| options[:specify_groups] = groups } opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } @@ -239,10 +237,10 @@ def parse_options!(argv) end opts.on( "--suffix [PATTERN]", - <<~TEXT + <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") override built in test file pattern (should match suffix): - '_spec\.rb$' - matches rspec files - '_(test|spec).rb$' - matches test or spec files + '_spec\.rb$' - matches rspec files + '_(test|spec).rb$' - matches test or spec files TEXT ) { |pattern| options[:suffix] = /#{pattern}/ } opts.on("--serialize-stdout", "Serialize stdout output, nothing will be written until everything is done") { options[:serialize_stdout] = true } @@ -296,8 +294,7 @@ def parse_options!(argv) raise "--group-by #{allowed.join(" or ")} is required for --only-group" end - not_allowed_with_specify_groups = [:single_process, :isolate, :isolate_count] - if options[:specify_groups] && (options.keys & not_allowed_with_specify_groups).any? + if options[:specify_groups] && (options.keys & [:single_process, :isolate, :isolate_count]).any? raise "Can't pass --specify-groups with any of these keys: --single, --isolate, or --isolate-n" end diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index ae37ccb52..959339f16 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -16,6 +16,7 @@ def in_even_groups_by_size(items, num_groups, options = {}) groups = Array.new(num_groups) { { items: [], size: 0 } } return specify_groups(items, num_groups, options, groups) if options[:specify_groups] + # add all files that should run in a single process to one group single_process_patterns = options[:single_process] || [] @@ -30,7 +31,7 @@ def in_even_groups_by_size(items, num_groups, options = {}) end if isolate_count >= num_groups - raise 'Number of isolated processes must be less than total the number of processes' + raise 'Number of isolated processes must be >= total number of processes' end if isolate_count >= 1 @@ -62,15 +63,17 @@ def specify_groups(items, num_groups, options, groups) specified_specs_not_found = all_specified_tests - specified_items_found.map(&:first) if specified_specs_not_found.any? - raise "Could not find #{specified_specs_not_found} from --specify-groups in the main selected files & folders" + raise "Could not find #{specified_specs_not_found} from --specify-groups in the selected files & folders" end if specify_test_process_groups.count == num_groups && items.flatten.any? raise( - "The number of groups in --specify-groups matches the number of groups from -n but there were other specs " \ - "found in the main selected files & folders not specified in --specify-groups. Make sure -n is larger than the " \ - "number of processes in --specify-groups if there are other specs that need to be run. The specs that aren't run: " \ - "#{items.map(&:first)}" + <<~ERROR + The number of groups in --specify-groups matches the number of groups from -n but there were other specs + found in the selected files & folders not specified in --specify-groups. Make sure -n is larger than the + number of processes in --specify-groups if there are other specs that need to be run. The specs that aren't run: + #{items.map(&:first)} + ERROR ) end @@ -79,15 +82,16 @@ def specify_groups(items, num_groups, options, groups) groups[i] = specify_test_process.split(',') end - # Return early here as we've processed the specify_groups tests and those exactly match the items passed in + # Return early when processed specify_groups tests exactly match the items passed in return groups if specify_test_process_groups.count == num_groups # Now sort the rest of the items into the main groups array - remaining_groups = groups[specify_test_process_groups.count..-1] + specified_range = specify_test_process_groups.count..-1 + remaining_groups = groups[specified_range] group_features_by_size(items_to_group(items), remaining_groups) # Don't sort all the groups, only sort the ones not specified in specify_groups sorted_groups = remaining_groups.map { |g| g[:items].sort } - groups[specify_test_process_groups.count..-1] = sorted_groups + groups[specified_range] = sorted_groups groups end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 1892adca6..8c14c4612 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -390,6 +390,16 @@ def test_unicode expect(group_2_result).to include("short test") end + it "shows nice --help" do + result = run_tests "--help" + expect( + result[/(.*)How many processes/, 1].size + ).to( + eq(result[/( +)found /, 1].size), + "Multiline option description must align with regular option description" + ) + end + context "RSpec" do it_fails_without_any_files "rspec" diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index b71f7241f..ee8ed583f 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -100,7 +100,7 @@ def call(num_groups, options = {}) expect do call(3, specify_groups: '1|2|6') end.to raise_error( - "Could not find [\"6\"] from --specify-groups in the main selected files & folders" + "Could not find [\"6\"] from --specify-groups in the selected files & folders" ) end @@ -108,16 +108,14 @@ def call(num_groups, options = {}) expect do call(3, specify_groups: '1,6|2') end.to raise_error( - "Could not find [\"6\"] from --specify-groups in the main selected files & folders" + "Could not find [\"6\"] from --specify-groups in the selected files & folders" ) end it "specify_groups aborts when number of specs is equal to number passed in" do expect do call(3, specify_groups: '1|2|3') - end.to raise_error( - "The number of groups in --specify-groups matches the number of groups from -n but there were other specs found in the main selected files & folders not specified in --specify-groups. Make sure -n is larger than the number of processes in --specify-groups if there are other specs that need to be run. The specs that aren't run: [\"4\", \"5\"]" - ) + end.to raise_error(/The specs that aren't run:\n\["4", "5"\]/) end it "specify_groups does not abort when the every single spec is specified in it" do From 225ee8ab093e516a4d73bd34e18c851a0e17f430 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Wed, 24 Feb 2021 09:42:34 -0800 Subject: [PATCH 076/177] v3.5.0 --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ Gemfile.lock | 5 +---- lib/parallel_tests/version.rb | 2 +- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aec5ee869..f935c4dae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,34 @@ ## Unreleased +### Breaking Changes + +- None + +### Added + +- None + +### Fixed + +- None + +## v3.5.0 - 2021-02-24 + +### Breaking Changes + +- None + +### Added + - Add support for specifying exactly how isolated processes run tests with 'specify-groups' option. +- Refactorings for rubocop + +### Fixed + +- None + +## v3.4.0 - 2020-12-24 ### Breaking Changes diff --git a/Gemfile.lock b/Gemfile.lock index 6e3443104..23f882402 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.4.0) + parallel_tests (3.5.0) parallel GEM @@ -92,8 +92,6 @@ GEM unicode-display_width (>= 1.4.0, < 3.0) rubocop-ast (1.4.0) parser (>= 2.7.1.5) - rubocop-rake (0.5.1) - rubocop ruby-progressbar (1.11.0) spinach (0.11.0) colorize @@ -121,7 +119,6 @@ DEPENDENCIES rake rspec (~> 3.3) rubocop - rubocop-rake spinach test-unit diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 71723fadf..913372119 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.4.0' + VERSION = '3.5.0' end From 91d2e7547b9be7b3c09ff2d1d8a24c71a3d1bb6e Mon Sep 17 00:00:00 2001 From: Simon Claessens Date: Sun, 7 Mar 2021 20:43:45 +0100 Subject: [PATCH 077/177] replace deprecated db:structure by db:schema (#803) --- CHANGELOG.md | 2 +- lib/parallel_tests/tasks.rb | 11 ++++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f935c4dae..89a74d787 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,7 +41,7 @@ ### Fixed -- None +- replace deprecated db:structure by db:schema (#801). ## 3.3.0 - 2020-09-16 diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index e5b1d86e5..5d206288c 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -123,8 +123,12 @@ def parse_args(args) ParallelTests::Tasks.check_for_pending_migrations if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format) # fast: dump once, load in parallel - type = (ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure") - Rake::Task["db:#{type}:dump"].invoke + if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') + Rake::Task["db:schema:dump"].invoke + else + type = (ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure") + Rake::Task["db:#{type}:dump"].invoke + end # remove database connection to prevent "database is being accessed by other users" ActiveRecord::Base.remove_connection if ActiveRecord::Base.configurations.any? @@ -163,7 +167,8 @@ def parse_args(args) end # load the structure from the structure.sql file - desc "Load structure for test databases via db:structure:load --> parallel:load_structure[num_cpus]" + # (faster for rails < 6.1, deprecated after and only configured by `ActiveRecord::Base.schema_format`) + desc "Load structure for test databases via db:schema:load --> parallel:load_structure[num_cpus]" task :load_structure, :count do |_, args| ParallelTests::Tasks.run_in_parallel( "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ From 40f72e928ff5f8d0640691a49ecef3bedf545bf5 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 7 Mar 2021 11:46:07 -0800 Subject: [PATCH 078/177] v3.5.1 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 23f882402..854159b61 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.5.0) + parallel_tests (3.5.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 913372119..89085534f 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.5.0' + VERSION = '3.5.1' end From 43353fb41ff667a9b9737f5031c0b345c0b9b9cd Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 7 Mar 2021 11:49:42 -0800 Subject: [PATCH 079/177] changelog --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89a74d787..4187d54cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,22 @@ - None +# Changelog + +## v3.5.1 - 2021-03-07 + +### Breaking Changes + +- None + +### Added + +- None + +### Fixed + +- Do not use db:structure for rails 6.1 + ## v3.5.0 - 2021-02-24 ### Breaking Changes From 45e9cbba573419fa3a9693815c694449eba93bd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Flasi=C5=84ski?= Date: Mon, 8 Mar 2021 16:59:36 +0100 Subject: [PATCH 080/177] fix prepare rake task (#805) --- lib/parallel_tests/tasks.rb | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 5d206288c..e5d6c2366 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -123,12 +123,10 @@ def parse_args(args) ParallelTests::Tasks.check_for_pending_migrations if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format) # fast: dump once, load in parallel - if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') - Rake::Task["db:schema:dump"].invoke - else - type = (ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure") - Rake::Task["db:#{type}:dump"].invoke - end + type = "schema" if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') + type ||= ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure" + + Rake::Task["db:#{type}:dump"].invoke # remove database connection to prevent "database is being accessed by other users" ActiveRecord::Base.remove_connection if ActiveRecord::Base.configurations.any? From b47ac54430bd27361fc0bdc0d88de2555ae61418 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 8 Mar 2021 08:00:30 -0800 Subject: [PATCH 081/177] refactor type assignment --- lib/parallel_tests/tasks.rb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index e5d6c2366..ee900c3a6 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -123,8 +123,12 @@ def parse_args(args) ParallelTests::Tasks.check_for_pending_migrations if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format) # fast: dump once, load in parallel - type = "schema" if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') - type ||= ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure" + type = + if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') + "schema" + else + ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure" + end Rake::Task["db:#{type}:dump"].invoke From 235deda2b86052eaf507efb0a8dfee100020db8b Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 8 Mar 2021 08:00:41 -0800 Subject: [PATCH 082/177] v3.5.2 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 854159b61..44b821a34 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.5.1) + parallel_tests (3.5.2) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 89085534f..7867717ad 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.5.1' + VERSION = '3.5.2' end From b83e9033084e0e6bbf849e22b2c8996cd1a6502d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 25 Mar 2021 18:45:58 +0100 Subject: [PATCH 083/177] Drop ruby 2.4 support and test against latest ruby & rails (#808) --- .github/workflows/test.yml | 4 +- .rubocop.yml | 5 +- CHANGELOG.md | 4 + Gemfile.lock | 74 +++++----- lib/parallel_tests.rb | 18 ++- lib/parallel_tests/cli.rb | 22 ++- parallel_tests.gemspec | 2 +- spec/fixtures/rails51/Gemfile | 7 - spec/fixtures/rails51/Gemfile.lock | 124 ---------------- .../app/assets/javascripts/application.js | 15 -- .../app/controllers/application_controller.rb | 4 - .../rails51/app/helpers/application_helper.rb | 3 - .../rails51/app/jobs/application_job.rb | 3 - .../app/views/layouts/application.html.erb | 14 -- spec/fixtures/rails51/bin/bundle | 4 - spec/fixtures/rails51/bin/rails | 5 - spec/fixtures/rails51/bin/update | 30 ---- spec/fixtures/rails51/bin/yarn | 12 -- spec/fixtures/rails51/config/application.rb | 19 --- spec/fixtures/rails51/config/boot.rb | 4 - spec/fixtures/rails51/config/cable.yml | 10 -- .../rails51/config/initializers/assets.rb | 15 -- .../initializers/backtrace_silencers.rb | 8 -- spec/fixtures/rails51/config/puma.rb | 57 -------- spec/fixtures/rails51/config/routes.rb | 4 - spec/fixtures/rails51/config/secrets.yml | 32 ----- spec/fixtures/rails51/db/schema.rb | 21 --- spec/fixtures/rails51/package.json | 5 - spec/fixtures/rails51/public/robots.txt | 1 - spec/fixtures/rails51/test/fixtures/users.yml | 7 - .../rails51/test/models/user2_test.rb | 8 -- .../fixtures/rails51/test/models/user_test.rb | 8 -- spec/fixtures/rails52/.ruby-version | 1 - spec/fixtures/rails52/Gemfile | 7 - spec/fixtures/rails52/Gemfile.lock | 132 ------------------ .../app/assets/javascripts/application.js | 16 --- .../rails52/app/assets/javascripts/cable.js | 13 -- .../rails52/app/helpers/application_helper.rb | 3 - .../rails52/app/jobs/application_job.rb | 3 - .../app/views/layouts/application.html.erb | 15 -- spec/fixtures/rails52/bin/bundle | 4 - spec/fixtures/rails52/bin/rake | 5 - spec/fixtures/rails52/bin/update | 32 ----- spec/fixtures/rails52/bin/yarn | 12 -- .../rails52/config/credentials.yml.enc | 1 - .../rails52/config/initializers/assets.rb | 15 -- spec/fixtures/rails52/config/routes.rb | 4 - spec/fixtures/rails52/config/storage.yml | 34 ----- spec/fixtures/rails52/db/schema.rb | 21 --- spec/fixtures/rails52/package.json | 5 - spec/fixtures/rails52/public/robots.txt | 1 - spec/fixtures/rails52/test/fixtures/users.yml | 7 - spec/fixtures/rails52/test/mailers/.keep | 0 spec/fixtures/rails52/test/models/.keep | 0 .../rails52/test/models/user2_test.rb | 8 -- .../fixtures/rails52/test/models/user_test.rb | 8 -- spec/fixtures/rails52/test/system/.keep | 0 spec/fixtures/rails52/vendor/.keep | 0 spec/fixtures/{rails52 => rails60}/.gitignore | 10 +- spec/fixtures/rails60/.ruby-version | 1 + spec/fixtures/rails60/Gemfile | 19 +++ spec/fixtures/rails60/Gemfile.lock | 124 ++++++++++++++++ spec/fixtures/{rails51 => rails60}/README.md | 0 spec/fixtures/{rails52 => rails60}/Rakefile | 1 - .../app/assets/config/manifest.js | 1 - .../app/assets/images/.keep | 0 .../app/assets/stylesheets/application.css | 0 .../app/channels/application_cable/channel.rb | 1 - .../channels/application_cable/connection.rb | 1 - .../app/controllers/application_controller.rb | 1 - .../app/controllers/concerns}/.keep | 0 .../rails60/app/helpers/application_helper.rb | 2 + .../app/javascript/channels/consumer.js} | 11 +- .../rails60/app/javascript/channels/index.js | 5 + .../app/javascript/packs/application.js | 16 +++ .../rails60/app/jobs/application_job.rb | 7 + .../app/mailers/application_mailer.rb | 1 - .../app/models/application_record.rb | 1 - .../app/models}/concerns/.keep | 0 .../{rails51 => rails60}/app/models/user.rb | 1 - .../app/views/layouts/application.html.erb | 15 ++ .../app/views/layouts/mailer.html.erb | 0 .../app/views/layouts/mailer.text.erb | 0 spec/fixtures/{rails52 => rails60}/bin/rails | 1 - spec/fixtures/{rails51 => rails60}/bin/rake | 1 - spec/fixtures/{rails52 => rails60}/bin/setup | 13 +- spec/fixtures/rails60/bin/yarn | 9 ++ spec/fixtures/{rails51 => rails60}/config.ru | 1 - .../config/application.rb | 20 ++- .../{rails52 => rails60}/config/boot.rb | 1 - .../{rails52 => rails60}/config/cable.yml | 4 +- .../rails60/config/credentials.yml.enc | 1 + .../{rails52 => rails60}/config/database.yml | 4 +- .../config/environment.rb | 1 - .../config/environments/development.rb | 15 +- .../config/environments/production.rb | 40 +++--- .../config/environments/test.rb | 16 ++- .../application_controller_renderer.rb | 1 - .../initializers/backtrace_silencers.rb | 1 - .../initializers/content_security_policy.rb | 6 +- .../config/initializers/cookies_serializer.rb | 1 - .../initializers/filter_parameter_logging.rb | 1 - .../config/initializers/inflections.rb | 1 - .../config/initializers/mime_types.rb | 1 - .../config/initializers/wrap_parameters.rb | 1 - .../config/locales/en.yml | 2 +- .../{rails52 => rails60}/config/puma.rb | 13 +- spec/fixtures/rails60/config/routes.rb | 3 + .../migrate/20210325101904_create_users.rb} | 3 +- spec/fixtures/rails60/db/schema.rb | 21 +++ .../fixtures/{rails52 => rails60}/db/seeds.rb | 1 - .../concerns => rails60/lib/assets}/.keep | 0 .../lib/assets => rails60/lib/tasks}/.keep | 0 .../{rails51/lib/tasks => rails60/log}/.keep | 0 spec/fixtures/rails60/package.json | 10 ++ .../{rails51 => rails60}/public/404.html | 0 .../{rails51 => rails60}/public/422.html | 0 .../{rails51 => rails60}/public/500.html | 0 .../public/apple-touch-icon-precomposed.png | 0 .../public/apple-touch-icon.png | 0 .../{rails51 => rails60}/public/favicon.ico | 0 spec/fixtures/rails60/public/robots.txt | 1 + .../test/application_system_test_case.rb | 1 - .../application_cable/connection_test.rb | 11 ++ .../log => rails60/test/controllers}/.keep | 0 .../test/fixtures}/.keep | 0 .../test/fixtures/files}/.keep | 0 spec/fixtures/rails60/test/fixtures/users.yml | 7 + .../files => rails60/test/helpers}/.keep | 0 .../test/integration}/.keep | 0 .../test/mailers}/.keep | 0 .../mailers => rails60/test/models}/.keep | 0 .../fixtures/rails60/test/models/user_test.rb | 7 + .../test/models => rails60/test/system}/.keep | 0 .../{rails52 => rails60}/test/test_helper.rb | 1 - .../test/system => rails60/vendor}/.keep | 0 spec/fixtures/rails61/.gitattributes | 10 ++ spec/fixtures/{rails51 => rails61}/.gitignore | 13 +- spec/fixtures/rails61/.ruby-version | 1 + spec/fixtures/rails61/Gemfile | 19 +++ spec/fixtures/rails61/Gemfile.lock | 125 +++++++++++++++++ spec/fixtures/{rails52 => rails61}/README.md | 0 spec/fixtures/{rails51 => rails61}/Rakefile | 3 +- .../app/assets/config/manifest.js | 1 - .../app/assets/images}/.keep | 0 .../app/assets/stylesheets/application.css | 0 .../app/channels/application_cable/channel.rb | 1 - .../channels/application_cable/connection.rb | 1 - .../app/controllers/application_controller.rb | 2 + .../app/controllers/concerns}/.keep | 0 .../rails61/app/helpers/application_helper.rb | 2 + .../app/javascript/channels/consumer.js | 6 + .../rails61/app/javascript/channels/index.js | 5 + .../app/javascript/packs/application.js | 11 ++ .../rails61/app/jobs/application_job.rb | 7 + .../app/mailers/application_mailer.rb | 1 - .../app/models/application_record.rb | 1 - .../app/models/concerns}/.keep | 0 .../{rails52 => rails61}/app/models/user.rb | 1 - .../app/views/layouts/application.html.erb | 16 +++ .../app/views/layouts/mailer.html.erb | 0 .../app/views/layouts/mailer.text.erb | 0 spec/fixtures/rails61/bin/rails | 4 + spec/fixtures/rails61/bin/rake | 4 + spec/fixtures/{rails51 => rails61}/bin/setup | 20 ++- spec/fixtures/rails61/bin/yarn | 17 +++ spec/fixtures/{rails52 => rails61}/config.ru | 4 +- spec/fixtures/rails61/config/application.rb | 35 +++++ spec/fixtures/rails61/config/boot.rb | 3 + spec/fixtures/rails61/config/cable.yml | 10 ++ .../rails61/config/credentials.yml.enc | 1 + .../{rails51 => rails61}/config/database.yml | 4 +- .../config/environment.rb | 3 +- .../config/environments/development.rb | 36 +++-- .../config/environments/production.rb | 63 ++++++--- .../config/environments/test.rb | 29 ++-- .../application_controller_renderer.rb | 1 - .../initializers/backtrace_silencers.rb | 8 ++ .../initializers/content_security_policy.rb | 30 ++++ .../config/initializers/cookies_serializer.rb | 1 - .../initializers/filter_parameter_logging.rb | 5 +- .../config/initializers/inflections.rb | 1 - .../config/initializers/mime_types.rb | 1 - .../config/initializers/permissions_policy.rb | 11 ++ .../config/initializers/wrap_parameters.rb | 1 - .../config/locales/en.yml | 2 +- spec/fixtures/rails61/config/puma.rb | 43 ++++++ spec/fixtures/rails61/config/routes.rb | 3 + .../migrate/20210325101931_create_users.rb} | 3 +- spec/fixtures/rails61/db/schema.rb | 21 +++ .../fixtures/{rails51 => rails61}/db/seeds.rb | 3 +- .../concerns => rails61/lib/assets}/.keep | 0 .../concerns => rails61/lib/tasks}/.keep | 0 .../{rails52/lib/assets => rails61/log}/.keep | 0 spec/fixtures/rails61/package.json | 10 ++ .../{rails52 => rails61}/public/404.html | 0 .../{rails52 => rails61}/public/422.html | 0 .../{rails52 => rails61}/public/500.html | 0 .../public/apple-touch-icon-precomposed.png | 0 .../public/apple-touch-icon.png | 0 .../{rails52 => rails61}/public/favicon.ico | 0 spec/fixtures/rails61/public/robots.txt | 1 + .../test/application_system_test_case.rb | 1 - .../application_cable/connection_test.rb | 11 ++ .../tasks => rails61/test/controllers}/.keep | 0 .../log => rails61/test/fixtures/files}/.keep | 0 spec/fixtures/rails61/test/fixtures/users.yml | 7 + .../storage => rails61/test/helpers}/.keep | 0 .../test/integration}/.keep | 0 .../fixtures => rails61/test/mailers}/.keep | 0 .../files => rails61/test/models}/.keep | 0 .../fixtures/rails61/test/models/user_test.rb | 7 + .../helpers => rails61/test/system}/.keep | 0 .../{rails51 => rails61}/test/test_helper.rb | 5 +- .../test/integration => rails61/vendor}/.keep | 0 spec/integration_spec.rb | 3 +- spec/rails_spec.rb | 4 +- 217 files changed, 959 insertions(+), 1018 deletions(-) delete mode 100644 spec/fixtures/rails51/Gemfile delete mode 100644 spec/fixtures/rails51/Gemfile.lock delete mode 100644 spec/fixtures/rails51/app/assets/javascripts/application.js delete mode 100644 spec/fixtures/rails51/app/controllers/application_controller.rb delete mode 100644 spec/fixtures/rails51/app/helpers/application_helper.rb delete mode 100644 spec/fixtures/rails51/app/jobs/application_job.rb delete mode 100644 spec/fixtures/rails51/app/views/layouts/application.html.erb delete mode 100755 spec/fixtures/rails51/bin/bundle delete mode 100755 spec/fixtures/rails51/bin/rails delete mode 100755 spec/fixtures/rails51/bin/update delete mode 100755 spec/fixtures/rails51/bin/yarn delete mode 100644 spec/fixtures/rails51/config/application.rb delete mode 100644 spec/fixtures/rails51/config/boot.rb delete mode 100644 spec/fixtures/rails51/config/cable.yml delete mode 100644 spec/fixtures/rails51/config/initializers/assets.rb delete mode 100644 spec/fixtures/rails51/config/initializers/backtrace_silencers.rb delete mode 100644 spec/fixtures/rails51/config/puma.rb delete mode 100644 spec/fixtures/rails51/config/routes.rb delete mode 100644 spec/fixtures/rails51/config/secrets.yml delete mode 100644 spec/fixtures/rails51/db/schema.rb delete mode 100644 spec/fixtures/rails51/package.json delete mode 100644 spec/fixtures/rails51/public/robots.txt delete mode 100644 spec/fixtures/rails51/test/fixtures/users.yml delete mode 100644 spec/fixtures/rails51/test/models/user2_test.rb delete mode 100644 spec/fixtures/rails51/test/models/user_test.rb delete mode 100644 spec/fixtures/rails52/.ruby-version delete mode 100644 spec/fixtures/rails52/Gemfile delete mode 100644 spec/fixtures/rails52/Gemfile.lock delete mode 100644 spec/fixtures/rails52/app/assets/javascripts/application.js delete mode 100644 spec/fixtures/rails52/app/assets/javascripts/cable.js delete mode 100644 spec/fixtures/rails52/app/helpers/application_helper.rb delete mode 100644 spec/fixtures/rails52/app/jobs/application_job.rb delete mode 100644 spec/fixtures/rails52/app/views/layouts/application.html.erb delete mode 100755 spec/fixtures/rails52/bin/bundle delete mode 100755 spec/fixtures/rails52/bin/rake delete mode 100755 spec/fixtures/rails52/bin/update delete mode 100755 spec/fixtures/rails52/bin/yarn delete mode 100644 spec/fixtures/rails52/config/credentials.yml.enc delete mode 100644 spec/fixtures/rails52/config/initializers/assets.rb delete mode 100644 spec/fixtures/rails52/config/routes.rb delete mode 100644 spec/fixtures/rails52/config/storage.yml delete mode 100644 spec/fixtures/rails52/db/schema.rb delete mode 100644 spec/fixtures/rails52/package.json delete mode 100644 spec/fixtures/rails52/public/robots.txt delete mode 100644 spec/fixtures/rails52/test/fixtures/users.yml delete mode 100644 spec/fixtures/rails52/test/mailers/.keep delete mode 100644 spec/fixtures/rails52/test/models/.keep delete mode 100644 spec/fixtures/rails52/test/models/user2_test.rb delete mode 100644 spec/fixtures/rails52/test/models/user_test.rb delete mode 100644 spec/fixtures/rails52/test/system/.keep delete mode 100644 spec/fixtures/rails52/vendor/.keep rename spec/fixtures/{rails52 => rails60}/.gitignore (85%) create mode 100644 spec/fixtures/rails60/.ruby-version create mode 100644 spec/fixtures/rails60/Gemfile create mode 100644 spec/fixtures/rails60/Gemfile.lock rename spec/fixtures/{rails51 => rails60}/README.md (100%) rename spec/fixtures/{rails52 => rails60}/Rakefile (88%) rename spec/fixtures/{rails51 => rails60}/app/assets/config/manifest.js (62%) rename spec/fixtures/{rails51 => rails60}/app/assets/images/.keep (100%) rename spec/fixtures/{rails51 => rails60}/app/assets/stylesheets/application.css (100%) rename spec/fixtures/{rails51 => rails60}/app/channels/application_cable/channel.rb (72%) rename spec/fixtures/{rails51 => rails60}/app/channels/application_cable/connection.rb (73%) rename spec/fixtures/{rails52 => rails60}/app/controllers/application_controller.rb (65%) rename spec/fixtures/{rails51/app/assets/javascripts/channels => rails60/app/controllers/concerns}/.keep (100%) create mode 100644 spec/fixtures/rails60/app/helpers/application_helper.rb rename spec/fixtures/{rails51/app/assets/javascripts/cable.js => rails60/app/javascript/channels/consumer.js} (50%) create mode 100644 spec/fixtures/rails60/app/javascript/channels/index.js create mode 100644 spec/fixtures/rails60/app/javascript/packs/application.js create mode 100644 spec/fixtures/rails60/app/jobs/application_job.rb rename spec/fixtures/{rails52 => rails60}/app/mailers/application_mailer.rb (77%) rename spec/fixtures/{rails52 => rails60}/app/models/application_record.rb (72%) rename spec/fixtures/{rails51/app/controllers => rails60/app/models}/concerns/.keep (100%) rename spec/fixtures/{rails51 => rails60}/app/models/user.rb (53%) create mode 100644 spec/fixtures/rails60/app/views/layouts/application.html.erb rename spec/fixtures/{rails51 => rails60}/app/views/layouts/mailer.html.erb (100%) rename spec/fixtures/{rails51 => rails60}/app/views/layouts/mailer.text.erb (100%) rename spec/fixtures/{rails52 => rails60}/bin/rails (82%) rename spec/fixtures/{rails51 => rails60}/bin/rake (75%) rename spec/fixtures/{rails52 => rails60}/bin/setup (67%) create mode 100755 spec/fixtures/rails60/bin/yarn rename spec/fixtures/{rails51 => rails60}/config.ru (81%) rename spec/fixtures/{rails52 => rails60}/config/application.rb (55%) rename spec/fixtures/{rails52 => rails60}/config/boot.rb (81%) rename spec/fixtures/{rails52 => rails60}/config/cable.yml (71%) create mode 100644 spec/fixtures/rails60/config/credentials.yml.enc rename spec/fixtures/{rails52 => rails60}/config/database.yml (84%) rename spec/fixtures/{rails51 => rails60}/config/environment.rb (81%) rename spec/fixtures/{rails52 => rails60}/config/environments/development.rb (78%) rename spec/fixtures/{rails52 => rails60}/config/environments/production.rb (71%) rename spec/fixtures/{rails51 => rails60}/config/environments/test.rb (76%) rename spec/fixtures/{rails51 => rails60}/config/initializers/application_controller_renderer.rb (87%) rename spec/fixtures/{rails52 => rails60}/config/initializers/backtrace_silencers.rb (93%) rename spec/fixtures/{rails52 => rails60}/config/initializers/content_security_policy.rb (77%) rename spec/fixtures/{rails51 => rails60}/config/initializers/cookies_serializer.rb (89%) rename spec/fixtures/{rails52 => rails60}/config/initializers/filter_parameter_logging.rb (86%) rename spec/fixtures/{rails52 => rails60}/config/initializers/inflections.rb (95%) rename spec/fixtures/{rails52 => rails60}/config/initializers/mime_types.rb (83%) rename spec/fixtures/{rails52 => rails60}/config/initializers/wrap_parameters.rb (94%) rename spec/fixtures/{rails51 => rails60}/config/locales/en.yml (93%) rename spec/fixtures/{rails52 => rails60}/config/puma.rb (74%) create mode 100644 spec/fixtures/rails60/config/routes.rb rename spec/fixtures/{rails51/db/migrate/20181024130108_create_users.rb => rails60/db/migrate/20210325101904_create_users.rb} (56%) create mode 100644 spec/fixtures/rails60/db/schema.rb rename spec/fixtures/{rails52 => rails60}/db/seeds.rb (92%) rename spec/fixtures/{rails51/app/models/concerns => rails60/lib/assets}/.keep (100%) rename spec/fixtures/{rails51/lib/assets => rails60/lib/tasks}/.keep (100%) rename spec/fixtures/{rails51/lib/tasks => rails60/log}/.keep (100%) create mode 100644 spec/fixtures/rails60/package.json rename spec/fixtures/{rails51 => rails60}/public/404.html (100%) rename spec/fixtures/{rails51 => rails60}/public/422.html (100%) rename spec/fixtures/{rails51 => rails60}/public/500.html (100%) rename spec/fixtures/{rails51 => rails60}/public/apple-touch-icon-precomposed.png (100%) rename spec/fixtures/{rails51 => rails60}/public/apple-touch-icon.png (100%) rename spec/fixtures/{rails51 => rails60}/public/favicon.ico (100%) create mode 100644 spec/fixtures/rails60/public/robots.txt rename spec/fixtures/{rails52 => rails60}/test/application_system_test_case.rb (83%) create mode 100644 spec/fixtures/rails60/test/channels/application_cable/connection_test.rb rename spec/fixtures/{rails51/log => rails60/test/controllers}/.keep (100%) rename spec/fixtures/{rails51/test/controllers => rails60/test/fixtures}/.keep (100%) rename spec/fixtures/{rails51/test/fixtures => rails60/test/fixtures/files}/.keep (100%) create mode 100644 spec/fixtures/rails60/test/fixtures/users.yml rename spec/fixtures/{rails51/test/fixtures/files => rails60/test/helpers}/.keep (100%) rename spec/fixtures/{rails51/test/helpers => rails60/test/integration}/.keep (100%) rename spec/fixtures/{rails51/test/integration => rails60/test/mailers}/.keep (100%) rename spec/fixtures/{rails51/test/mailers => rails60/test/models}/.keep (100%) create mode 100644 spec/fixtures/rails60/test/models/user_test.rb rename spec/fixtures/{rails51/test/models => rails60/test/system}/.keep (100%) rename spec/fixtures/{rails52 => rails60}/test/test_helper.rb (90%) rename spec/fixtures/{rails51/test/system => rails60/vendor}/.keep (100%) create mode 100644 spec/fixtures/rails61/.gitattributes rename spec/fixtures/{rails51 => rails61}/.gitignore (71%) create mode 100644 spec/fixtures/rails61/.ruby-version create mode 100644 spec/fixtures/rails61/Gemfile create mode 100644 spec/fixtures/rails61/Gemfile.lock rename spec/fixtures/{rails52 => rails61}/README.md (100%) rename spec/fixtures/{rails51 => rails61}/Rakefile (73%) rename spec/fixtures/{rails52 => rails61}/app/assets/config/manifest.js (62%) rename spec/fixtures/{rails51/vendor => rails61/app/assets/images}/.keep (100%) rename spec/fixtures/{rails52 => rails61}/app/assets/stylesheets/application.css (100%) rename spec/fixtures/{rails52 => rails61}/app/channels/application_cable/channel.rb (72%) rename spec/fixtures/{rails52 => rails61}/app/channels/application_cable/connection.rb (73%) create mode 100644 spec/fixtures/rails61/app/controllers/application_controller.rb rename spec/fixtures/{rails52/app/assets/images => rails61/app/controllers/concerns}/.keep (100%) create mode 100644 spec/fixtures/rails61/app/helpers/application_helper.rb create mode 100644 spec/fixtures/rails61/app/javascript/channels/consumer.js create mode 100644 spec/fixtures/rails61/app/javascript/channels/index.js create mode 100644 spec/fixtures/rails61/app/javascript/packs/application.js create mode 100644 spec/fixtures/rails61/app/jobs/application_job.rb rename spec/fixtures/{rails51 => rails61}/app/mailers/application_mailer.rb (77%) rename spec/fixtures/{rails51 => rails61}/app/models/application_record.rb (72%) rename spec/fixtures/{rails52/app/assets/javascripts/channels => rails61/app/models/concerns}/.keep (100%) rename spec/fixtures/{rails52 => rails61}/app/models/user.rb (53%) create mode 100644 spec/fixtures/rails61/app/views/layouts/application.html.erb rename spec/fixtures/{rails52 => rails61}/app/views/layouts/mailer.html.erb (100%) rename spec/fixtures/{rails52 => rails61}/app/views/layouts/mailer.text.erb (100%) create mode 100755 spec/fixtures/rails61/bin/rails create mode 100755 spec/fixtures/rails61/bin/rake rename spec/fixtures/{rails51 => rails61}/bin/setup (58%) create mode 100755 spec/fixtures/rails61/bin/yarn rename spec/fixtures/{rails52 => rails61}/config.ru (57%) create mode 100644 spec/fixtures/rails61/config/application.rb create mode 100644 spec/fixtures/rails61/config/boot.rb create mode 100644 spec/fixtures/rails61/config/cable.yml create mode 100644 spec/fixtures/rails61/config/credentials.yml.enc rename spec/fixtures/{rails51 => rails61}/config/database.yml (84%) rename spec/fixtures/{rails52 => rails61}/config/environment.rb (61%) rename spec/fixtures/{rails51 => rails61}/config/environments/development.rb (55%) rename spec/fixtures/{rails51 => rails61}/config/environments/production.rb (57%) rename spec/fixtures/{rails52 => rails61}/config/environments/test.rb (63%) rename spec/fixtures/{rails52 => rails61}/config/initializers/application_controller_renderer.rb (87%) create mode 100644 spec/fixtures/rails61/config/initializers/backtrace_silencers.rb create mode 100644 spec/fixtures/rails61/config/initializers/content_security_policy.rb rename spec/fixtures/{rails52 => rails61}/config/initializers/cookies_serializer.rb (89%) rename spec/fixtures/{rails51 => rails61}/config/initializers/filter_parameter_logging.rb (52%) rename spec/fixtures/{rails51 => rails61}/config/initializers/inflections.rb (95%) rename spec/fixtures/{rails51 => rails61}/config/initializers/mime_types.rb (83%) create mode 100644 spec/fixtures/rails61/config/initializers/permissions_policy.rb rename spec/fixtures/{rails51 => rails61}/config/initializers/wrap_parameters.rb (94%) rename spec/fixtures/{rails52 => rails61}/config/locales/en.yml (93%) create mode 100644 spec/fixtures/rails61/config/puma.rb create mode 100644 spec/fixtures/rails61/config/routes.rb rename spec/fixtures/{rails52/db/migrate/20181024130151_create_users.rb => rails61/db/migrate/20210325101931_create_users.rb} (56%) create mode 100644 spec/fixtures/rails61/db/schema.rb rename spec/fixtures/{rails51 => rails61}/db/seeds.rb (64%) rename spec/fixtures/{rails52/app/controllers/concerns => rails61/lib/assets}/.keep (100%) rename spec/fixtures/{rails52/app/models/concerns => rails61/lib/tasks}/.keep (100%) rename spec/fixtures/{rails52/lib/assets => rails61/log}/.keep (100%) create mode 100644 spec/fixtures/rails61/package.json rename spec/fixtures/{rails52 => rails61}/public/404.html (100%) rename spec/fixtures/{rails52 => rails61}/public/422.html (100%) rename spec/fixtures/{rails52 => rails61}/public/500.html (100%) rename spec/fixtures/{rails52 => rails61}/public/apple-touch-icon-precomposed.png (100%) rename spec/fixtures/{rails52 => rails61}/public/apple-touch-icon.png (100%) rename spec/fixtures/{rails52 => rails61}/public/favicon.ico (100%) create mode 100644 spec/fixtures/rails61/public/robots.txt rename spec/fixtures/{rails51 => rails61}/test/application_system_test_case.rb (83%) create mode 100644 spec/fixtures/rails61/test/channels/application_cable/connection_test.rb rename spec/fixtures/{rails52/lib/tasks => rails61/test/controllers}/.keep (100%) rename spec/fixtures/{rails52/log => rails61/test/fixtures/files}/.keep (100%) create mode 100644 spec/fixtures/rails61/test/fixtures/users.yml rename spec/fixtures/{rails52/storage => rails61/test/helpers}/.keep (100%) rename spec/fixtures/{rails52/test/controllers => rails61/test/integration}/.keep (100%) rename spec/fixtures/{rails52/test/fixtures => rails61/test/mailers}/.keep (100%) rename spec/fixtures/{rails52/test/fixtures/files => rails61/test/models}/.keep (100%) create mode 100644 spec/fixtures/rails61/test/models/user_test.rb rename spec/fixtures/{rails52/test/helpers => rails61/test/system}/.keep (100%) rename spec/fixtures/{rails51 => rails61}/test/test_helper.rb (65%) rename spec/fixtures/{rails52/test/integration => rails61/vendor}/.keep (100%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 44579f9f4..b68b0b662 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,11 +13,11 @@ jobs: strategy: fail-fast: false matrix: - ruby: ['2.7', '2.6', '2.5', '2.4', head, jruby-head] + ruby: ['3.0', '2.7', '2.6', '2.5', head, jruby-head] os: [ubuntu-latest, windows-latest] task: [default] include: - - ruby: '2.4' # lowest supported version + - ruby: '2.5' # lowest supported version os: ubuntu-latest task: rubocop env: diff --git a/.rubocop.yml b/.rubocop.yml index 059edea15..67bb29d84 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,11 +1,14 @@ AllCops: NewCops: enable - TargetRubyVersion: 2.4 + TargetRubyVersion: 2.5 SuggestExtensions: false Exclude: - '**/vendor/bundle/**/*' - 'spec/fixtures/*/db/schema.rb' +Style/FrozenStringLiteralComment: + Enabled: false + Style/StringLiterals: Enabled: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 4187d54cf..968097a1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ - None +### Dependencies + +- Drop ruby 2.4 support. + # Changelog ## v3.5.1 - 2021-03-07 diff --git a/Gemfile.lock b/Gemfile.lock index 44b821a34..8cf57cbda 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,49 +7,54 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (5.2.4.3) + activesupport (6.1.3) concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) ast (2.4.1) builder (3.2.4) bump (0.9.0) colorize (0.8.1) - concurrent-ruby (1.1.6) - cucumber (4.0.0) + concurrent-ruby (1.1.8) + cucumber (4.1.0) builder (~> 3.2, >= 3.2.3) - cucumber-core (~> 7.0, >= 7.0.0) + cucumber-core (~> 7.1, >= 7.1.0) + cucumber-create-meta (~> 1.0.0, >= 1.0.0) cucumber-cucumber-expressions (~> 10.1, >= 10.1.0) - cucumber-gherkin (~> 13.0, >= 13.0.0) - cucumber-html-formatter (~> 6.0, >= 6.0.1) - cucumber-messages (~> 12.1, >= 12.1.1) - cucumber-wire (~> 3.0, >= 3.0.0) - diff-lcs (~> 1.3, >= 1.3) + cucumber-gherkin (~> 14.0, >= 14.0.1) + cucumber-html-formatter (~> 7.0, >= 7.0.0) + cucumber-messages (~> 12.2, >= 12.2.0) + cucumber-wire (~> 3.1, >= 3.1.0) + diff-lcs (~> 1.3, >= 1.3, < 1.4) multi_test (~> 0.1, >= 0.1.2) sys-uname (~> 1.0, >= 1.0.2) - cucumber-core (7.0.0) - cucumber-gherkin (~> 13.0, >= 13.0.0) - cucumber-messages (~> 12.1, >= 12.1.1) + cucumber-core (7.1.0) + cucumber-gherkin (~> 14.0, >= 14.0.1) + cucumber-messages (~> 12.2, >= 12.2.0) cucumber-tag-expressions (~> 2.0, >= 2.0.4) - cucumber-cucumber-expressions (10.2.0) - cucumber-gherkin (13.0.0) - cucumber-messages (~> 12.0, >= 12.0.0) - cucumber-html-formatter (6.0.2) - cucumber-messages (~> 12.1, >= 12.1.1) - cucumber-messages (12.1.1) + cucumber-create-meta (1.0.0) + cucumber-messages (~> 12.2, >= 12.2.0) + sys-uname (~> 1.2, >= 1.2.1) + cucumber-cucumber-expressions (10.3.0) + cucumber-gherkin (14.2.0) + cucumber-messages (~> 12.4, >= 12.4.0) + cucumber-html-formatter (7.2.0) + cucumber-messages (~> 12.4, >= 12.4.0) + cucumber-messages (12.4.0) protobuf-cucumber (~> 3.10, >= 3.10.8) cucumber-tag-expressions (2.0.4) - cucumber-wire (3.0.0) - cucumber-core (~> 7.0, >= 7.0.0) + cucumber-wire (3.1.0) + cucumber-core (~> 7.1, >= 7.1.0) cucumber-cucumber-expressions (~> 10.1, >= 10.1.0) - cucumber-messages (~> 12.1, >= 12.1.1) - cuke_modeler (3.0.0) - cucumber-gherkin (< 14.0) + cucumber-messages (~> 12.2, >= 12.2.0) + cuke_modeler (3.7.0) + cucumber-gherkin (< 18.0) diff-lcs (1.3) - ffi (1.13.1) + ffi (1.15.0) gherkin-ruby (0.3.2) - i18n (1.8.3) + i18n (1.8.9) concurrent-ruby (~> 1.0) json (2.3.0) middleware (0.1.0) @@ -97,15 +102,16 @@ GEM colorize gherkin-ruby (>= 0.3.2) json - sys-uname (1.2.1) - ffi (>= 1.0.0) + sys-uname (1.2.2) + ffi (~> 1.1) test-unit (3.3.6) power_assert - thor (1.0.1) + thor (1.1.0) thread_safe (0.3.6) - tzinfo (1.2.7) - thread_safe (~> 0.1) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) unicode-display_width (2.0.0) + zeitwerk (2.4.2) PLATFORMS ruby @@ -123,4 +129,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 2.1.4 + 2.2.15 diff --git a/lib/parallel_tests.rb b/lib/parallel_tests.rb index 997076e9e..84030f862 100644 --- a/lib/parallel_tests.rb +++ b/lib/parallel_tests.rb @@ -23,16 +23,14 @@ def determine_number_of_processes(count) def with_pid_file Tempfile.open('parallel_tests-pidfile') do |f| - begin - ENV['PARALLEL_PID_FILE'] = f.path - # Pids object should be created before threads will start adding pids to it - # Otherwise we would have to use Mutex to prevent creation of several instances - @pids = pids - yield - ensure - ENV['PARALLEL_PID_FILE'] = nil - @pids = nil - end + ENV['PARALLEL_PID_FILE'] = f.path + # Pids object should be created before threads will start adding pids to it + # Otherwise we would have to use Mutex to prevent creation of several instances + @pids = pids + yield + ensure + ENV['PARALLEL_PID_FILE'] = nil + @pids = nil end end diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 7083bdd53..25f912c9f 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -105,13 +105,11 @@ def reprint_output(result, lockfile) def lock(lockfile) File.open(lockfile) do |lock| - begin - lock.flock File::LOCK_EX - yield - ensure - # This shouldn't be necessary, but appears to be - lock.flock File::LOCK_UN - end + lock.flock File::LOCK_EX + yield + ensure + # This shouldn't be necessary, but appears to be + lock.flock File::LOCK_UN end end @@ -228,12 +226,10 @@ def parse_options!(argv) opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg.lstrip } opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber / spinach") do |type| - begin - @runner = load_runner(type) - rescue NameError, LoadError => e - puts "Runner for `#{type}` type has not been found! (#{e})" - abort - end + @runner = load_runner(type) + rescue NameError, LoadError => e + puts "Runner for `#{type}` type has not been found! (#{e})" + abort end opts.on( "--suffix [PATTERN]", diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 4b329e94f..b6d5f3f9d 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,5 +17,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.4.0' + s.required_ruby_version = '>= 2.5.0' end diff --git a/spec/fixtures/rails51/Gemfile b/spec/fixtures/rails51/Gemfile deleted file mode 100644 index b55c480eb..000000000 --- a/spec/fixtures/rails51/Gemfile +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true -source 'https://rubygems.org' - -gem 'rails', '5.1.6' -gem 'sqlite3' -gem 'tzinfo-data' -gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails51/Gemfile.lock b/spec/fixtures/rails51/Gemfile.lock deleted file mode 100644 index fe7ad4b23..000000000 --- a/spec/fixtures/rails51/Gemfile.lock +++ /dev/null @@ -1,124 +0,0 @@ -PATH - remote: ../../.. - specs: - parallel_tests (3.4.0) - parallel - -GEM - remote: https://rubygems.org/ - specs: - actioncable (5.1.6) - actionpack (= 5.1.6) - nio4r (~> 2.0) - websocket-driver (~> 0.6.1) - actionmailer (5.1.6) - actionpack (= 5.1.6) - actionview (= 5.1.6) - activejob (= 5.1.6) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.1.6) - actionview (= 5.1.6) - activesupport (= 5.1.6) - rack (~> 2.0) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.1.6) - activesupport (= 5.1.6) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.1.6) - activesupport (= 5.1.6) - globalid (>= 0.3.6) - activemodel (5.1.6) - activesupport (= 5.1.6) - activerecord (5.1.6) - activemodel (= 5.1.6) - activesupport (= 5.1.6) - arel (~> 8.0) - activesupport (5.1.6) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - arel (8.0.0) - builder (3.2.3) - concurrent-ruby (1.0.5) - crass (1.0.4) - erubi (1.7.1) - globalid (0.4.1) - activesupport (>= 4.2.0) - i18n (1.1.1) - concurrent-ruby (~> 1.0) - loofah (2.2.2) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) - mini_mime (>= 0.1.1) - method_source (0.9.0) - mini_mime (1.0.1) - mini_portile2 (2.3.0) - minitest (5.11.3) - nio4r (2.3.1) - nokogiri (1.8.5) - mini_portile2 (~> 2.3.0) - parallel (1.20.1) - rack (2.0.5) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.1.6) - actioncable (= 5.1.6) - actionmailer (= 5.1.6) - actionpack (= 5.1.6) - actionview (= 5.1.6) - activejob (= 5.1.6) - activemodel (= 5.1.6) - activerecord (= 5.1.6) - activesupport (= 5.1.6) - bundler (>= 1.3.0) - railties (= 5.1.6) - sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.1.6) - actionpack (= 5.1.6) - activesupport (= 5.1.6) - method_source - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rake (12.3.1) - sprockets (3.7.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - sqlite3 (1.3.13) - thor (0.20.0) - thread_safe (0.3.6) - tzinfo (1.2.5) - thread_safe (~> 0.1) - tzinfo-data (1.2019.3) - tzinfo (>= 1.0.0) - websocket-driver (0.6.5) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) - -PLATFORMS - ruby - -DEPENDENCIES - parallel_tests! - rails (= 5.1.6) - sqlite3 - tzinfo-data - -BUNDLED WITH - 2.1.4 diff --git a/spec/fixtures/rails51/app/assets/javascripts/application.js b/spec/fixtures/rails51/app/assets/javascripts/application.js deleted file mode 100644 index 46b20359f..000000000 --- a/spec/fixtures/rails51/app/assets/javascripts/application.js +++ /dev/null @@ -1,15 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's -// vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. JavaScript code in this file should be added after the last require_* statement. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require rails-ujs -//= require turbolinks -//= require_tree . diff --git a/spec/fixtures/rails51/app/controllers/application_controller.rb b/spec/fixtures/rails51/app/controllers/application_controller.rb deleted file mode 100644 index 6d369f832..000000000 --- a/spec/fixtures/rails51/app/controllers/application_controller.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true -class ApplicationController < ActionController::Base - protect_from_forgery with: :exception -end diff --git a/spec/fixtures/rails51/app/helpers/application_helper.rb b/spec/fixtures/rails51/app/helpers/application_helper.rb deleted file mode 100644 index 71249b93b..000000000 --- a/spec/fixtures/rails51/app/helpers/application_helper.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true -module ApplicationHelper -end diff --git a/spec/fixtures/rails51/app/jobs/application_job.rb b/spec/fixtures/rails51/app/jobs/application_job.rb deleted file mode 100644 index 32fe70b8e..000000000 --- a/spec/fixtures/rails51/app/jobs/application_job.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true -class ApplicationJob < ActiveJob::Base -end diff --git a/spec/fixtures/rails51/app/views/layouts/application.html.erb b/spec/fixtures/rails51/app/views/layouts/application.html.erb deleted file mode 100644 index 3d0d52825..000000000 --- a/spec/fixtures/rails51/app/views/layouts/application.html.erb +++ /dev/null @@ -1,14 +0,0 @@ - - - - Rails51 - <%= csrf_meta_tags %> - - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> - - - - <%= yield %> - - diff --git a/spec/fixtures/rails51/bin/bundle b/spec/fixtures/rails51/bin/bundle deleted file mode 100755 index 74a18868b..000000000 --- a/spec/fixtures/rails51/bin/bundle +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -load Gem.bin_path('bundler', 'bundle') diff --git a/spec/fixtures/rails51/bin/rails b/spec/fixtures/rails51/bin/rails deleted file mode 100755 index dd027b406..000000000 --- a/spec/fixtures/rails51/bin/rails +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' diff --git a/spec/fixtures/rails51/bin/update b/spec/fixtures/rails51/bin/update deleted file mode 100755 index 1594fcbcb..000000000 --- a/spec/fixtures/rails51/bin/update +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -require 'pathname' -require 'fileutils' -include FileUtils # rubocop:disable Style/MixinUsage - -# path to your application root. -APP_ROOT = Pathname.new File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a way to update your development environment automatically. - # Add necessary update steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - puts "\n== Updating database ==" - system! 'bin/rails db:migrate' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end diff --git a/spec/fixtures/rails51/bin/yarn b/spec/fixtures/rails51/bin/yarn deleted file mode 100755 index 0d571d110..000000000 --- a/spec/fixtures/rails51/bin/yarn +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -VENDOR_PATH = File.expand_path('..', __dir__) -Dir.chdir(VENDOR_PATH) do - begin - exec "yarnpkg #{ARGV.join(" ")}" - rescue Errno::ENOENT - warn "Yarn executable was not detected in the system." - warn "Download Yarn at https://yarnpkg.com/en/docs/install" - exit 1 - end -end diff --git a/spec/fixtures/rails51/config/application.rb b/spec/fixtures/rails51/config/application.rb deleted file mode 100644 index 7cec4d3ec..000000000 --- a/spec/fixtures/rails51/config/application.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true -require_relative 'boot' - -require 'rails/all' - -# Require the gems listed in Gemfile, including any gems -# you've limited to :test, :development, or :production. -Bundler.require(*Rails.groups) - -module Rails51 - class Application < Rails::Application - # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.1 - - # Settings in config/environments/* take precedence over those specified here. - # Application configuration should go into files in config/initializers - # -- all .rb files in that directory are automatically loaded. - end -end diff --git a/spec/fixtures/rails51/config/boot.rb b/spec/fixtures/rails51/config/boot.rb deleted file mode 100644 index 9be337a42..000000000 --- a/spec/fixtures/rails51/config/boot.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) - -require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/spec/fixtures/rails51/config/cable.yml b/spec/fixtures/rails51/config/cable.yml deleted file mode 100644 index e40eb09e4..000000000 --- a/spec/fixtures/rails51/config/cable.yml +++ /dev/null @@ -1,10 +0,0 @@ -development: - adapter: async - -test: - adapter: async - -production: - adapter: redis - url: redis://localhost:6379/1 - channel_prefix: rails51_production diff --git a/spec/fixtures/rails51/config/initializers/assets.rb b/spec/fixtures/rails51/config/initializers/assets.rb deleted file mode 100644 index b6970c9e6..000000000 --- a/spec/fixtures/rails51/config/initializers/assets.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' - -# Add additional assets to the asset load path. -# Rails.application.config.assets.paths << Emoji.images_path -# Add Yarn node_modules folder to the asset load path. -Rails.application.config.assets.paths << Rails.root.join('node_modules') - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in the app/assets -# folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb b/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb deleted file mode 100644 index d0f0d3b5d..000000000 --- a/spec/fixtures/rails51/config/initializers/backtrace_silencers.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true -# Be sure to restart your server when you modify this file. - -# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. -# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ } - -# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code. -# Rails.backtrace_cleaner.remove_silencers! diff --git a/spec/fixtures/rails51/config/puma.rb b/spec/fixtures/rails51/config/puma.rb deleted file mode 100644 index 3ea935c19..000000000 --- a/spec/fixtures/rails51/config/puma.rb +++ /dev/null @@ -1,57 +0,0 @@ -# frozen_string_literal: true -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. -# -threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) -threads threads_count, threads_count - -# Specifies the `port` that Puma will listen on to receive requests; default is 3000. -# -port ENV.fetch("PORT", 3000) - -# Specifies the `environment` that Puma will run in. -# -environment ENV.fetch("RAILS_ENV", "development") - -# Specifies the number of `workers` to boot in clustered mode. -# Workers are forked webserver processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). -# -# workers ENV.fetch("WEB_CONCURRENCY") { 2 } - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. If you use this option -# you need to make sure to reconnect any threads in the `on_worker_boot` -# block. -# -# preload_app! - -# If you are preloading your application and using Active Record, it's -# recommended that you close any connections to the database before workers -# are forked to prevent connection leakage. -# -# before_fork do -# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) -# end - -# The code in the `on_worker_boot` will be called if you are using -# clustered mode by specifying a number of `workers`. After each worker -# process is booted, this block will be run. If you are using the `preload_app!` -# option, you will want to use this block to reconnect to any threads -# or connections that may have been created at application boot, as Ruby -# cannot share connections between processes. -# -# on_worker_boot do -# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) -# end -# - -# Allow puma to be restarted by `rails restart` command. -plugin :tmp_restart diff --git a/spec/fixtures/rails51/config/routes.rb b/spec/fixtures/rails51/config/routes.rb deleted file mode 100644 index 6bf1218e2..000000000 --- a/spec/fixtures/rails51/config/routes.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true -Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html -end diff --git a/spec/fixtures/rails51/config/secrets.yml b/spec/fixtures/rails51/config/secrets.yml deleted file mode 100644 index ce38993f6..000000000 --- a/spec/fixtures/rails51/config/secrets.yml +++ /dev/null @@ -1,32 +0,0 @@ -# Be sure to restart your server when you modify this file. - -# Your secret key is used for verifying the integrity of signed cookies. -# If you change this key, all old signed cookies will become invalid! - -# Make sure the secret is at least 30 characters and all random, -# no regular words or you'll be exposed to dictionary attacks. -# You can use `rails secret` to generate a secure secret key. - -# Make sure the secrets in this file are kept private -# if you're sharing your code publicly. - -# Shared secrets are available across all environments. - -# shared: -# api_key: a1B2c3D4e5F6 - -# Environmental secrets are only available for that specific environment. - -development: - secret_key_base: af5bb48e3a90b938d2aeaf8afd214eb048a2914b0e3b6aeb01633048e29fbd36891ecdb3973a14b66544c86e460065fc0b7a5bc945cdc885c1149c7d36c8f764 - -test: - secret_key_base: 46f5f95eca19f28e3c1b8370b070c96fd1f2f62b817fad9e6b51e95944dba1171ea3c3d96e92106ed3f0e59c288ee259b05efbc44632636857aeb40ffe2ece7e - -# Do not keep production secrets in the unencrypted secrets file. -# Instead, either read values from the environment. -# Or, use `bin/rails secrets:setup` to configure encrypted secrets -# and move the `production:` environment over there. - -production: - secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/spec/fixtures/rails51/db/schema.rb b/spec/fixtures/rails51/db/schema.rb deleted file mode 100644 index 8bb85b8f8..000000000 --- a/spec/fixtures/rails51/db/schema.rb +++ /dev/null @@ -1,21 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 20181024130108) do - - create_table "users", force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - -end diff --git a/spec/fixtures/rails51/package.json b/spec/fixtures/rails51/package.json deleted file mode 100644 index 3d33606a0..000000000 --- a/spec/fixtures/rails51/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "rails51", - "private": true, - "dependencies": {} -} diff --git a/spec/fixtures/rails51/public/robots.txt b/spec/fixtures/rails51/public/robots.txt deleted file mode 100644 index 37b576a4a..000000000 --- a/spec/fixtures/rails51/public/robots.txt +++ /dev/null @@ -1 +0,0 @@ -# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/spec/fixtures/rails51/test/fixtures/users.yml b/spec/fixtures/rails51/test/fixtures/users.yml deleted file mode 100644 index 56066c68a..000000000 --- a/spec/fixtures/rails51/test/fixtures/users.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -one: - name: MyString - -two: - name: MyString diff --git a/spec/fixtures/rails51/test/models/user2_test.rb b/spec/fixtures/rails51/test/models/user2_test.rb deleted file mode 100644 index bcebe28c8..000000000 --- a/spec/fixtures/rails51/test/models/user2_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class User2Test < ActiveSupport::TestCase - test "the truth" do - User.create - end -end diff --git a/spec/fixtures/rails51/test/models/user_test.rb b/spec/fixtures/rails51/test/models/user_test.rb deleted file mode 100644 index 045d9e148..000000000 --- a/spec/fixtures/rails51/test/models/user_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class UserTest < ActiveSupport::TestCase - test "the truth" do - User.create - end -end diff --git a/spec/fixtures/rails52/.ruby-version b/spec/fixtures/rails52/.ruby-version deleted file mode 100644 index a4db534a2..000000000 --- a/spec/fixtures/rails52/.ruby-version +++ /dev/null @@ -1 +0,0 @@ -2.5.3 \ No newline at end of file diff --git a/spec/fixtures/rails52/Gemfile b/spec/fixtures/rails52/Gemfile deleted file mode 100644 index 34b52d996..000000000 --- a/spec/fixtures/rails52/Gemfile +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true -source 'https://rubygems.org' - -gem 'rails', '5.2.1' -gem 'sqlite3' -gem 'tzinfo-data' -gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails52/Gemfile.lock b/spec/fixtures/rails52/Gemfile.lock deleted file mode 100644 index 16f228f8a..000000000 --- a/spec/fixtures/rails52/Gemfile.lock +++ /dev/null @@ -1,132 +0,0 @@ -PATH - remote: ../../.. - specs: - parallel_tests (3.4.0) - parallel - -GEM - remote: https://rubygems.org/ - specs: - actioncable (5.2.1) - actionpack (= 5.2.1) - nio4r (~> 2.0) - websocket-driver (>= 0.6.1) - actionmailer (5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 2.0) - actionpack (5.2.1) - actionview (= 5.2.1) - activesupport (= 5.2.1) - rack (~> 2.0) - rack-test (>= 0.6.3) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.1) - activesupport (= 5.2.1) - builder (~> 3.1) - erubi (~> 1.4) - rails-dom-testing (~> 2.0) - rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.1) - activesupport (= 5.2.1) - globalid (>= 0.3.6) - activemodel (5.2.1) - activesupport (= 5.2.1) - activerecord (5.2.1) - activemodel (= 5.2.1) - activesupport (= 5.2.1) - arel (>= 9.0) - activestorage (5.2.1) - actionpack (= 5.2.1) - activerecord (= 5.2.1) - marcel (~> 0.3.1) - activesupport (5.2.1) - concurrent-ruby (~> 1.0, >= 1.0.2) - i18n (>= 0.7, < 2) - minitest (~> 5.1) - tzinfo (~> 1.1) - arel (9.0.0) - builder (3.2.3) - concurrent-ruby (1.0.5) - crass (1.0.4) - erubi (1.7.1) - globalid (0.4.1) - activesupport (>= 4.2.0) - i18n (1.1.1) - concurrent-ruby (~> 1.0) - loofah (2.2.2) - crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) - mini_mime (>= 0.1.1) - marcel (0.3.3) - mimemagic (~> 0.3.2) - method_source (0.9.0) - mimemagic (0.3.2) - mini_mime (1.0.1) - mini_portile2 (2.3.0) - minitest (5.11.3) - nio4r (2.3.1) - nokogiri (1.8.5) - mini_portile2 (~> 2.3.0) - parallel (1.20.1) - rack (2.0.5) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.2.1) - actioncable (= 5.2.1) - actionmailer (= 5.2.1) - actionpack (= 5.2.1) - actionview (= 5.2.1) - activejob (= 5.2.1) - activemodel (= 5.2.1) - activerecord (= 5.2.1) - activestorage (= 5.2.1) - activesupport (= 5.2.1) - bundler (>= 1.3.0) - railties (= 5.2.1) - sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) - nokogiri (>= 1.6) - rails-html-sanitizer (1.0.4) - loofah (~> 2.2, >= 2.2.2) - railties (5.2.1) - actionpack (= 5.2.1) - activesupport (= 5.2.1) - method_source - rake (>= 0.8.7) - thor (>= 0.19.0, < 2.0) - rake (12.3.1) - sprockets (3.7.2) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.1) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - sqlite3 (1.3.13) - thor (0.20.0) - thread_safe (0.3.6) - tzinfo (1.2.5) - thread_safe (~> 0.1) - tzinfo-data (1.2019.3) - tzinfo (>= 1.0.0) - websocket-driver (0.7.0) - websocket-extensions (>= 0.1.0) - websocket-extensions (0.1.3) - -PLATFORMS - ruby - -DEPENDENCIES - parallel_tests! - rails (= 5.2.1) - sqlite3 - tzinfo-data - -BUNDLED WITH - 2.1.4 diff --git a/spec/fixtures/rails52/app/assets/javascripts/application.js b/spec/fixtures/rails52/app/assets/javascripts/application.js deleted file mode 100644 index 82e6f0f6c..000000000 --- a/spec/fixtures/rails52/app/assets/javascripts/application.js +++ /dev/null @@ -1,16 +0,0 @@ -// This is a manifest file that'll be compiled into application.js, which will include all the files -// listed below. -// -// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, or any plugin's -// vendor/assets/javascripts directory can be referenced here using a relative path. -// -// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the -// compiled file. JavaScript code in this file should be added after the last require_* statement. -// -// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details -// about supported directives. -// -//= require rails-ujs -//= require activestorage -//= require turbolinks -//= require_tree . diff --git a/spec/fixtures/rails52/app/assets/javascripts/cable.js b/spec/fixtures/rails52/app/assets/javascripts/cable.js deleted file mode 100644 index 739aa5f02..000000000 --- a/spec/fixtures/rails52/app/assets/javascripts/cable.js +++ /dev/null @@ -1,13 +0,0 @@ -// Action Cable provides the framework to deal with WebSockets in Rails. -// You can generate new channels where WebSocket features live using the `rails generate channel` command. -// -//= require action_cable -//= require_self -//= require_tree ./channels - -(function() { - this.App || (this.App = {}); - - App.cable = ActionCable.createConsumer(); - -}).call(this); diff --git a/spec/fixtures/rails52/app/helpers/application_helper.rb b/spec/fixtures/rails52/app/helpers/application_helper.rb deleted file mode 100644 index 71249b93b..000000000 --- a/spec/fixtures/rails52/app/helpers/application_helper.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true -module ApplicationHelper -end diff --git a/spec/fixtures/rails52/app/jobs/application_job.rb b/spec/fixtures/rails52/app/jobs/application_job.rb deleted file mode 100644 index 32fe70b8e..000000000 --- a/spec/fixtures/rails52/app/jobs/application_job.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: true -class ApplicationJob < ActiveJob::Base -end diff --git a/spec/fixtures/rails52/app/views/layouts/application.html.erb b/spec/fixtures/rails52/app/views/layouts/application.html.erb deleted file mode 100644 index 318a1529a..000000000 --- a/spec/fixtures/rails52/app/views/layouts/application.html.erb +++ /dev/null @@ -1,15 +0,0 @@ - - - - Rails52 - <%= csrf_meta_tags %> - <%= csp_meta_tag %> - - <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> - <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %> - - - - <%= yield %> - - diff --git a/spec/fixtures/rails52/bin/bundle b/spec/fixtures/rails52/bin/bundle deleted file mode 100755 index 74a18868b..000000000 --- a/spec/fixtures/rails52/bin/bundle +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -load Gem.bin_path('bundler', 'bundle') diff --git a/spec/fixtures/rails52/bin/rake b/spec/fixtures/rails52/bin/rake deleted file mode 100755 index 609af7470..000000000 --- a/spec/fixtures/rails52/bin/rake +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -require_relative '../config/boot' -require 'rake' -Rake.application.run diff --git a/spec/fixtures/rails52/bin/update b/spec/fixtures/rails52/bin/update deleted file mode 100755 index 4cc53024e..000000000 --- a/spec/fixtures/rails52/bin/update +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -require 'fileutils' -include FileUtils # rubocop:disable Style/MixinUsage - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a way to update your development environment automatically. - # Add necessary update steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - # Install JavaScript dependencies if using Yarn - # system('bin/yarn') - - puts "\n== Updating database ==" - system! 'bin/rails db:migrate' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end diff --git a/spec/fixtures/rails52/bin/yarn b/spec/fixtures/rails52/bin/yarn deleted file mode 100755 index d5619dbd6..000000000 --- a/spec/fixtures/rails52/bin/yarn +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env ruby -# frozen_string_literal: true -APP_ROOT = File.expand_path('..', __dir__) -Dir.chdir(APP_ROOT) do - begin - exec "yarnpkg", *ARGV - rescue Errno::ENOENT - warn "Yarn executable was not detected in the system." - warn "Download Yarn at https://yarnpkg.com/en/docs/install" - exit 1 - end -end diff --git a/spec/fixtures/rails52/config/credentials.yml.enc b/spec/fixtures/rails52/config/credentials.yml.enc deleted file mode 100644 index a8d1858af..000000000 --- a/spec/fixtures/rails52/config/credentials.yml.enc +++ /dev/null @@ -1 +0,0 @@ -56tStLZJJzxR8hQ5NcvwzMWuLGRc8y4/pk141nnv0DdNlD8uQRYIsm/YkpxJyoU3tyY1/IcdqmVU0JAUkvvaW1+RrwjtF7O0S2YSGxQ/HW0qzIFMt3BmkP3ECmdDGi5nXhRDMUNrQZdQs+aPhRhQB8eKklFeuC8ayKNPWgAzs2UW96TW0/kTHCIi4VNje3fjEPAF6yDXDUBr6RKUXFEJdWMMxSYr1CDEQKOQHj8HET+fRQG08qvpN7BDsv4Uvg8ijO4i1wTabfM1PRGbtw1wFeZzDvOIz58JCqA1ZbgsY4eDGZgpDVx+TT2fuFsG8utWoj7zgsNdNJoYNWsKD/Q1uEgJTDHq2FEdkesJ8gT5XhcfvkuUcwQloEGazeiTQKQ6qGmK8ieZf8HyRGicNsC3/rbHVKk2Zovipvlx--LQpkmklfLtm6EHJQ--I2YLoXnjDTX72UEv1cgHog== \ No newline at end of file diff --git a/spec/fixtures/rails52/config/initializers/assets.rb b/spec/fixtures/rails52/config/initializers/assets.rb deleted file mode 100644 index b6970c9e6..000000000 --- a/spec/fixtures/rails52/config/initializers/assets.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: true -# Be sure to restart your server when you modify this file. - -# Version of your assets, change this if you want to expire all your assets. -Rails.application.config.assets.version = '1.0' - -# Add additional assets to the asset load path. -# Rails.application.config.assets.paths << Emoji.images_path -# Add Yarn node_modules folder to the asset load path. -Rails.application.config.assets.paths << Rails.root.join('node_modules') - -# Precompile additional assets. -# application.js, application.css, and all non-JS/CSS in the app/assets -# folder are already added. -# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/spec/fixtures/rails52/config/routes.rb b/spec/fixtures/rails52/config/routes.rb deleted file mode 100644 index 6bf1218e2..000000000 --- a/spec/fixtures/rails52/config/routes.rb +++ /dev/null @@ -1,4 +0,0 @@ -# frozen_string_literal: true -Rails.application.routes.draw do - # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html -end diff --git a/spec/fixtures/rails52/config/storage.yml b/spec/fixtures/rails52/config/storage.yml deleted file mode 100644 index d32f76e8f..000000000 --- a/spec/fixtures/rails52/config/storage.yml +++ /dev/null @@ -1,34 +0,0 @@ -test: - service: Disk - root: <%= Rails.root.join("tmp/storage") %> - -local: - service: Disk - root: <%= Rails.root.join("storage") %> - -# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) -# amazon: -# service: S3 -# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> -# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> -# region: us-east-1 -# bucket: your_own_bucket - -# Remember not to checkin your GCS keyfile to a repository -# google: -# service: GCS -# project: your_project -# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> -# bucket: your_own_bucket - -# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) -# microsoft: -# service: AzureStorage -# storage_account_name: your_account_name -# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> -# container: your_container_name - -# mirror: -# service: Mirror -# primary: local -# mirrors: [ amazon, google, microsoft ] diff --git a/spec/fixtures/rails52/db/schema.rb b/spec/fixtures/rails52/db/schema.rb deleted file mode 100644 index 733245696..000000000 --- a/spec/fixtures/rails52/db/schema.rb +++ /dev/null @@ -1,21 +0,0 @@ -# This file is auto-generated from the current state of the database. Instead -# of editing this file, please use the migrations feature of Active Record to -# incrementally modify your database, and then regenerate this schema definition. -# -# Note that this schema.rb definition is the authoritative source for your -# database schema. If you need to create the application database on another -# system, you should be using db:schema:load, not running all the migrations -# from scratch. The latter is a flawed and unsustainable approach (the more migrations -# you'll amass, the slower it'll run and the greater likelihood for issues). -# -# It's strongly recommended that you check this file into your version control system. - -ActiveRecord::Schema.define(version: 2018_10_24_130151) do - - create_table "users", force: :cascade do |t| - t.string "name" - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - end - -end diff --git a/spec/fixtures/rails52/package.json b/spec/fixtures/rails52/package.json deleted file mode 100644 index 3a0a0d7c3..000000000 --- a/spec/fixtures/rails52/package.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "rails52", - "private": true, - "dependencies": {} -} diff --git a/spec/fixtures/rails52/public/robots.txt b/spec/fixtures/rails52/public/robots.txt deleted file mode 100644 index 37b576a4a..000000000 --- a/spec/fixtures/rails52/public/robots.txt +++ /dev/null @@ -1 +0,0 @@ -# See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/spec/fixtures/rails52/test/fixtures/users.yml b/spec/fixtures/rails52/test/fixtures/users.yml deleted file mode 100644 index 56066c68a..000000000 --- a/spec/fixtures/rails52/test/fixtures/users.yml +++ /dev/null @@ -1,7 +0,0 @@ -# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html - -one: - name: MyString - -two: - name: MyString diff --git a/spec/fixtures/rails52/test/mailers/.keep b/spec/fixtures/rails52/test/mailers/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/rails52/test/models/.keep b/spec/fixtures/rails52/test/models/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/rails52/test/models/user2_test.rb b/spec/fixtures/rails52/test/models/user2_test.rb deleted file mode 100644 index bcebe28c8..000000000 --- a/spec/fixtures/rails52/test/models/user2_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class User2Test < ActiveSupport::TestCase - test "the truth" do - User.create - end -end diff --git a/spec/fixtures/rails52/test/models/user_test.rb b/spec/fixtures/rails52/test/models/user_test.rb deleted file mode 100644 index 045d9e148..000000000 --- a/spec/fixtures/rails52/test/models/user_test.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true -require 'test_helper' - -class UserTest < ActiveSupport::TestCase - test "the truth" do - User.create - end -end diff --git a/spec/fixtures/rails52/test/system/.keep b/spec/fixtures/rails52/test/system/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/rails52/vendor/.keep b/spec/fixtures/rails52/vendor/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/spec/fixtures/rails52/.gitignore b/spec/fixtures/rails60/.gitignore similarity index 85% rename from spec/fixtures/rails52/.gitignore rename to spec/fixtures/rails60/.gitignore index 81452db92..3fd725c86 100644 --- a/spec/fixtures/rails52/.gitignore +++ b/spec/fixtures/rails60/.gitignore @@ -10,6 +10,7 @@ # Ignore the default SQLite database. /db/*.sqlite3 /db/*.sqlite3-journal +/db/*.sqlite3-* # Ignore all logfiles and tempfiles. /log/* @@ -17,12 +18,11 @@ !/log/.keep !/tmp/.keep -# Ignore uploaded files in development -/storage/* -!/storage/.keep +# Ignore pidfiles, but keep the directory. +/tmp/pids/* +!/tmp/pids/ +!/tmp/pids/.keep -/node_modules -/yarn-error.log /public/assets .byebug_history diff --git a/spec/fixtures/rails60/.ruby-version b/spec/fixtures/rails60/.ruby-version new file mode 100644 index 000000000..4a36342fc --- /dev/null +++ b/spec/fixtures/rails60/.ruby-version @@ -0,0 +1 @@ +3.0.0 diff --git a/spec/fixtures/rails60/Gemfile b/spec/fixtures/rails60/Gemfile new file mode 100644 index 000000000..75e568a27 --- /dev/null +++ b/spec/fixtures/rails60/Gemfile @@ -0,0 +1,19 @@ +# frozen_string_literal: true +source 'https://rubygems.org' + +rails_version = '6.0.3' + +gem 'actioncable', rails_version +gem 'actionmailer', rails_version +gem 'actionpack', rails_version +gem 'actionview', rails_version +gem 'activejob', rails_version +gem 'activemodel', rails_version +gem 'activerecord', rails_version +gem 'activesupport', rails_version +gem 'railties', rails_version +gem 'sprockets-rails' + +gem 'sqlite3' +gem 'tzinfo-data' +gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock new file mode 100644 index 000000000..e27df67c7 --- /dev/null +++ b/spec/fixtures/rails60/Gemfile.lock @@ -0,0 +1,124 @@ +PATH + remote: ../../.. + specs: + parallel_tests (3.5.2) + parallel + +GEM + remote: https://rubygems.org/ + specs: + actioncable (6.0.3) + actionpack (= 6.0.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (6.0.3) + actionpack (= 6.0.3) + actionview (= 6.0.3) + activejob (= 6.0.3) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (6.0.3) + actionview (= 6.0.3) + activesupport (= 6.0.3) + rack (~> 2.0, >= 2.0.8) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actionview (6.0.3) + activesupport (= 6.0.3) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.0.3) + activesupport (= 6.0.3) + globalid (>= 0.3.6) + activemodel (6.0.3) + activesupport (= 6.0.3) + activerecord (6.0.3) + activemodel (= 6.0.3) + activesupport (= 6.0.3) + activesupport (6.0.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 0.7, < 2) + minitest (~> 5.1) + tzinfo (~> 1.1) + zeitwerk (~> 2.2, >= 2.2.2) + builder (3.2.4) + concurrent-ruby (1.1.8) + crass (1.0.6) + erubi (1.10.0) + globalid (0.4.2) + activesupport (>= 4.2.0) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + loofah (2.9.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + method_source (1.0.0) + mini_mime (1.0.2) + minitest (5.14.4) + nio4r (2.5.7) + nokogiri (1.11.2-x64-mingw32) + racc (~> 1.4) + nokogiri (1.11.2-x86_64-linux) + racc (~> 1.4) + parallel (1.20.1) + racc (1.5.2) + rack (2.2.3) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (6.0.3) + actionpack (= 6.0.3) + activesupport (= 6.0.3) + method_source + rake (>= 0.8.7) + thor (>= 0.20.3, < 2.0) + rake (13.0.3) + sprockets (4.0.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.2) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.4.2) + thor (1.1.0) + thread_safe (0.3.6) + tzinfo (1.2.9) + thread_safe (~> 0.1) + tzinfo-data (1.2021.1) + tzinfo (>= 1.0.0) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.4.2) + +PLATFORMS + x64-mingw32 + x86_64-linux + +DEPENDENCIES + actioncable (= 6.0.3) + actionmailer (= 6.0.3) + actionpack (= 6.0.3) + actionview (= 6.0.3) + activejob (= 6.0.3) + activemodel (= 6.0.3) + activerecord (= 6.0.3) + activesupport (= 6.0.3) + parallel_tests! + railties (= 6.0.3) + sprockets-rails + sqlite3 + tzinfo-data + +BUNDLED WITH + 2.2.15 diff --git a/spec/fixtures/rails51/README.md b/spec/fixtures/rails60/README.md similarity index 100% rename from spec/fixtures/rails51/README.md rename to spec/fixtures/rails60/README.md diff --git a/spec/fixtures/rails52/Rakefile b/spec/fixtures/rails60/Rakefile similarity index 88% rename from spec/fixtures/rails52/Rakefile rename to spec/fixtures/rails60/Rakefile index 84f2bc394..e85f91391 100644 --- a/spec/fixtures/rails52/Rakefile +++ b/spec/fixtures/rails60/Rakefile @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. diff --git a/spec/fixtures/rails51/app/assets/config/manifest.js b/spec/fixtures/rails60/app/assets/config/manifest.js similarity index 62% rename from spec/fixtures/rails51/app/assets/config/manifest.js rename to spec/fixtures/rails60/app/assets/config/manifest.js index b16e53d6d..591819335 100644 --- a/spec/fixtures/rails51/app/assets/config/manifest.js +++ b/spec/fixtures/rails60/app/assets/config/manifest.js @@ -1,3 +1,2 @@ //= link_tree ../images -//= link_directory ../javascripts .js //= link_directory ../stylesheets .css diff --git a/spec/fixtures/rails51/app/assets/images/.keep b/spec/fixtures/rails60/app/assets/images/.keep similarity index 100% rename from spec/fixtures/rails51/app/assets/images/.keep rename to spec/fixtures/rails60/app/assets/images/.keep diff --git a/spec/fixtures/rails51/app/assets/stylesheets/application.css b/spec/fixtures/rails60/app/assets/stylesheets/application.css similarity index 100% rename from spec/fixtures/rails51/app/assets/stylesheets/application.css rename to spec/fixtures/rails60/app/assets/stylesheets/application.css diff --git a/spec/fixtures/rails51/app/channels/application_cable/channel.rb b/spec/fixtures/rails60/app/channels/application_cable/channel.rb similarity index 72% rename from spec/fixtures/rails51/app/channels/application_cable/channel.rb rename to spec/fixtures/rails60/app/channels/application_cable/channel.rb index 51e3e936b..d67269728 100644 --- a/spec/fixtures/rails51/app/channels/application_cable/channel.rb +++ b/spec/fixtures/rails60/app/channels/application_cable/channel.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/spec/fixtures/rails51/app/channels/application_cable/connection.rb b/spec/fixtures/rails60/app/channels/application_cable/connection.rb similarity index 73% rename from spec/fixtures/rails51/app/channels/application_cable/connection.rb rename to spec/fixtures/rails60/app/channels/application_cable/connection.rb index fa70319da..0ff5442f4 100644 --- a/spec/fixtures/rails51/app/channels/application_cable/connection.rb +++ b/spec/fixtures/rails60/app/channels/application_cable/connection.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/spec/fixtures/rails52/app/controllers/application_controller.rb b/spec/fixtures/rails60/app/controllers/application_controller.rb similarity index 65% rename from spec/fixtures/rails52/app/controllers/application_controller.rb rename to spec/fixtures/rails60/app/controllers/application_controller.rb index e0491348f..09705d12a 100644 --- a/spec/fixtures/rails52/app/controllers/application_controller.rb +++ b/spec/fixtures/rails60/app/controllers/application_controller.rb @@ -1,3 +1,2 @@ -# frozen_string_literal: true class ApplicationController < ActionController::Base end diff --git a/spec/fixtures/rails51/app/assets/javascripts/channels/.keep b/spec/fixtures/rails60/app/controllers/concerns/.keep similarity index 100% rename from spec/fixtures/rails51/app/assets/javascripts/channels/.keep rename to spec/fixtures/rails60/app/controllers/concerns/.keep diff --git a/spec/fixtures/rails60/app/helpers/application_helper.rb b/spec/fixtures/rails60/app/helpers/application_helper.rb new file mode 100644 index 000000000..de6be7945 --- /dev/null +++ b/spec/fixtures/rails60/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/spec/fixtures/rails51/app/assets/javascripts/cable.js b/spec/fixtures/rails60/app/javascript/channels/consumer.js similarity index 50% rename from spec/fixtures/rails51/app/assets/javascripts/cable.js rename to spec/fixtures/rails60/app/javascript/channels/consumer.js index 739aa5f02..0eceb59b1 100644 --- a/spec/fixtures/rails51/app/assets/javascripts/cable.js +++ b/spec/fixtures/rails60/app/javascript/channels/consumer.js @@ -1,13 +1,6 @@ // Action Cable provides the framework to deal with WebSockets in Rails. // You can generate new channels where WebSocket features live using the `rails generate channel` command. -// -//= require action_cable -//= require_self -//= require_tree ./channels -(function() { - this.App || (this.App = {}); +import { createConsumer } from "@rails/actioncable" - App.cable = ActionCable.createConsumer(); - -}).call(this); +export default createConsumer() diff --git a/spec/fixtures/rails60/app/javascript/channels/index.js b/spec/fixtures/rails60/app/javascript/channels/index.js new file mode 100644 index 000000000..0cfcf7491 --- /dev/null +++ b/spec/fixtures/rails60/app/javascript/channels/index.js @@ -0,0 +1,5 @@ +// Load all the channels within this directory and all subdirectories. +// Channel files must be named *_channel.js. + +const channels = require.context('.', true, /_channel\.js$/) +channels.keys().forEach(channels) diff --git a/spec/fixtures/rails60/app/javascript/packs/application.js b/spec/fixtures/rails60/app/javascript/packs/application.js new file mode 100644 index 000000000..28d74208c --- /dev/null +++ b/spec/fixtures/rails60/app/javascript/packs/application.js @@ -0,0 +1,16 @@ +// This file is automatically compiled by Webpack, along with any other files +// present in this directory. You're encouraged to place your actual application logic in +// a relevant structure within app/javascript and only use these pack files to reference +// that code so it'll be compiled. + +require("@rails/ujs").start() +require("turbolinks").start() +require("channels") + + +// Uncomment to copy all static images under ../images to the output folder and reference +// them with the image_pack_tag helper in views (e.g <%= image_pack_tag 'rails.png' %>) +// or the `imagePath` JavaScript helper below. +// +// const images = require.context('../images', true) +// const imagePath = (name) => images(name, true) diff --git a/spec/fixtures/rails60/app/jobs/application_job.rb b/spec/fixtures/rails60/app/jobs/application_job.rb new file mode 100644 index 000000000..d394c3d10 --- /dev/null +++ b/spec/fixtures/rails60/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/spec/fixtures/rails52/app/mailers/application_mailer.rb b/spec/fixtures/rails60/app/mailers/application_mailer.rb similarity index 77% rename from spec/fixtures/rails52/app/mailers/application_mailer.rb rename to spec/fixtures/rails60/app/mailers/application_mailer.rb index 24289009a..286b2239d 100644 --- a/spec/fixtures/rails52/app/mailers/application_mailer.rb +++ b/spec/fixtures/rails60/app/mailers/application_mailer.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' diff --git a/spec/fixtures/rails52/app/models/application_record.rb b/spec/fixtures/rails60/app/models/application_record.rb similarity index 72% rename from spec/fixtures/rails52/app/models/application_record.rb rename to spec/fixtures/rails60/app/models/application_record.rb index 767a072b5..10a4cba84 100644 --- a/spec/fixtures/rails52/app/models/application_record.rb +++ b/spec/fixtures/rails60/app/models/application_record.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end diff --git a/spec/fixtures/rails51/app/controllers/concerns/.keep b/spec/fixtures/rails60/app/models/concerns/.keep similarity index 100% rename from spec/fixtures/rails51/app/controllers/concerns/.keep rename to spec/fixtures/rails60/app/models/concerns/.keep diff --git a/spec/fixtures/rails51/app/models/user.rb b/spec/fixtures/rails60/app/models/user.rb similarity index 53% rename from spec/fixtures/rails51/app/models/user.rb rename to spec/fixtures/rails60/app/models/user.rb index b161db0c3..379658a50 100644 --- a/spec/fixtures/rails51/app/models/user.rb +++ b/spec/fixtures/rails60/app/models/user.rb @@ -1,3 +1,2 @@ -# frozen_string_literal: true class User < ApplicationRecord end diff --git a/spec/fixtures/rails60/app/views/layouts/application.html.erb b/spec/fixtures/rails60/app/views/layouts/application.html.erb new file mode 100644 index 000000000..60ee8159f --- /dev/null +++ b/spec/fixtures/rails60/app/views/layouts/application.html.erb @@ -0,0 +1,15 @@ + + + + Rails60 + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> + + + + <%= yield %> + + diff --git a/spec/fixtures/rails51/app/views/layouts/mailer.html.erb b/spec/fixtures/rails60/app/views/layouts/mailer.html.erb similarity index 100% rename from spec/fixtures/rails51/app/views/layouts/mailer.html.erb rename to spec/fixtures/rails60/app/views/layouts/mailer.html.erb diff --git a/spec/fixtures/rails51/app/views/layouts/mailer.text.erb b/spec/fixtures/rails60/app/views/layouts/mailer.text.erb similarity index 100% rename from spec/fixtures/rails51/app/views/layouts/mailer.text.erb rename to spec/fixtures/rails60/app/views/layouts/mailer.text.erb diff --git a/spec/fixtures/rails52/bin/rails b/spec/fixtures/rails60/bin/rails similarity index 82% rename from spec/fixtures/rails52/bin/rails rename to spec/fixtures/rails60/bin/rails index dd027b406..073966023 100755 --- a/spec/fixtures/rails52/bin/rails +++ b/spec/fixtures/rails60/bin/rails @@ -1,5 +1,4 @@ #!/usr/bin/env ruby -# frozen_string_literal: true APP_PATH = File.expand_path('../config/application', __dir__) require_relative '../config/boot' require 'rails/commands' diff --git a/spec/fixtures/rails51/bin/rake b/spec/fixtures/rails60/bin/rake similarity index 75% rename from spec/fixtures/rails51/bin/rake rename to spec/fixtures/rails60/bin/rake index 609af7470..17240489f 100755 --- a/spec/fixtures/rails51/bin/rake +++ b/spec/fixtures/rails60/bin/rake @@ -1,5 +1,4 @@ #!/usr/bin/env ruby -# frozen_string_literal: true require_relative '../config/boot' require 'rake' Rake.application.run diff --git a/spec/fixtures/rails52/bin/setup b/spec/fixtures/rails60/bin/setup similarity index 67% rename from spec/fixtures/rails52/bin/setup rename to spec/fixtures/rails60/bin/setup index e876cef46..5853b5ea8 100755 --- a/spec/fixtures/rails52/bin/setup +++ b/spec/fixtures/rails60/bin/setup @@ -1,7 +1,5 @@ #!/usr/bin/env ruby -# frozen_string_literal: true require 'fileutils' -include FileUtils # rubocop:disable Style/MixinUsage # path to your application root. APP_ROOT = File.expand_path('..', __dir__) @@ -10,24 +8,25 @@ def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end -chdir APP_ROOT do - # This script is a starting point to setup your application. +FileUtils.chdir APP_ROOT do + # This script is a way to setup or update your development environment automatically. + # This script is idempotent, so that you can run it at anytime and get an expectable outcome. # Add necessary setup steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') - # Install JavaScript dependencies if using Yarn + # Install JavaScript dependencies # system('bin/yarn') # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' + # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system! 'bin/rails db:setup' + system! 'bin/rails db:prepare' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' diff --git a/spec/fixtures/rails60/bin/yarn b/spec/fixtures/rails60/bin/yarn new file mode 100755 index 000000000..b24854dce --- /dev/null +++ b/spec/fixtures/rails60/bin/yarn @@ -0,0 +1,9 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + exec "yarnpkg", *ARGV +rescue Errno::ENOENT + warn "Yarn executable was not detected in the system." + warn "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 +end diff --git a/spec/fixtures/rails51/config.ru b/spec/fixtures/rails60/config.ru similarity index 81% rename from spec/fixtures/rails51/config.ru rename to spec/fixtures/rails60/config.ru index 7eae2644f..f7ba0b527 100644 --- a/spec/fixtures/rails51/config.ru +++ b/spec/fixtures/rails60/config.ru @@ -1,4 +1,3 @@ -# frozen_string_literal: true # This file is used by Rack-based servers to start the application. require_relative 'config/environment' diff --git a/spec/fixtures/rails52/config/application.rb b/spec/fixtures/rails60/config/application.rb similarity index 55% rename from spec/fixtures/rails52/config/application.rb rename to spec/fixtures/rails60/config/application.rb index 5cccc17df..c596e99c8 100644 --- a/spec/fixtures/rails52/config/application.rb +++ b/spec/fixtures/rails60/config/application.rb @@ -1,16 +1,28 @@ -# frozen_string_literal: true require_relative 'boot' -require 'rails/all' +require "rails" +# Pick the frameworks you want: +require "active_model/railtie" +require "active_job/railtie" +require "active_record/railtie" +# require "active_storage/engine" +require "action_controller/railtie" +require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" +require "action_view/railtie" +require "action_cable/engine" +# require "sprockets/railtie" +require "rails/test_unit/railtie" # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. Bundler.require(*Rails.groups) -module Rails52 +module Rails60 class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.2 + config.load_defaults 6.0 # Settings in config/environments/* take precedence over those specified here. # Application configuration can go into files in config/initializers diff --git a/spec/fixtures/rails52/config/boot.rb b/spec/fixtures/rails60/config/boot.rb similarity index 81% rename from spec/fixtures/rails52/config/boot.rb rename to spec/fixtures/rails60/config/boot.rb index 9be337a42..30f5120df 100644 --- a/spec/fixtures/rails52/config/boot.rb +++ b/spec/fixtures/rails60/config/boot.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) require 'bundler/setup' # Set up gems listed in the Gemfile. diff --git a/spec/fixtures/rails52/config/cable.yml b/spec/fixtures/rails60/config/cable.yml similarity index 71% rename from spec/fixtures/rails52/config/cable.yml rename to spec/fixtures/rails60/config/cable.yml index 71933205b..debdc02e7 100644 --- a/spec/fixtures/rails52/config/cable.yml +++ b/spec/fixtures/rails60/config/cable.yml @@ -2,9 +2,9 @@ development: adapter: async test: - adapter: async + adapter: test production: adapter: redis url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> - channel_prefix: rails52_production + channel_prefix: rails60_production diff --git a/spec/fixtures/rails60/config/credentials.yml.enc b/spec/fixtures/rails60/config/credentials.yml.enc new file mode 100644 index 000000000..d7824b920 --- /dev/null +++ b/spec/fixtures/rails60/config/credentials.yml.enc @@ -0,0 +1 @@ +8Y8/F1ai6tfrAft/z0x+qNBnelef8uXXLft0kSsqh8WxI67QWJNyIqK6JBgwUpvQylLyomhY6DlPrOYzi0nj8AnjxYJGdIAKFbQq9PqJ9/0gzHs/QoyWCPLczqTYkKzvUshv+T+XbzRdI0Wz2umoaBVNyRzP7uMwtqVDecZhRgOd35gYlAAqFmfdvjKFeIIpNdTRINqq9W4fQmLuZ45Wk6QbdtU3HMFYJGv5aiFyg+kZQ2M/mGtskGCGIm+i7e8XMBNOJo+oMTRzEC0Z5tktz+epdsKBoJCJ7sJyMs3mUnt1SJc2AG4ORpRymvqSC3lkAiL/zhfynSoxMyktLmwT+vjvaemHjqT4MllkVvFutIZQMuSfYLIUGM5zKWdQvg0pahwYTADQJeCibtIQzWRhaBi79LjniupyG+RN--uZKZ0kvSJ5E4V8zX--AGm8/1XOThzOHhRVZY5jiA== \ No newline at end of file diff --git a/spec/fixtures/rails52/config/database.yml b/spec/fixtures/rails60/config/database.yml similarity index 84% rename from spec/fixtures/rails52/config/database.yml rename to spec/fixtures/rails60/config/database.yml index faeb94565..f90baf882 100644 --- a/spec/fixtures/rails52/config/database.yml +++ b/spec/fixtures/rails60/config/database.yml @@ -1,4 +1,4 @@ -# SQLite version 3.x +# SQLite. Versions 3.8.0 and up are supported. # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile @@ -6,7 +6,7 @@ # default: &default adapter: sqlite3 - pool: 5 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: diff --git a/spec/fixtures/rails51/config/environment.rb b/spec/fixtures/rails60/config/environment.rb similarity index 81% rename from spec/fixtures/rails51/config/environment.rb rename to spec/fixtures/rails60/config/environment.rb index 12ea62f88..426333bb4 100644 --- a/spec/fixtures/rails51/config/environment.rb +++ b/spec/fixtures/rails60/config/environment.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Load the Rails application. require_relative 'application' diff --git a/spec/fixtures/rails52/config/environments/development.rb b/spec/fixtures/rails60/config/environments/development.rb similarity index 78% rename from spec/fixtures/rails52/config/environments/development.rb rename to spec/fixtures/rails60/config/environments/development.rb index a61361fe5..04bd3eeba 100644 --- a/spec/fixtures/rails52/config/environments/development.rb +++ b/spec/fixtures/rails60/config/environments/development.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -17,6 +16,7 @@ # Run rails dev:cache to toggle caching. if Rails.root.join('tmp', 'caching-dev.txt').exist? config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store config.public_file_server.headers = { @@ -28,9 +28,6 @@ config.cache_store = :null_store end - # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = :local - # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false @@ -45,15 +42,7 @@ # Highlight code that triggered database queries in logs. config.active_record.verbose_query_logs = true - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true - - # Suppress logger output for asset requests. - config.assets.quiet = true - - # Raises error for missing translations + # Raises error for missing translations. # config.action_view.raise_on_missing_translations = true # Use an evented file watcher to asynchronously detect changes in source code, diff --git a/spec/fixtures/rails52/config/environments/production.rb b/spec/fixtures/rails60/config/environments/production.rb similarity index 71% rename from spec/fixtures/rails52/config/environments/production.rb rename to spec/fixtures/rails60/config/environments/production.rb index fb40a27a5..08e99c0fe 100644 --- a/spec/fixtures/rails52/config/environments/production.rb +++ b/spec/fixtures/rails60/config/environments/production.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -23,15 +22,6 @@ # Apache or NGINX already handles this. config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - # config.assets.css_compressor = :sass - - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false - - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb - # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.action_controller.asset_host = 'http://assets.example.com' @@ -39,10 +29,7 @@ # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = :local - - # Mount Action Cable outside main process or domain + # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil # config.action_cable.url = 'wss://example.com/cable' # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] @@ -60,9 +47,9 @@ # Use a different cache store in production. # config.cache_store = :mem_cache_store - # Use a real queuing backend for Active Job (and separate queues per environment) + # Use a real queuing backend for Active Job (and separate queues per environment). # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "rails52_#{Rails.env}" + # config.active_job.queue_name_prefix = "rails60_production" config.action_mailer.perform_caching = false @@ -92,4 +79,25 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Inserts middleware to perform automatic connection switching. + # The `database_selector` hash is used to pass options to the DatabaseSelector + # middleware. The `delay` is used to determine how long to wait after a write + # to send a subsequent read to the primary. + # + # The `database_resolver` class is used by the middleware to determine which + # database is appropriate to use based on the time delay. + # + # The `database_resolver_context` class is used by the middleware to set + # timestamps for the last write to the primary. The resolver uses the context + # class timestamps to determine how long to wait before reading from the + # replica. + # + # By default Rails will store a last write timestamp in the session. The + # DatabaseSelector middleware is designed as such you can define your own + # strategy for connection switching and pass that into the middleware through + # these configuration options. + # config.active_record.database_selector = { delay: 2.seconds } + # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver + # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session end diff --git a/spec/fixtures/rails51/config/environments/test.rb b/spec/fixtures/rails60/config/environments/test.rb similarity index 76% rename from spec/fixtures/rails51/config/environments/test.rb rename to spec/fixtures/rails60/config/environments/test.rb index b0c64d7a2..2f62f93cb 100644 --- a/spec/fixtures/rails51/config/environments/test.rb +++ b/spec/fixtures/rails60/config/environments/test.rb @@ -1,11 +1,11 @@ -# frozen_string_literal: true +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application @@ -16,18 +16,20 @@ # Configure public file server for tests with Cache-Control for performance. config.public_file_server.enabled = true config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.seconds.to_i}" + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" } # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false + config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -38,6 +40,6 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Raises error for missing translations + # Raises error for missing translations. # config.action_view.raise_on_missing_translations = true end diff --git a/spec/fixtures/rails51/config/initializers/application_controller_renderer.rb b/spec/fixtures/rails60/config/initializers/application_controller_renderer.rb similarity index 87% rename from spec/fixtures/rails51/config/initializers/application_controller_renderer.rb rename to spec/fixtures/rails60/config/initializers/application_controller_renderer.rb index f4556db39..89d2efab2 100644 --- a/spec/fixtures/rails51/config/initializers/application_controller_renderer.rb +++ b/spec/fixtures/rails60/config/initializers/application_controller_renderer.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/spec/fixtures/rails52/config/initializers/backtrace_silencers.rb b/spec/fixtures/rails60/config/initializers/backtrace_silencers.rb similarity index 93% rename from spec/fixtures/rails52/config/initializers/backtrace_silencers.rb rename to spec/fixtures/rails60/config/initializers/backtrace_silencers.rb index d0f0d3b5d..59385cdf3 100644 --- a/spec/fixtures/rails52/config/initializers/backtrace_silencers.rb +++ b/spec/fixtures/rails60/config/initializers/backtrace_silencers.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. diff --git a/spec/fixtures/rails52/config/initializers/content_security_policy.rb b/spec/fixtures/rails60/config/initializers/content_security_policy.rb similarity index 77% rename from spec/fixtures/rails52/config/initializers/content_security_policy.rb rename to spec/fixtures/rails60/config/initializers/content_security_policy.rb index 497f5667c..35d0f26fc 100644 --- a/spec/fixtures/rails52/config/initializers/content_security_policy.rb +++ b/spec/fixtures/rails60/config/initializers/content_security_policy.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Define an application-wide content security policy @@ -12,6 +11,8 @@ # policy.object_src :none # policy.script_src :self, :https # policy.style_src :self, :https +# # If you are using webpack-dev-server then specify webpack-dev-server host +# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? # # Specify URI for violation reports # # policy.report_uri "/csp-violation-report-endpoint" @@ -20,6 +21,9 @@ # If you are using UJS then enable automatic nonce generation # Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } +# Set the nonce only to specific directives +# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + # Report CSP violations to a specified URI # For further information see the following documentation: # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only diff --git a/spec/fixtures/rails51/config/initializers/cookies_serializer.rb b/spec/fixtures/rails60/config/initializers/cookies_serializer.rb similarity index 89% rename from spec/fixtures/rails51/config/initializers/cookies_serializer.rb rename to spec/fixtures/rails60/config/initializers/cookies_serializer.rb index 2a7295959..5a6a32d37 100644 --- a/spec/fixtures/rails51/config/initializers/cookies_serializer.rb +++ b/spec/fixtures/rails60/config/initializers/cookies_serializer.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb b/spec/fixtures/rails60/config/initializers/filter_parameter_logging.rb similarity index 86% rename from spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb rename to spec/fixtures/rails60/config/initializers/filter_parameter_logging.rb index b7fe1231f..4a994e1e7 100644 --- a/spec/fixtures/rails52/config/initializers/filter_parameter_logging.rb +++ b/spec/fixtures/rails60/config/initializers/filter_parameter_logging.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. diff --git a/spec/fixtures/rails52/config/initializers/inflections.rb b/spec/fixtures/rails60/config/initializers/inflections.rb similarity index 95% rename from spec/fixtures/rails52/config/initializers/inflections.rb rename to spec/fixtures/rails60/config/initializers/inflections.rb index aa7435fbc..ac033bf9d 100644 --- a/spec/fixtures/rails52/config/initializers/inflections.rb +++ b/spec/fixtures/rails60/config/initializers/inflections.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/spec/fixtures/rails52/config/initializers/mime_types.rb b/spec/fixtures/rails60/config/initializers/mime_types.rb similarity index 83% rename from spec/fixtures/rails52/config/initializers/mime_types.rb rename to spec/fixtures/rails60/config/initializers/mime_types.rb index 6e1d16f02..dc1899682 100644 --- a/spec/fixtures/rails52/config/initializers/mime_types.rb +++ b/spec/fixtures/rails60/config/initializers/mime_types.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/spec/fixtures/rails52/config/initializers/wrap_parameters.rb b/spec/fixtures/rails60/config/initializers/wrap_parameters.rb similarity index 94% rename from spec/fixtures/rails52/config/initializers/wrap_parameters.rb rename to spec/fixtures/rails60/config/initializers/wrap_parameters.rb index 18c382529..bbfc3961b 100644 --- a/spec/fixtures/rails52/config/initializers/wrap_parameters.rb +++ b/spec/fixtures/rails60/config/initializers/wrap_parameters.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/spec/fixtures/rails51/config/locales/en.yml b/spec/fixtures/rails60/config/locales/en.yml similarity index 93% rename from spec/fixtures/rails51/config/locales/en.yml rename to spec/fixtures/rails60/config/locales/en.yml index decc5a857..cf9b342d0 100644 --- a/spec/fixtures/rails51/config/locales/en.yml +++ b/spec/fixtures/rails60/config/locales/en.yml @@ -27,7 +27,7 @@ # 'true': 'foo' # # To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. +# available at https://guides.rubyonrails.org/i18n.html. en: hello: "Hello world" diff --git a/spec/fixtures/rails52/config/puma.rb b/spec/fixtures/rails60/config/puma.rb similarity index 74% rename from spec/fixtures/rails52/config/puma.rb rename to spec/fixtures/rails60/config/puma.rb index d05463a09..283e163b1 100644 --- a/spec/fixtures/rails52/config/puma.rb +++ b/spec/fixtures/rails60/config/puma.rb @@ -1,12 +1,12 @@ -# frozen_string_literal: true # Puma can serve each request in a thread from an internal thread pool. # The `threads` method setting takes two numbers: a minimum and maximum. # Any libraries that use thread pools should be configured to match # the maximum value specified for Puma. Default is set to 5 threads for minimum # and maximum; this matches the default thread size of Active Record. # -threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) -threads threads_count, threads_count +max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # @@ -14,10 +14,13 @@ # Specifies the `environment` that Puma will run in. # -environment ENV.fetch("RAILS_ENV", "development") +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } # Specifies the number of `workers` to boot in clustered mode. -# Workers are forked webserver processes. If using threads and workers together +# Workers are forked web server processes. If using threads and workers together # the concurrency of the application would be max `threads` * `workers`. # Workers do not work on JRuby or Windows (both of which do not support # processes). diff --git a/spec/fixtures/rails60/config/routes.rb b/spec/fixtures/rails60/config/routes.rb new file mode 100644 index 000000000..c06383a17 --- /dev/null +++ b/spec/fixtures/rails60/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html +end diff --git a/spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb b/spec/fixtures/rails60/db/migrate/20210325101904_create_users.rb similarity index 56% rename from spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb rename to spec/fixtures/rails60/db/migrate/20210325101904_create_users.rb index 2b5b822b5..6c10d9cad 100644 --- a/spec/fixtures/rails51/db/migrate/20181024130108_create_users.rb +++ b/spec/fixtures/rails60/db/migrate/20210325101904_create_users.rb @@ -1,5 +1,4 @@ -# frozen_string_literal: true -class CreateUsers < ActiveRecord::Migration[5.1] +class CreateUsers < ActiveRecord::Migration[6.0] def change create_table :users do |t| t.string :name diff --git a/spec/fixtures/rails60/db/schema.rb b/spec/fixtures/rails60/db/schema.rb new file mode 100644 index 000000000..a0bb87f84 --- /dev/null +++ b/spec/fixtures/rails60/db/schema.rb @@ -0,0 +1,21 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `rails +# db:schema:load`. When creating a new database, `rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 2021_03_25_101904) do + + create_table "users", force: :cascade do |t| + t.string "name" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + +end diff --git a/spec/fixtures/rails52/db/seeds.rb b/spec/fixtures/rails60/db/seeds.rb similarity index 92% rename from spec/fixtures/rails52/db/seeds.rb rename to spec/fixtures/rails60/db/seeds.rb index 8744e3c59..1beea2acc 100644 --- a/spec/fixtures/rails52/db/seeds.rb +++ b/spec/fixtures/rails60/db/seeds.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # This file should contain all the record creation needed to seed the database with its default values. # The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). # diff --git a/spec/fixtures/rails51/app/models/concerns/.keep b/spec/fixtures/rails60/lib/assets/.keep similarity index 100% rename from spec/fixtures/rails51/app/models/concerns/.keep rename to spec/fixtures/rails60/lib/assets/.keep diff --git a/spec/fixtures/rails51/lib/assets/.keep b/spec/fixtures/rails60/lib/tasks/.keep similarity index 100% rename from spec/fixtures/rails51/lib/assets/.keep rename to spec/fixtures/rails60/lib/tasks/.keep diff --git a/spec/fixtures/rails51/lib/tasks/.keep b/spec/fixtures/rails60/log/.keep similarity index 100% rename from spec/fixtures/rails51/lib/tasks/.keep rename to spec/fixtures/rails60/log/.keep diff --git a/spec/fixtures/rails60/package.json b/spec/fixtures/rails60/package.json new file mode 100644 index 000000000..867b0a0f3 --- /dev/null +++ b/spec/fixtures/rails60/package.json @@ -0,0 +1,10 @@ +{ + "name": "rails60", + "private": true, + "dependencies": { + "@rails/ujs": "^6.0.0", + "turbolinks": "^5.2.0", + "@rails/actioncable": "^6.0.0" + }, + "version": "0.1.0" +} diff --git a/spec/fixtures/rails51/public/404.html b/spec/fixtures/rails60/public/404.html similarity index 100% rename from spec/fixtures/rails51/public/404.html rename to spec/fixtures/rails60/public/404.html diff --git a/spec/fixtures/rails51/public/422.html b/spec/fixtures/rails60/public/422.html similarity index 100% rename from spec/fixtures/rails51/public/422.html rename to spec/fixtures/rails60/public/422.html diff --git a/spec/fixtures/rails51/public/500.html b/spec/fixtures/rails60/public/500.html similarity index 100% rename from spec/fixtures/rails51/public/500.html rename to spec/fixtures/rails60/public/500.html diff --git a/spec/fixtures/rails51/public/apple-touch-icon-precomposed.png b/spec/fixtures/rails60/public/apple-touch-icon-precomposed.png similarity index 100% rename from spec/fixtures/rails51/public/apple-touch-icon-precomposed.png rename to spec/fixtures/rails60/public/apple-touch-icon-precomposed.png diff --git a/spec/fixtures/rails51/public/apple-touch-icon.png b/spec/fixtures/rails60/public/apple-touch-icon.png similarity index 100% rename from spec/fixtures/rails51/public/apple-touch-icon.png rename to spec/fixtures/rails60/public/apple-touch-icon.png diff --git a/spec/fixtures/rails51/public/favicon.ico b/spec/fixtures/rails60/public/favicon.ico similarity index 100% rename from spec/fixtures/rails51/public/favicon.ico rename to spec/fixtures/rails60/public/favicon.ico diff --git a/spec/fixtures/rails60/public/robots.txt b/spec/fixtures/rails60/public/robots.txt new file mode 100644 index 000000000..c19f78ab6 --- /dev/null +++ b/spec/fixtures/rails60/public/robots.txt @@ -0,0 +1 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/spec/fixtures/rails52/test/application_system_test_case.rb b/spec/fixtures/rails60/test/application_system_test_case.rb similarity index 83% rename from spec/fixtures/rails52/test/application_system_test_case.rb rename to spec/fixtures/rails60/test/application_system_test_case.rb index 93fada67a..d19212abd 100644 --- a/spec/fixtures/rails52/test/application_system_test_case.rb +++ b/spec/fixtures/rails60/test/application_system_test_case.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase diff --git a/spec/fixtures/rails60/test/channels/application_cable/connection_test.rb b/spec/fixtures/rails60/test/channels/application_cable/connection_test.rb new file mode 100644 index 000000000..800405f15 --- /dev/null +++ b/spec/fixtures/rails60/test/channels/application_cable/connection_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase + # test "connects with cookies" do + # cookies.signed[:user_id] = 42 + # + # connect + # + # assert_equal connection.user_id, "42" + # end +end diff --git a/spec/fixtures/rails51/log/.keep b/spec/fixtures/rails60/test/controllers/.keep similarity index 100% rename from spec/fixtures/rails51/log/.keep rename to spec/fixtures/rails60/test/controllers/.keep diff --git a/spec/fixtures/rails51/test/controllers/.keep b/spec/fixtures/rails60/test/fixtures/.keep similarity index 100% rename from spec/fixtures/rails51/test/controllers/.keep rename to spec/fixtures/rails60/test/fixtures/.keep diff --git a/spec/fixtures/rails51/test/fixtures/.keep b/spec/fixtures/rails60/test/fixtures/files/.keep similarity index 100% rename from spec/fixtures/rails51/test/fixtures/.keep rename to spec/fixtures/rails60/test/fixtures/files/.keep diff --git a/spec/fixtures/rails60/test/fixtures/users.yml b/spec/fixtures/rails60/test/fixtures/users.yml new file mode 100644 index 000000000..7d4122404 --- /dev/null +++ b/spec/fixtures/rails60/test/fixtures/users.yml @@ -0,0 +1,7 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + +two: + name: MyString diff --git a/spec/fixtures/rails51/test/fixtures/files/.keep b/spec/fixtures/rails60/test/helpers/.keep similarity index 100% rename from spec/fixtures/rails51/test/fixtures/files/.keep rename to spec/fixtures/rails60/test/helpers/.keep diff --git a/spec/fixtures/rails51/test/helpers/.keep b/spec/fixtures/rails60/test/integration/.keep similarity index 100% rename from spec/fixtures/rails51/test/helpers/.keep rename to spec/fixtures/rails60/test/integration/.keep diff --git a/spec/fixtures/rails51/test/integration/.keep b/spec/fixtures/rails60/test/mailers/.keep similarity index 100% rename from spec/fixtures/rails51/test/integration/.keep rename to spec/fixtures/rails60/test/mailers/.keep diff --git a/spec/fixtures/rails51/test/mailers/.keep b/spec/fixtures/rails60/test/models/.keep similarity index 100% rename from spec/fixtures/rails51/test/mailers/.keep rename to spec/fixtures/rails60/test/models/.keep diff --git a/spec/fixtures/rails60/test/models/user_test.rb b/spec/fixtures/rails60/test/models/user_test.rb new file mode 100644 index 000000000..82f61e010 --- /dev/null +++ b/spec/fixtures/rails60/test/models/user_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/spec/fixtures/rails51/test/models/.keep b/spec/fixtures/rails60/test/system/.keep similarity index 100% rename from spec/fixtures/rails51/test/models/.keep rename to spec/fixtures/rails60/test/system/.keep diff --git a/spec/fixtures/rails52/test/test_helper.rb b/spec/fixtures/rails60/test/test_helper.rb similarity index 90% rename from spec/fixtures/rails52/test/test_helper.rb rename to spec/fixtures/rails60/test/test_helper.rb index 58af4446f..3ab84e3d1 100644 --- a/spec/fixtures/rails52/test/test_helper.rb +++ b/spec/fixtures/rails60/test/test_helper.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true ENV['RAILS_ENV'] ||= 'test' require_relative '../config/environment' require 'rails/test_help' diff --git a/spec/fixtures/rails51/test/system/.keep b/spec/fixtures/rails60/vendor/.keep similarity index 100% rename from spec/fixtures/rails51/test/system/.keep rename to spec/fixtures/rails60/vendor/.keep diff --git a/spec/fixtures/rails61/.gitattributes b/spec/fixtures/rails61/.gitattributes new file mode 100644 index 000000000..516857104 --- /dev/null +++ b/spec/fixtures/rails61/.gitattributes @@ -0,0 +1,10 @@ +# See https://git-scm.com/docs/gitattributes for more about git attribute files. + +# Mark the database schema as having been generated. +db/schema.rb linguist-generated + +# Mark the yarn lockfile as having been generated. +yarn.lock linguist-generated + +# Mark any vendored files as having been vendored. +vendor/* linguist-vendored diff --git a/spec/fixtures/rails51/.gitignore b/spec/fixtures/rails61/.gitignore similarity index 71% rename from spec/fixtures/rails51/.gitignore rename to spec/fixtures/rails61/.gitignore index dcc5b36f3..eb612efd0 100644 --- a/spec/fixtures/rails51/.gitignore +++ b/spec/fixtures/rails61/.gitignore @@ -9,7 +9,7 @@ # Ignore the default SQLite database. /db/*.sqlite3 -/db/*.sqlite3-journal +/db/*.sqlite3-* # Ignore all logfiles and tempfiles. /log/* @@ -17,7 +17,14 @@ !/log/.keep !/tmp/.keep -/node_modules -/yarn-error.log +# Ignore pidfiles, but keep the directory. +/tmp/pids/* +!/tmp/pids/ +!/tmp/pids/.keep + +/public/assets .byebug_history + +# Ignore master key for decrypting credentials and more. +/config/master.key diff --git a/spec/fixtures/rails61/.ruby-version b/spec/fixtures/rails61/.ruby-version new file mode 100644 index 000000000..4a36342fc --- /dev/null +++ b/spec/fixtures/rails61/.ruby-version @@ -0,0 +1 @@ +3.0.0 diff --git a/spec/fixtures/rails61/Gemfile b/spec/fixtures/rails61/Gemfile new file mode 100644 index 000000000..6925c0c66 --- /dev/null +++ b/spec/fixtures/rails61/Gemfile @@ -0,0 +1,19 @@ +# frozen_string_literal: true +source 'https://rubygems.org' + +rails_version = '6.1.3' + +gem 'actioncable', rails_version +gem 'actionmailer', rails_version +gem 'actionpack', rails_version +gem 'actionview', rails_version +gem 'activejob', rails_version +gem 'activemodel', rails_version +gem 'activerecord', rails_version +gem 'activesupport', rails_version +gem 'railties', rails_version +gem 'sprockets-rails' + +gem 'sqlite3' +gem 'tzinfo-data' +gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock new file mode 100644 index 000000000..f261b9561 --- /dev/null +++ b/spec/fixtures/rails61/Gemfile.lock @@ -0,0 +1,125 @@ +PATH + remote: ../../.. + specs: + parallel_tests (3.5.2) + parallel + +GEM + remote: https://rubygems.org/ + specs: + actioncable (6.1.3) + actionpack (= 6.1.3) + activesupport (= 6.1.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (6.1.3) + actionpack (= 6.1.3) + actionview (= 6.1.3) + activejob (= 6.1.3) + activesupport (= 6.1.3) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 2.0) + actionpack (6.1.3) + actionview (= 6.1.3) + activesupport (= 6.1.3) + rack (~> 2.0, >= 2.0.9) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actionview (6.1.3) + activesupport (= 6.1.3) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (6.1.3) + activesupport (= 6.1.3) + globalid (>= 0.3.6) + activemodel (6.1.3) + activesupport (= 6.1.3) + activerecord (6.1.3) + activemodel (= 6.1.3) + activesupport (= 6.1.3) + activesupport (6.1.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + zeitwerk (~> 2.3) + builder (3.2.4) + concurrent-ruby (1.1.8) + crass (1.0.6) + erubi (1.10.0) + globalid (0.4.2) + activesupport (>= 4.2.0) + i18n (1.8.9) + concurrent-ruby (~> 1.0) + loofah (2.9.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + method_source (1.0.0) + mini_mime (1.0.2) + minitest (5.14.4) + nio4r (2.5.7) + nokogiri (1.11.2-x64-mingw32) + racc (~> 1.4) + nokogiri (1.11.2-x86_64-linux) + racc (~> 1.4) + parallel (1.20.1) + racc (1.5.2) + rack (2.2.3) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.3.0) + loofah (~> 2.3) + railties (6.1.3) + actionpack (= 6.1.3) + activesupport (= 6.1.3) + method_source + rake (>= 0.8.7) + thor (~> 1.0) + rake (13.0.3) + sprockets (4.0.2) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.2) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + sqlite3 (1.4.2) + thor (1.1.0) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2021.1) + tzinfo (>= 1.0.0) + websocket-driver (0.7.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.4.2) + +PLATFORMS + x64-mingw32 + x86_64-linux + +DEPENDENCIES + actioncable (= 6.1.3) + actionmailer (= 6.1.3) + actionpack (= 6.1.3) + actionview (= 6.1.3) + activejob (= 6.1.3) + activemodel (= 6.1.3) + activerecord (= 6.1.3) + activesupport (= 6.1.3) + parallel_tests! + railties (= 6.1.3) + sprockets-rails + sqlite3 + tzinfo-data + +BUNDLED WITH + 2.2.15 diff --git a/spec/fixtures/rails52/README.md b/spec/fixtures/rails61/README.md similarity index 100% rename from spec/fixtures/rails52/README.md rename to spec/fixtures/rails61/README.md diff --git a/spec/fixtures/rails51/Rakefile b/spec/fixtures/rails61/Rakefile similarity index 73% rename from spec/fixtures/rails51/Rakefile rename to spec/fixtures/rails61/Rakefile index 84f2bc394..9a5ea7383 100644 --- a/spec/fixtures/rails51/Rakefile +++ b/spec/fixtures/rails61/Rakefile @@ -1,7 +1,6 @@ -# frozen_string_literal: true # Add your own tasks in files placed in lib/tasks ending in .rake, # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. -require_relative 'config/application' +require_relative "config/application" Rails.application.load_tasks diff --git a/spec/fixtures/rails52/app/assets/config/manifest.js b/spec/fixtures/rails61/app/assets/config/manifest.js similarity index 62% rename from spec/fixtures/rails52/app/assets/config/manifest.js rename to spec/fixtures/rails61/app/assets/config/manifest.js index b16e53d6d..591819335 100644 --- a/spec/fixtures/rails52/app/assets/config/manifest.js +++ b/spec/fixtures/rails61/app/assets/config/manifest.js @@ -1,3 +1,2 @@ //= link_tree ../images -//= link_directory ../javascripts .js //= link_directory ../stylesheets .css diff --git a/spec/fixtures/rails51/vendor/.keep b/spec/fixtures/rails61/app/assets/images/.keep similarity index 100% rename from spec/fixtures/rails51/vendor/.keep rename to spec/fixtures/rails61/app/assets/images/.keep diff --git a/spec/fixtures/rails52/app/assets/stylesheets/application.css b/spec/fixtures/rails61/app/assets/stylesheets/application.css similarity index 100% rename from spec/fixtures/rails52/app/assets/stylesheets/application.css rename to spec/fixtures/rails61/app/assets/stylesheets/application.css diff --git a/spec/fixtures/rails52/app/channels/application_cable/channel.rb b/spec/fixtures/rails61/app/channels/application_cable/channel.rb similarity index 72% rename from spec/fixtures/rails52/app/channels/application_cable/channel.rb rename to spec/fixtures/rails61/app/channels/application_cable/channel.rb index 51e3e936b..d67269728 100644 --- a/spec/fixtures/rails52/app/channels/application_cable/channel.rb +++ b/spec/fixtures/rails61/app/channels/application_cable/channel.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true module ApplicationCable class Channel < ActionCable::Channel::Base end diff --git a/spec/fixtures/rails52/app/channels/application_cable/connection.rb b/spec/fixtures/rails61/app/channels/application_cable/connection.rb similarity index 73% rename from spec/fixtures/rails52/app/channels/application_cable/connection.rb rename to spec/fixtures/rails61/app/channels/application_cable/connection.rb index fa70319da..0ff5442f4 100644 --- a/spec/fixtures/rails52/app/channels/application_cable/connection.rb +++ b/spec/fixtures/rails61/app/channels/application_cable/connection.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true module ApplicationCable class Connection < ActionCable::Connection::Base end diff --git a/spec/fixtures/rails61/app/controllers/application_controller.rb b/spec/fixtures/rails61/app/controllers/application_controller.rb new file mode 100644 index 000000000..09705d12a --- /dev/null +++ b/spec/fixtures/rails61/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/spec/fixtures/rails52/app/assets/images/.keep b/spec/fixtures/rails61/app/controllers/concerns/.keep similarity index 100% rename from spec/fixtures/rails52/app/assets/images/.keep rename to spec/fixtures/rails61/app/controllers/concerns/.keep diff --git a/spec/fixtures/rails61/app/helpers/application_helper.rb b/spec/fixtures/rails61/app/helpers/application_helper.rb new file mode 100644 index 000000000..de6be7945 --- /dev/null +++ b/spec/fixtures/rails61/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/spec/fixtures/rails61/app/javascript/channels/consumer.js b/spec/fixtures/rails61/app/javascript/channels/consumer.js new file mode 100644 index 000000000..8ec3aad3a --- /dev/null +++ b/spec/fixtures/rails61/app/javascript/channels/consumer.js @@ -0,0 +1,6 @@ +// Action Cable provides the framework to deal with WebSockets in Rails. +// You can generate new channels where WebSocket features live using the `bin/rails generate channel` command. + +import { createConsumer } from "@rails/actioncable" + +export default createConsumer() diff --git a/spec/fixtures/rails61/app/javascript/channels/index.js b/spec/fixtures/rails61/app/javascript/channels/index.js new file mode 100644 index 000000000..0cfcf7491 --- /dev/null +++ b/spec/fixtures/rails61/app/javascript/channels/index.js @@ -0,0 +1,5 @@ +// Load all the channels within this directory and all subdirectories. +// Channel files must be named *_channel.js. + +const channels = require.context('.', true, /_channel\.js$/) +channels.keys().forEach(channels) diff --git a/spec/fixtures/rails61/app/javascript/packs/application.js b/spec/fixtures/rails61/app/javascript/packs/application.js new file mode 100644 index 000000000..26530c6c0 --- /dev/null +++ b/spec/fixtures/rails61/app/javascript/packs/application.js @@ -0,0 +1,11 @@ +// This file is automatically compiled by Webpack, along with any other files +// present in this directory. You're encouraged to place your actual application logic in +// a relevant structure within app/javascript and only use these pack files to reference +// that code so it'll be compiled. + +import Rails from "@rails/ujs" +import Turbolinks from "turbolinks" +import "channels" + +Rails.start() +Turbolinks.start() diff --git a/spec/fixtures/rails61/app/jobs/application_job.rb b/spec/fixtures/rails61/app/jobs/application_job.rb new file mode 100644 index 000000000..d394c3d10 --- /dev/null +++ b/spec/fixtures/rails61/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/spec/fixtures/rails51/app/mailers/application_mailer.rb b/spec/fixtures/rails61/app/mailers/application_mailer.rb similarity index 77% rename from spec/fixtures/rails51/app/mailers/application_mailer.rb rename to spec/fixtures/rails61/app/mailers/application_mailer.rb index 24289009a..286b2239d 100644 --- a/spec/fixtures/rails51/app/mailers/application_mailer.rb +++ b/spec/fixtures/rails61/app/mailers/application_mailer.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true class ApplicationMailer < ActionMailer::Base default from: 'from@example.com' layout 'mailer' diff --git a/spec/fixtures/rails51/app/models/application_record.rb b/spec/fixtures/rails61/app/models/application_record.rb similarity index 72% rename from spec/fixtures/rails51/app/models/application_record.rb rename to spec/fixtures/rails61/app/models/application_record.rb index 767a072b5..10a4cba84 100644 --- a/spec/fixtures/rails51/app/models/application_record.rb +++ b/spec/fixtures/rails61/app/models/application_record.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true class ApplicationRecord < ActiveRecord::Base self.abstract_class = true end diff --git a/spec/fixtures/rails52/app/assets/javascripts/channels/.keep b/spec/fixtures/rails61/app/models/concerns/.keep similarity index 100% rename from spec/fixtures/rails52/app/assets/javascripts/channels/.keep rename to spec/fixtures/rails61/app/models/concerns/.keep diff --git a/spec/fixtures/rails52/app/models/user.rb b/spec/fixtures/rails61/app/models/user.rb similarity index 53% rename from spec/fixtures/rails52/app/models/user.rb rename to spec/fixtures/rails61/app/models/user.rb index b161db0c3..379658a50 100644 --- a/spec/fixtures/rails52/app/models/user.rb +++ b/spec/fixtures/rails61/app/models/user.rb @@ -1,3 +1,2 @@ -# frozen_string_literal: true class User < ApplicationRecord end diff --git a/spec/fixtures/rails61/app/views/layouts/application.html.erb b/spec/fixtures/rails61/app/views/layouts/application.html.erb new file mode 100644 index 000000000..2cd2637fe --- /dev/null +++ b/spec/fixtures/rails61/app/views/layouts/application.html.erb @@ -0,0 +1,16 @@ + + + + Rails61 + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %> + <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %> + + + + <%= yield %> + + diff --git a/spec/fixtures/rails52/app/views/layouts/mailer.html.erb b/spec/fixtures/rails61/app/views/layouts/mailer.html.erb similarity index 100% rename from spec/fixtures/rails52/app/views/layouts/mailer.html.erb rename to spec/fixtures/rails61/app/views/layouts/mailer.html.erb diff --git a/spec/fixtures/rails52/app/views/layouts/mailer.text.erb b/spec/fixtures/rails61/app/views/layouts/mailer.text.erb similarity index 100% rename from spec/fixtures/rails52/app/views/layouts/mailer.text.erb rename to spec/fixtures/rails61/app/views/layouts/mailer.text.erb diff --git a/spec/fixtures/rails61/bin/rails b/spec/fixtures/rails61/bin/rails new file mode 100755 index 000000000..6fb4e4051 --- /dev/null +++ b/spec/fixtures/rails61/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/spec/fixtures/rails61/bin/rake b/spec/fixtures/rails61/bin/rake new file mode 100755 index 000000000..4fbf10b96 --- /dev/null +++ b/spec/fixtures/rails61/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "rake" +Rake.application.run diff --git a/spec/fixtures/rails51/bin/setup b/spec/fixtures/rails61/bin/setup similarity index 58% rename from spec/fixtures/rails51/bin/setup rename to spec/fixtures/rails61/bin/setup index 4c1bacf0f..90700ac4f 100755 --- a/spec/fixtures/rails51/bin/setup +++ b/spec/fixtures/rails61/bin/setup @@ -1,34 +1,32 @@ #!/usr/bin/env ruby -# frozen_string_literal: true -require 'pathname' -require 'fileutils' -include FileUtils # rubocop:disable Style/MixinUsage +require "fileutils" # path to your application root. -APP_ROOT = Pathname.new File.expand_path('..', __dir__) +APP_ROOT = File.expand_path('..', __dir__) def system!(*args) system(*args) || abort("\n== Command #{args} failed ==") end -chdir APP_ROOT do - # This script is a starting point to setup your application. +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. # Add necessary setup steps to this file. puts '== Installing dependencies ==' system! 'gem install bundler --conservative' system('bundle check') || system!('bundle install') - # Install JavaScript dependencies if using Yarn - # system('bin/yarn') + # Install JavaScript dependencies + system! 'bin/yarn' # puts "\n== Copying sample files ==" # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' + # FileUtils.cp 'config/database.yml.sample', 'config/database.yml' # end puts "\n== Preparing database ==" - system! 'bin/rails db:setup' + system! 'bin/rails db:prepare' puts "\n== Removing old logs and tempfiles ==" system! 'bin/rails log:clear tmp:clear' diff --git a/spec/fixtures/rails61/bin/yarn b/spec/fixtures/rails61/bin/yarn new file mode 100755 index 000000000..da6c479af --- /dev/null +++ b/spec/fixtures/rails61/bin/yarn @@ -0,0 +1,17 @@ +#!/usr/bin/env ruby +APP_ROOT = File.expand_path('..', __dir__) +Dir.chdir(APP_ROOT) do + yarn = ENV["PATH"].split(File::PATH_SEPARATOR) + .reject { |dir| File.expand_path(dir) == __dir__ } + .product(["yarn", "yarn.cmd", "yarn.ps1"]) + .map { |dir, file| File.expand_path(file, dir) } + .find { |file| File.executable?(file) } + + if yarn + exec yarn, *ARGV + else + warn "Yarn executable was not detected in the system." + warn "Download Yarn at https://yarnpkg.com/en/docs/install" + exit 1 + end +end diff --git a/spec/fixtures/rails52/config.ru b/spec/fixtures/rails61/config.ru similarity index 57% rename from spec/fixtures/rails52/config.ru rename to spec/fixtures/rails61/config.ru index 7eae2644f..4a3c09a68 100644 --- a/spec/fixtures/rails52/config.ru +++ b/spec/fixtures/rails61/config.ru @@ -1,6 +1,6 @@ -# frozen_string_literal: true # This file is used by Rack-based servers to start the application. -require_relative 'config/environment' +require_relative "config/environment" run Rails.application +Rails.application.load_server diff --git a/spec/fixtures/rails61/config/application.rb b/spec/fixtures/rails61/config/application.rb new file mode 100644 index 000000000..d07333913 --- /dev/null +++ b/spec/fixtures/rails61/config/application.rb @@ -0,0 +1,35 @@ +require_relative "boot" + +require "rails" +# Pick the frameworks you want: +require "active_model/railtie" +require "active_job/railtie" +require "active_record/railtie" +# require "active_storage/engine" +require "action_controller/railtie" +require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" +require "action_view/railtie" +require "action_cable/engine" +# require "sprockets/railtie" +require "rails/test_unit/railtie" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Rails61 + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 6.1 + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + end +end diff --git a/spec/fixtures/rails61/config/boot.rb b/spec/fixtures/rails61/config/boot.rb new file mode 100644 index 000000000..d69bd27dc --- /dev/null +++ b/spec/fixtures/rails61/config/boot.rb @@ -0,0 +1,3 @@ +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. diff --git a/spec/fixtures/rails61/config/cable.yml b/spec/fixtures/rails61/config/cable.yml new file mode 100644 index 000000000..da0571339 --- /dev/null +++ b/spec/fixtures/rails61/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: rails61_production diff --git a/spec/fixtures/rails61/config/credentials.yml.enc b/spec/fixtures/rails61/config/credentials.yml.enc new file mode 100644 index 000000000..a8669465f --- /dev/null +++ b/spec/fixtures/rails61/config/credentials.yml.enc @@ -0,0 +1 @@ +aubiW8m61jDG+NneYhU9p325QDOmlICTJ5Qz4otgOiuYt7jYRtFHq6UW+5FK5Rnn6ixynhGE2B1D8mq1OLO4r3F7R/O236cseJqh+TOX0VTKRdnuCgSCTdJXFd2DTSsg4yRYM7xDFIT6qNv+Htn56vMTZMz8tvLQ+AfsN6yWJ9NruN6mQiA/8JOdAjKVj2sTPHAZB1+ktj0jFwo5Mr/Ixy6Vxd7lMlhV2p6AIzIqQEzFVpyKr9iuFF570ZkMVuRAyozTT7+4jRtk2JY63VvIqabS+kaAR/76TTZYzF4hadtWC/x5NW6vewlmbyGEpCVLkZzNHCRzsnHdE3zMf/fhfTyYVcbyrkSOP9L7FG5dQmqDtIDY0JyLeADDeHL2N4GwlbqDuV1HUtTPh2FYKB32MFth2lsL30HvQH5F--JFMR1GM9jIjoF7nq--2bcbl0NUQsk5KX9uj6zSiw== \ No newline at end of file diff --git a/spec/fixtures/rails51/config/database.yml b/spec/fixtures/rails61/config/database.yml similarity index 84% rename from spec/fixtures/rails51/config/database.yml rename to spec/fixtures/rails61/config/database.yml index faeb94565..f90baf882 100644 --- a/spec/fixtures/rails51/config/database.yml +++ b/spec/fixtures/rails61/config/database.yml @@ -1,4 +1,4 @@ -# SQLite version 3.x +# SQLite. Versions 3.8.0 and up are supported. # gem install sqlite3 # # Ensure the SQLite 3 gem is defined in your Gemfile @@ -6,7 +6,7 @@ # default: &default adapter: sqlite3 - pool: 5 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> timeout: 5000 development: diff --git a/spec/fixtures/rails52/config/environment.rb b/spec/fixtures/rails61/config/environment.rb similarity index 61% rename from spec/fixtures/rails52/config/environment.rb rename to spec/fixtures/rails61/config/environment.rb index 12ea62f88..cac531577 100644 --- a/spec/fixtures/rails52/config/environment.rb +++ b/spec/fixtures/rails61/config/environment.rb @@ -1,6 +1,5 @@ -# frozen_string_literal: true # Load the Rails application. -require_relative 'application' +require_relative "application" # Initialize the Rails application. Rails.application.initialize! diff --git a/spec/fixtures/rails51/config/environments/development.rb b/spec/fixtures/rails61/config/environments/development.rb similarity index 55% rename from spec/fixtures/rails51/config/environments/development.rb rename to spec/fixtures/rails61/config/environments/development.rb index 8a4e13721..e65bd2a7f 100644 --- a/spec/fixtures/rails51/config/environments/development.rb +++ b/spec/fixtures/rails61/config/environments/development.rb @@ -1,9 +1,10 @@ -# frozen_string_literal: true +require "active_support/core_ext/integer/time" + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # In the development environment your application's code is reloaded on - # every request. This slows down response time but is perfect for development + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development # since you don't have to restart the web server when you make code changes. config.cache_classes = false @@ -14,12 +15,14 @@ config.consider_all_requests_local = true # Enable/disable caching. By default caching is disabled. - if Rails.root.join('tmp/caching-dev.txt').exist? + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.seconds.to_i}" + 'Cache-Control' => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false @@ -35,21 +38,28 @@ # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load - # Debug mode disables concatenation and preprocessing of assets. - # This option may cause significant delays in view rendering with a large - # number of complex assets. - config.assets.debug = true + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true - # Suppress logger output for asset requests. - config.assets.quiet = true + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true # Use an evented file watcher to asynchronously detect changes in source code, # routes, locales, etc. This feature depends on the listen gem. # config.file_watcher = ActiveSupport::EventedFileUpdateChecker + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true end diff --git a/spec/fixtures/rails51/config/environments/production.rb b/spec/fixtures/rails61/config/environments/production.rb similarity index 57% rename from spec/fixtures/rails51/config/environments/production.rb rename to spec/fixtures/rails61/config/environments/production.rb index ff1eda28e..972a88e43 100644 --- a/spec/fixtures/rails51/config/environments/production.rb +++ b/spec/fixtures/rails61/config/environments/production.rb @@ -1,4 +1,5 @@ -# frozen_string_literal: true +require "active_support/core_ext/integer/time" + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -15,32 +16,22 @@ config.consider_all_requests_local = false config.action_controller.perform_caching = true - # Attempt to read encrypted secrets from `config/secrets.yml.enc`. - # Requires an encryption key in `ENV["RAILS_MASTER_KEY"]` or - # `config/secrets.yml.key`. - config.read_encrypted_secrets = true + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true # Disable serving static files from the `/public` folder by default since # Apache or NGINX already handles this. config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? - # Compress JavaScripts and CSS. - config.assets.js_compressor = :uglifier - # config.assets.css_compressor = :sass - - # Do not fallback to assets pipeline if a precompiled asset is missed. - config.assets.compile = false - - # `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' + # config.asset_host = 'http://assets.example.com' # Specifies the header that your server uses for sending files. # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX - # Mount Action Cable outside main process or domain + # Mount Action Cable outside main process or domain. # config.action_cable.mount_path = nil # config.action_cable.url = 'wss://example.com/cable' # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] @@ -48,9 +39,9 @@ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true - # Use the lowest log level to ensure availability of diagnostic information - # when problems arise. - config.log_level = :debug + # Include generic and useful information about system operation, but avoid logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). + config.log_level = :info # Prepend all log lines with the following tags. config.log_tags = [:request_id] @@ -58,9 +49,10 @@ # Use a different cache store in production. # config.cache_store = :mem_cache_store - # Use a real queuing backend for Active Job (and separate queues per environment) + # Use a real queuing backend for Active Job (and separate queues per environment). # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "rails51_#{Rails.env}" + # config.active_job.queue_name_prefix = "rails61_production" + config.action_mailer.perform_caching = false # Ignore bad email addresses and do not raise email delivery errors. @@ -74,11 +66,17 @@ # Send deprecation notices to registered listeners. config.active_support.deprecation = :notify + # Log disallowed deprecations. + config.active_support.disallowed_deprecation = :log + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + # Use default logging formatter so that PID and timestamp are not suppressed. config.log_formatter = ::Logger::Formatter.new # Use a different logger for distributed setups. - # require 'syslog/logger' + # require "syslog/logger" # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') if ENV["RAILS_LOG_TO_STDOUT"].present? @@ -89,4 +87,25 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false + + # Inserts middleware to perform automatic connection switching. + # The `database_selector` hash is used to pass options to the DatabaseSelector + # middleware. The `delay` is used to determine how long to wait after a write + # to send a subsequent read to the primary. + # + # The `database_resolver` class is used by the middleware to determine which + # database is appropriate to use based on the time delay. + # + # The `database_resolver_context` class is used by the middleware to set + # timestamps for the last write to the primary. The resolver uses the context + # class timestamps to determine how long to wait before reading from the + # replica. + # + # By default Rails will store a last write timestamp in the session. The + # DatabaseSelector middleware is designed as such you can define your own + # strategy for connection switching and pass that into the middleware through + # these configuration options. + # config.active_record.database_selector = { delay: 2.seconds } + # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver + # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session end diff --git a/spec/fixtures/rails52/config/environments/test.rb b/spec/fixtures/rails61/config/environments/test.rb similarity index 63% rename from spec/fixtures/rails52/config/environments/test.rb rename to spec/fixtures/rails61/config/environments/test.rb index 79de6da35..d66c042f9 100644 --- a/spec/fixtures/rails52/config/environments/test.rb +++ b/spec/fixtures/rails61/config/environments/test.rb @@ -1,11 +1,13 @@ -# frozen_string_literal: true +require "active_support/core_ext/integer/time" + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # The test environment is used exclusively to run your application's - # test suite. You never need to work with it otherwise. Remember that - # your test database is "scratch space" for the test suite and is wiped - # and recreated between test runs. Don't rely on the data there! config.cache_classes = true # Do not eager load code on boot. This avoids loading your whole application @@ -22,6 +24,7 @@ # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.cache_store = :null_store # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false @@ -29,9 +32,6 @@ # Disable request forgery protection in test environment. config.action_controller.allow_forgery_protection = false - # Store uploaded files on the local file system in a temporary directory - config.active_storage.service = :test - config.action_mailer.perform_caching = false # Tell Action Mailer not to deliver emails to the real world. @@ -42,6 +42,15 @@ # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true end diff --git a/spec/fixtures/rails52/config/initializers/application_controller_renderer.rb b/spec/fixtures/rails61/config/initializers/application_controller_renderer.rb similarity index 87% rename from spec/fixtures/rails52/config/initializers/application_controller_renderer.rb rename to spec/fixtures/rails61/config/initializers/application_controller_renderer.rb index f4556db39..89d2efab2 100644 --- a/spec/fixtures/rails52/config/initializers/application_controller_renderer.rb +++ b/spec/fixtures/rails61/config/initializers/application_controller_renderer.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # ActiveSupport::Reloader.to_prepare do diff --git a/spec/fixtures/rails61/config/initializers/backtrace_silencers.rb b/spec/fixtures/rails61/config/initializers/backtrace_silencers.rb new file mode 100644 index 000000000..33699c309 --- /dev/null +++ b/spec/fixtures/rails61/config/initializers/backtrace_silencers.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code +# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". +Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] diff --git a/spec/fixtures/rails61/config/initializers/content_security_policy.rb b/spec/fixtures/rails61/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..35d0f26fc --- /dev/null +++ b/spec/fixtures/rails61/config/initializers/content_security_policy.rb @@ -0,0 +1,30 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # If you are using webpack-dev-server then specify webpack-dev-server host +# policy.connect_src :self, :https, "http://localhost:3035", "ws://localhost:3035" if Rails.env.development? + +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Set the nonce only to specific directives +# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/spec/fixtures/rails52/config/initializers/cookies_serializer.rb b/spec/fixtures/rails61/config/initializers/cookies_serializer.rb similarity index 89% rename from spec/fixtures/rails52/config/initializers/cookies_serializer.rb rename to spec/fixtures/rails61/config/initializers/cookies_serializer.rb index 2a7295959..5a6a32d37 100644 --- a/spec/fixtures/rails52/config/initializers/cookies_serializer.rb +++ b/spec/fixtures/rails61/config/initializers/cookies_serializer.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Specify a serializer for the signed and encrypted cookie jars. diff --git a/spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb b/spec/fixtures/rails61/config/initializers/filter_parameter_logging.rb similarity index 52% rename from spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb rename to spec/fixtures/rails61/config/initializers/filter_parameter_logging.rb index b7fe1231f..4b34a0366 100644 --- a/spec/fixtures/rails51/config/initializers/filter_parameter_logging.rb +++ b/spec/fixtures/rails61/config/initializers/filter_parameter_logging.rb @@ -1,5 +1,6 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Configure sensitive parameters which will be filtered from the log file. -Rails.application.config.filter_parameters += [:password] +Rails.application.config.filter_parameters += [ + :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/spec/fixtures/rails51/config/initializers/inflections.rb b/spec/fixtures/rails61/config/initializers/inflections.rb similarity index 95% rename from spec/fixtures/rails51/config/initializers/inflections.rb rename to spec/fixtures/rails61/config/initializers/inflections.rb index aa7435fbc..ac033bf9d 100644 --- a/spec/fixtures/rails51/config/initializers/inflections.rb +++ b/spec/fixtures/rails61/config/initializers/inflections.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new inflection rules using the following format. Inflections diff --git a/spec/fixtures/rails51/config/initializers/mime_types.rb b/spec/fixtures/rails61/config/initializers/mime_types.rb similarity index 83% rename from spec/fixtures/rails51/config/initializers/mime_types.rb rename to spec/fixtures/rails61/config/initializers/mime_types.rb index 6e1d16f02..dc1899682 100644 --- a/spec/fixtures/rails51/config/initializers/mime_types.rb +++ b/spec/fixtures/rails61/config/initializers/mime_types.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # Add new mime types for use in respond_to blocks: diff --git a/spec/fixtures/rails61/config/initializers/permissions_policy.rb b/spec/fixtures/rails61/config/initializers/permissions_policy.rb new file mode 100644 index 000000000..00f64d71b --- /dev/null +++ b/spec/fixtures/rails61/config/initializers/permissions_policy.rb @@ -0,0 +1,11 @@ +# Define an application-wide HTTP permissions policy. For further +# information see https://developers.google.com/web/updates/2018/06/feature-policy +# +# Rails.application.config.permissions_policy do |f| +# f.camera :none +# f.gyroscope :none +# f.microphone :none +# f.usb :none +# f.fullscreen :self +# f.payment :self, "https://secure.example.com" +# end diff --git a/spec/fixtures/rails51/config/initializers/wrap_parameters.rb b/spec/fixtures/rails61/config/initializers/wrap_parameters.rb similarity index 94% rename from spec/fixtures/rails51/config/initializers/wrap_parameters.rb rename to spec/fixtures/rails61/config/initializers/wrap_parameters.rb index 18c382529..bbfc3961b 100644 --- a/spec/fixtures/rails51/config/initializers/wrap_parameters.rb +++ b/spec/fixtures/rails61/config/initializers/wrap_parameters.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true # Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which diff --git a/spec/fixtures/rails52/config/locales/en.yml b/spec/fixtures/rails61/config/locales/en.yml similarity index 93% rename from spec/fixtures/rails52/config/locales/en.yml rename to spec/fixtures/rails61/config/locales/en.yml index decc5a857..cf9b342d0 100644 --- a/spec/fixtures/rails52/config/locales/en.yml +++ b/spec/fixtures/rails61/config/locales/en.yml @@ -27,7 +27,7 @@ # 'true': 'foo' # # To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. +# available at https://guides.rubyonrails.org/i18n.html. en: hello: "Hello world" diff --git a/spec/fixtures/rails61/config/puma.rb b/spec/fixtures/rails61/config/puma.rb new file mode 100644 index 000000000..fa40ee6f5 --- /dev/null +++ b/spec/fixtures/rails61/config/puma.rb @@ -0,0 +1,43 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +# Specifies the `worker_timeout` threshold that Puma will use to wait before +# terminating a worker in development environments. +# +worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT", 3000) + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked web server processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/spec/fixtures/rails61/config/routes.rb b/spec/fixtures/rails61/config/routes.rb new file mode 100644 index 000000000..c06383a17 --- /dev/null +++ b/spec/fixtures/rails61/config/routes.rb @@ -0,0 +1,3 @@ +Rails.application.routes.draw do + # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html +end diff --git a/spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb b/spec/fixtures/rails61/db/migrate/20210325101931_create_users.rb similarity index 56% rename from spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb rename to spec/fixtures/rails61/db/migrate/20210325101931_create_users.rb index 55b4dfea6..9f06756e8 100644 --- a/spec/fixtures/rails52/db/migrate/20181024130151_create_users.rb +++ b/spec/fixtures/rails61/db/migrate/20210325101931_create_users.rb @@ -1,5 +1,4 @@ -# frozen_string_literal: true -class CreateUsers < ActiveRecord::Migration[5.2] +class CreateUsers < ActiveRecord::Migration[6.1] def change create_table :users do |t| t.string :name diff --git a/spec/fixtures/rails61/db/schema.rb b/spec/fixtures/rails61/db/schema.rb new file mode 100644 index 000000000..64f426a4f --- /dev/null +++ b/spec/fixtures/rails61/db/schema.rb @@ -0,0 +1,21 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema.define(version: 2021_03_25_101931) do + + create_table "users", force: :cascade do |t| + t.string "name" + t.datetime "created_at", precision: 6, null: false + t.datetime "updated_at", precision: 6, null: false + end + +end diff --git a/spec/fixtures/rails51/db/seeds.rb b/spec/fixtures/rails61/db/seeds.rb similarity index 64% rename from spec/fixtures/rails51/db/seeds.rb rename to spec/fixtures/rails61/db/seeds.rb index 8744e3c59..f3a0480d1 100644 --- a/spec/fixtures/rails51/db/seeds.rb +++ b/spec/fixtures/rails61/db/seeds.rb @@ -1,6 +1,5 @@ -# frozen_string_literal: true # This file should contain all the record creation needed to seed the database with its default values. -# The data can then be loaded with the rails db:seed command (or created alongside the database with db:setup). +# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). # # Examples: # diff --git a/spec/fixtures/rails52/app/controllers/concerns/.keep b/spec/fixtures/rails61/lib/assets/.keep similarity index 100% rename from spec/fixtures/rails52/app/controllers/concerns/.keep rename to spec/fixtures/rails61/lib/assets/.keep diff --git a/spec/fixtures/rails52/app/models/concerns/.keep b/spec/fixtures/rails61/lib/tasks/.keep similarity index 100% rename from spec/fixtures/rails52/app/models/concerns/.keep rename to spec/fixtures/rails61/lib/tasks/.keep diff --git a/spec/fixtures/rails52/lib/assets/.keep b/spec/fixtures/rails61/log/.keep similarity index 100% rename from spec/fixtures/rails52/lib/assets/.keep rename to spec/fixtures/rails61/log/.keep diff --git a/spec/fixtures/rails61/package.json b/spec/fixtures/rails61/package.json new file mode 100644 index 000000000..672812ed6 --- /dev/null +++ b/spec/fixtures/rails61/package.json @@ -0,0 +1,10 @@ +{ + "name": "rails61", + "private": true, + "dependencies": { + "@rails/ujs": "^6.0.0", + "turbolinks": "^5.2.0", + "@rails/actioncable": "^6.0.0" + }, + "version": "0.1.0" +} diff --git a/spec/fixtures/rails52/public/404.html b/spec/fixtures/rails61/public/404.html similarity index 100% rename from spec/fixtures/rails52/public/404.html rename to spec/fixtures/rails61/public/404.html diff --git a/spec/fixtures/rails52/public/422.html b/spec/fixtures/rails61/public/422.html similarity index 100% rename from spec/fixtures/rails52/public/422.html rename to spec/fixtures/rails61/public/422.html diff --git a/spec/fixtures/rails52/public/500.html b/spec/fixtures/rails61/public/500.html similarity index 100% rename from spec/fixtures/rails52/public/500.html rename to spec/fixtures/rails61/public/500.html diff --git a/spec/fixtures/rails52/public/apple-touch-icon-precomposed.png b/spec/fixtures/rails61/public/apple-touch-icon-precomposed.png similarity index 100% rename from spec/fixtures/rails52/public/apple-touch-icon-precomposed.png rename to spec/fixtures/rails61/public/apple-touch-icon-precomposed.png diff --git a/spec/fixtures/rails52/public/apple-touch-icon.png b/spec/fixtures/rails61/public/apple-touch-icon.png similarity index 100% rename from spec/fixtures/rails52/public/apple-touch-icon.png rename to spec/fixtures/rails61/public/apple-touch-icon.png diff --git a/spec/fixtures/rails52/public/favicon.ico b/spec/fixtures/rails61/public/favicon.ico similarity index 100% rename from spec/fixtures/rails52/public/favicon.ico rename to spec/fixtures/rails61/public/favicon.ico diff --git a/spec/fixtures/rails61/public/robots.txt b/spec/fixtures/rails61/public/robots.txt new file mode 100644 index 000000000..c19f78ab6 --- /dev/null +++ b/spec/fixtures/rails61/public/robots.txt @@ -0,0 +1 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/spec/fixtures/rails51/test/application_system_test_case.rb b/spec/fixtures/rails61/test/application_system_test_case.rb similarity index 83% rename from spec/fixtures/rails51/test/application_system_test_case.rb rename to spec/fixtures/rails61/test/application_system_test_case.rb index 93fada67a..d19212abd 100644 --- a/spec/fixtures/rails51/test/application_system_test_case.rb +++ b/spec/fixtures/rails61/test/application_system_test_case.rb @@ -1,4 +1,3 @@ -# frozen_string_literal: true require "test_helper" class ApplicationSystemTestCase < ActionDispatch::SystemTestCase diff --git a/spec/fixtures/rails61/test/channels/application_cable/connection_test.rb b/spec/fixtures/rails61/test/channels/application_cable/connection_test.rb new file mode 100644 index 000000000..800405f15 --- /dev/null +++ b/spec/fixtures/rails61/test/channels/application_cable/connection_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase + # test "connects with cookies" do + # cookies.signed[:user_id] = 42 + # + # connect + # + # assert_equal connection.user_id, "42" + # end +end diff --git a/spec/fixtures/rails52/lib/tasks/.keep b/spec/fixtures/rails61/test/controllers/.keep similarity index 100% rename from spec/fixtures/rails52/lib/tasks/.keep rename to spec/fixtures/rails61/test/controllers/.keep diff --git a/spec/fixtures/rails52/log/.keep b/spec/fixtures/rails61/test/fixtures/files/.keep similarity index 100% rename from spec/fixtures/rails52/log/.keep rename to spec/fixtures/rails61/test/fixtures/files/.keep diff --git a/spec/fixtures/rails61/test/fixtures/users.yml b/spec/fixtures/rails61/test/fixtures/users.yml new file mode 100644 index 000000000..7d4122404 --- /dev/null +++ b/spec/fixtures/rails61/test/fixtures/users.yml @@ -0,0 +1,7 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +one: + name: MyString + +two: + name: MyString diff --git a/spec/fixtures/rails52/storage/.keep b/spec/fixtures/rails61/test/helpers/.keep similarity index 100% rename from spec/fixtures/rails52/storage/.keep rename to spec/fixtures/rails61/test/helpers/.keep diff --git a/spec/fixtures/rails52/test/controllers/.keep b/spec/fixtures/rails61/test/integration/.keep similarity index 100% rename from spec/fixtures/rails52/test/controllers/.keep rename to spec/fixtures/rails61/test/integration/.keep diff --git a/spec/fixtures/rails52/test/fixtures/.keep b/spec/fixtures/rails61/test/mailers/.keep similarity index 100% rename from spec/fixtures/rails52/test/fixtures/.keep rename to spec/fixtures/rails61/test/mailers/.keep diff --git a/spec/fixtures/rails52/test/fixtures/files/.keep b/spec/fixtures/rails61/test/models/.keep similarity index 100% rename from spec/fixtures/rails52/test/fixtures/files/.keep rename to spec/fixtures/rails61/test/models/.keep diff --git a/spec/fixtures/rails61/test/models/user_test.rb b/spec/fixtures/rails61/test/models/user_test.rb new file mode 100644 index 000000000..5c07f4900 --- /dev/null +++ b/spec/fixtures/rails61/test/models/user_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/spec/fixtures/rails52/test/helpers/.keep b/spec/fixtures/rails61/test/system/.keep similarity index 100% rename from spec/fixtures/rails52/test/helpers/.keep rename to spec/fixtures/rails61/test/system/.keep diff --git a/spec/fixtures/rails51/test/test_helper.rb b/spec/fixtures/rails61/test/test_helper.rb similarity index 65% rename from spec/fixtures/rails51/test/test_helper.rb rename to spec/fixtures/rails61/test/test_helper.rb index 562b8c129..e9f0b367c 100644 --- a/spec/fixtures/rails51/test/test_helper.rb +++ b/spec/fixtures/rails61/test/test_helper.rb @@ -1,7 +1,6 @@ -# frozen_string_literal: true ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../config/environment', __dir__) -require 'rails/test_help' +require_relative "../config/environment" +require "rails/test_help" class ActiveSupport::TestCase # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. diff --git a/spec/fixtures/rails52/test/integration/.keep b/spec/fixtures/rails61/vendor/.keep similarity index 100% rename from spec/fixtures/rails52/test/integration/.keep rename to spec/fixtures/rails61/vendor/.keep diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 8c14c4612..3b2675af3 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -84,7 +84,8 @@ def self.it_fails_without_any_files(type) expect(result).to include '2 processes for 2 specs, ~ 1 spec per process' end - describe "--fail-fast" do + # Uses `Process.kill` under the hood, which on Windows doesn't work as expected. It kills all process group instead of just one process. + describe "--fail-fast", unless: Gem.win_platform? do def run_tests(test_option: nil) super( "spec", diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 0e43f1760..e73640520 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -13,8 +13,7 @@ def sh(command, options = {}) result end - # TODO: rails 6 - ['rails51', 'rails52'].each do |rails| + ['rails60', 'rails61'].each do |rails| it "can create and run #{rails}" do skip 'rails fixtures are not set up for java' if RUBY_PLATFORM == "java" @@ -25,7 +24,6 @@ def sh(command, options = {}) ENV.delete("RACK_ENV") sh "bundle config --local path vendor/bundle" - sh "bundle config --local force_ruby_platform true" sh "bundle install" sh "rm -rf db/*.sqlite3" sh "bundle exec rake db:setup parallel:create --trace 2>&1" From 4c1fa263069bb31ed177acec51925e1e6ac84f86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 25 Mar 2021 20:01:54 +0100 Subject: [PATCH 084/177] Run default test folder if no arguments passed (#809) --- CHANGELOG.md | 2 +- lib/parallel_tests/cli.rb | 6 +++++- lib/parallel_tests/cucumber/runner.rb | 4 ++++ lib/parallel_tests/gherkin/runner.rb | 4 ++++ lib/parallel_tests/rspec/runner.rb | 4 ++++ lib/parallel_tests/spinach/runner.rb | 4 ++++ lib/parallel_tests/test/runner.rb | 4 ++++ spec/integration_spec.rb | 18 ++++++++++++------ spec/parallel_tests/cli_spec.rb | 6 +++--- 9 files changed, 41 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 968097a1b..2448bb3e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Added -- None +- Run default test folder if no arguments are passed. ### Fixed diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 25f912c9f..33930bb86 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -274,7 +274,11 @@ def parse_options!(argv) files, remaining = extract_file_paths(argv) unless options[:execute] - abort "Pass files or folders to run" unless files.any? + if files.empty? + default_test_folder = @runner.default_test_folder + files = [default_test_folder] if File.directory?(default_test_folder) + abort "Pass files or folders to run" if files.empty? + end options[:files] = files.map { |file_path| Pathname.new(file_path).cleanpath.to_s } end diff --git a/lib/parallel_tests/cucumber/runner.rb b/lib/parallel_tests/cucumber/runner.rb index b47e548da..a352b43d0 100644 --- a/lib/parallel_tests/cucumber/runner.rb +++ b/lib/parallel_tests/cucumber/runner.rb @@ -12,6 +12,10 @@ def name 'cucumber' end + def default_test_folder + 'features' + end + def line_is_result?(line) super || line =~ SCENARIO_REGEX || line =~ SCENARIOS_RESULTS_BOUNDARY_REGEX end diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index 408e04e60..0253fd9ef 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -34,6 +34,10 @@ def test_file_name @test_file_name || 'feature' end + def default_test_folder + 'features' + end + def test_suffix /\.feature$/ end diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index 794cd063a..7c8b494cc 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -26,6 +26,10 @@ def runtime_log "tmp/parallel_runtime_rspec.log" end + def default_test_folder + "spec" + end + def test_file_name "spec" end diff --git a/lib/parallel_tests/spinach/runner.rb b/lib/parallel_tests/spinach/runner.rb index b57eeb4c9..20971457a 100644 --- a/lib/parallel_tests/spinach/runner.rb +++ b/lib/parallel_tests/spinach/runner.rb @@ -9,6 +9,10 @@ def name 'spinach' end + def default_test_folder + 'features' + end + def runtime_logging # Not Yet Supported "" diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 92e1d7628..5b34ae21d 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -15,6 +15,10 @@ def test_suffix /_(test|spec).rb$/ end + def default_test_folder + "test" + end + def test_file_name "test" end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 3b2675af3..1293e4285 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -54,8 +54,14 @@ def run_tests(test_folder, options = {}) result end - def self.it_fails_without_any_files(type) - it "fails without any files" do + def self.it_runs_the_default_folder_if_it_exists(type, test_folder) + it "runs the default folder if it exists" do + full_path_to_test_folder = File.join(folder, test_folder) + ensure_folder full_path_to_test_folder + results = run_tests("", fail: false, type: type) + expect(results).to_not include("Pass files or folders to run") + + FileUtils.remove_dir(full_path_to_test_folder, true) results = run_tests("", fail: true, type: type) expect(results).to include("Pass files or folders to run") end @@ -402,7 +408,7 @@ def test_unicode end context "RSpec" do - it_fails_without_any_files "rspec" + it_runs_the_default_folder_if_it_exists "rspec", "spec" it "captures seed with random failures with --verbose" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' @@ -426,7 +432,7 @@ def test_unicode expect(result).to include('test_xxx') # verbose output of every test end - it_fails_without_any_files "test" + it_runs_the_default_folder_if_it_exists "test", "test" end context "Cucumber" do @@ -480,7 +486,7 @@ def test_unicode expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end - it_fails_without_any_files "cucumber" + it_runs_the_default_folder_if_it_exists "cucumber", "features" it "collates failing scenarios" do write "features/pass.feature", "Feature: xxx\n Scenario: xxx\n Given I pass" @@ -596,7 +602,7 @@ class A < Spinach::FeatureSteps expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end - it_fails_without_any_files "spinach" + it_runs_the_default_folder_if_it_exists "spinach", "features" end describe "graceful shutdown" do diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index d01a33c8d..0e821336a 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -13,9 +13,9 @@ def call(*args) subject.send(:parse_options!, *args) end - it "fails without file" do - expect(subject).to receive(:abort).with("Pass files or folders to run") - call(["-n3"]) + it "does not fail without file" do + expect(subject).not_to receive(:abort) + call(["-n3", "-t", "rspec"]) end it "cleanups file paths" do From a57485734ed548f44e55316e5b1ddd9d9bd3dc35 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 25 Mar 2021 12:04:43 -0700 Subject: [PATCH 085/177] refactor --- lib/parallel_tests/cli.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 33930bb86..61197fd42 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -276,8 +276,11 @@ def parse_options!(argv) unless options[:execute] if files.empty? default_test_folder = @runner.default_test_folder - files = [default_test_folder] if File.directory?(default_test_folder) - abort "Pass files or folders to run" if files.empty? + if File.directory?(default_test_folder) + files = [default_test_folder] + else + abort "Pass files or folders to run" + end end options[:files] = files.map { |file_path| Pathname.new(file_path).cleanpath.to_s } end From df573f11453578ecee382a6bdb46cbbada50c941 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 25 Mar 2021 12:06:48 -0700 Subject: [PATCH 086/177] v3.6.0 --- CHANGELOG.md | 16 ++++++++++++---- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2448bb3e3..751fb5992 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,17 +8,25 @@ ### Added -- Run default test folder if no arguments are passed. +- None ### Fixed - None -### Dependencies +## v3.6.0 - 2021-03-25 -- Drop ruby 2.4 support. +### Breaking Changes -# Changelog +- Drop ruby 2.4 support + +### Added + +- Run default test folder if no arguments are passed. + +### Fixed + +- None ## v3.5.1 - 2021-03-07 diff --git a/Gemfile.lock b/Gemfile.lock index 8cf57cbda..d5270b8d9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.5.2) + parallel_tests (3.6.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 7867717ad..0e3040644 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.5.2' + VERSION = '3.6.0' end From e6b6d389a983e6666daff343dd16409a90cd8f33 Mon Sep 17 00:00:00 2001 From: Zach Dennis Date: Thu, 8 Apr 2021 12:47:04 -0400 Subject: [PATCH 087/177] Adding --highest-exit-status which returns the highest exit status from test runs (#812) rather than always exiting with 1 when running in parallel. The use-case for this is test suites that use exit statuses to communicate additional information besides failure such as marking a suite as unstable. This treats an exit status of 1 as a generic failure which is the default for most suites, and treats any error above 1 as being preferred when present. This change is backwards compatible for existing test suites that use parallel_tests. * Update Readme options with `bin/parallel_tests -h` * Updating changelog with the addition of the --highest-exit-status option * Updating Github test workflow to install bundler --- .github/workflows/test.yml | 1 + CHANGELOG.md | 2 +- Readme.md | 25 ++++++++-------- lib/parallel_tests/cli.rb | 17 ++++++++++- spec/integration_spec.rb | 58 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 15 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b68b0b662..8c81a9f4a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,6 +29,7 @@ jobs: - name: Setup OS dependencies uses: MSP-Greg/setup-ruby-pkgs@v1 with: + bundler: 2.2.15 ruby-version: ${{ matrix.ruby }} apt-get: libsqlite3-dev - name: Install dependencies diff --git a/CHANGELOG.md b/CHANGELOG.md index 751fb5992..c2899adf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Added -- None +- Added `--highest-exit-status` option to return the highest exit status to allow sub-processes to send things other than 1 ### Fixed diff --git a/Readme.md b/Readme.md index a6195e2a2..6fc1a7c16 100644 --- a/Readme.md +++ b/Readme.md @@ -202,22 +202,21 @@ Options are: -p, --pattern [PATTERN] run tests matching this regex pattern --exclude-pattern [PATTERN] exclude tests matching this regex pattern --group-by [TYPE] group tests by: - found - order of finding files - steps - number of cucumber/spinach steps - scenarios - individual cucumber scenarios - filesize - by size of the file - runtime - info from runtime log - default - runtime when runtime log is filled otherwise filesize + found - order of finding files + steps - number of cucumber/spinach steps + scenarios - individual cucumber scenarios + filesize - by size of the file + runtime - info from runtime log + default - runtime when runtime log is filled otherwise filesize -m, --multiply-processes [FLOAT] use given number as a multiplier of processes to run -s, --single [PATTERN] Run all matching files in the same process - -i, --isolate Do not run any other tests in the group used by --single(-s). - Automatically turned on if --isolate-n is set above 0. - --isolate-n Number of processes for isolated groups. Default to 1 when --isolate is on. + -i, --isolate Do not run any other tests in the group used by --single(-s) + --isolate-n [PROCESSES] Use 'isolate' singles with number of processes, default: 1. + --highest-exit-status Exit with the highest exit status provided by test run(s) --specify-groups [SPECS] Use 'specify-groups' if you want to specify multiple specs running in multiple processes in a specific formation. Commas indicate specs in the same process, - pipes indicate specs in a new process. Cannot use with --single, --isolate, or + pipes indicate specs in a new process. Cannot use with --single, --isolate, or --isolate-n. Ex. - Ex. $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' Process 1 will contain 1_spec.rb and 2_spec.rb Process 2 will contain 3_spec.rb @@ -227,8 +226,8 @@ Options are: -o, --test-options '[OPTIONS]' execute test commands with those options -t, --type [TYPE] test(default) / rspec / cucumber / spinach --suffix [PATTERN] override built in test file pattern (should match suffix): - '_spec.rb$' - matches rspec files - '_(test|spec).rb$' - matches test or spec files + '_spec.rb$' - matches rspec files + '_(test|spec).rb$' - matches test or spec files --serialize-stdout Serialize stdout output, nothing will be written until everything is done --prefix-output-with-test-env-number Prefixes test env number to the output when not using --serialize-stdout diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 61197fd42..860f8ff29 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -84,7 +84,18 @@ def run_tests_in_parallel(num_processes, options) report_time_taken(&run_tests_proc) end - abort final_fail_message if any_test_failed?(test_results) + if any_test_failed?(test_results) + warn final_fail_message + + # return the highest exit status to allow sub-processes to send things other than 1 + exit_status = if options[:highest_exit_status] + test_results.map { |data| data.fetch(:exit_status) }.max + else + 1 + end + + exit exit_status + end end def run_tests(group, process_number, num_processes, options) @@ -207,6 +218,10 @@ def parse_options!(argv) "Use 'isolate' singles with number of processes, default: 1." ) { |n| options[:isolate_count] = n } + opts.on("--highest-exit-status", "Exit with the highest exit status provided by test run(s)") do + options[:highest_exit_status] = true + end + opts.on( "--specify-groups [SPECS]", <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 1293e4285..d4bc3d03c 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -70,6 +70,35 @@ def self.it_runs_the_default_folder_if_it_exists(type, test_folder) let(:printed_commands) { /specs? per process\nbundle exec rspec/ } let(:printed_rerun) { "run the group again:\n\nbundle exec rspec" } + context "running tests sequentially" do + it "exits with 0 when each run is successful" do + run_tests "spec", type: 'rspec', fail: 0 + end + + it "exits with 1 when a test run fails" do + write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){ expect(true).to be false }}' + run_tests "spec", type: 'rspec', fail: 1 + end + + it "exits with 1 even when the test run exits with a different status" do + write 'spec/xxx2_spec.rb', <<~SPEC + RSpec.configure { |c| c.failure_exit_code = 99 } + describe("it"){it("should"){ expect(true).to be false }} + SPEC + + run_tests "spec", type: 'rspec', fail: 1 + end + + it "exits with the highest exit status" do + write 'spec/xxx2_spec.rb', <<~SPEC + RSpec.configure { |c| c.failure_exit_code = 99 } + describe("it"){it("should"){ expect(true).to be false }} + SPEC + + run_tests "spec", type: 'rspec', add: "--highest-exit-status", fail: 99 + end + end + it "runs tests in parallel" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){puts "TEST2"}}' @@ -90,6 +119,35 @@ def self.it_runs_the_default_folder_if_it_exists(type, test_folder) expect(result).to include '2 processes for 2 specs, ~ 1 spec per process' end + context "running test in parallel" do + it "exits with 0 when each run is successful" do + run_tests "spec", type: 'rspec', processes: 4, fail: 0 + end + + it "exits with 1 when a test run fails" do + write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){ expect(true).to be false }}' + run_tests "spec", type: 'rspec', processes: 4, fail: 1 + end + + it "exits with 1 even when the test run exits with a different status" do + write 'spec/xxx2_spec.rb', <<~SPEC + RSpec.configure { |c| c.failure_exit_code = 99 } + describe("it"){it("should"){ expect(true).to be false }} + SPEC + + run_tests "spec", type: 'rspec', processes: 4, fail: 1 + end + + it "exits with the highest exit status" do + write 'spec/xxx2_spec.rb', <<~SPEC + RSpec.configure { |c| c.failure_exit_code = 99 } + describe("it"){it("should"){ expect(true).to be false }} + SPEC + + run_tests "spec", type: 'rspec', processes: 4, add: "--highest-exit-status", fail: 99 + end + end + # Uses `Process.kill` under the hood, which on Windows doesn't work as expected. It kills all process group instead of just one process. describe "--fail-fast", unless: Gem.win_platform? do def run_tests(test_option: nil) From 9a141390293d712d31736184bb8407c707139e14 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 8 Apr 2021 09:48:08 -0700 Subject: [PATCH 088/177] v3.7.0 --- CHANGELOG.md | 14 ++++++++++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2899adf0..9571c1a7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,20 @@ ### Added +- None + +### Fixed + +- None + +## v3.7.0 - 2021-04-08 + +### Breaking Changes + +- None + +### Added + - Added `--highest-exit-status` option to return the highest exit status to allow sub-processes to send things other than 1 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index d5270b8d9..2f66c7948 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.6.0) + parallel_tests (3.7.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 0e3040644..e4c871431 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.6.0' + VERSION = '3.7.0' end From afbd50a3f6d8870d18dc14329401dc64adfcad6c Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 8 Apr 2021 09:49:54 -0700 Subject: [PATCH 089/177] thx for the PR --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 6fc1a7c16..c88a03fd5 100644 --- a/Readme.md +++ b/Readme.md @@ -393,6 +393,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Nathan Broadbent](https://github.com/ndbroadbent) - [Vikram B Kumar](https://github.com/v-kumar) - [Joshua Pinter](https://github.com/joshuapinter) + - [Zach Dennis](https://github.com/zdennis) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 9bc92338e2668ca4c2df81ba79a38759fcee2300 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 8 Apr 2021 10:06:20 -0700 Subject: [PATCH 090/177] do not hardcode bundler (#813) --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8c81a9f4a..b68b0b662 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,7 +29,6 @@ jobs: - name: Setup OS dependencies uses: MSP-Greg/setup-ruby-pkgs@v1 with: - bundler: 2.2.15 ruby-version: ${{ matrix.ruby }} apt-get: libsqlite3-dev - name: Install dependencies From 13948eee13bb8a7f458ee0d6461030165d02aedd Mon Sep 17 00:00:00 2001 From: Luke Hill <20105237+luke-hill@users.noreply.github.com> Date: Wed, 11 Aug 2021 16:30:43 +0100 Subject: [PATCH 091/177] Update Readme.md (#826) * Update Readme.md * CR changes --- Readme.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/Readme.md b/Readme.md index c88a03fd5..4caa9e511 100644 --- a/Readme.md +++ b/Readme.md @@ -182,19 +182,24 @@ Setup for non-rails gem install parallel_tests # go to your project dir - parallel_test test/ - parallel_rspec spec/ - parallel_cucumber features/ - parallel_spinach features/ + parallel_test + parallel_rspec + parallel_cucumber + parallel_spinach - - use `ENV['TEST_ENV_NUMBER']` inside your tests to select separate db/memcache/etc. - - Only run selected files & folders: + - use `ENV['TEST_ENV_NUMBER']` inside your tests to select separate db/memcache/etc. (docker compose: expose it) + - Only run a subset of files / folders: + `parallel_test test/bar test/baz/foo_text.rb` - Pass test-options and files via `--`: - - `parallel_test -- -t acceptance -f progress -- spec/foo_spec.rb spec/acceptance` + + `parallel_rspec -- -t acceptance -f progress -- spec/foo_spec.rb spec/acceptance` + + - Pass in test options, by using the -o flag (wrap everything in quotes): + + `parallel_cucumber -n 2 -o '-p foo_profile --tags @only_this_tag or @only_that_tag --format summary'` Options are: From 3e664853001e201eb02c79645f4a84cfc6a48ad9 Mon Sep 17 00:00:00 2001 From: Luke Hill <20105237+luke-hill@users.noreply.github.com> Date: Sat, 14 Aug 2021 00:39:16 +0100 Subject: [PATCH 092/177] Permit parallel_tests/cucumber running to allow --retry flag (#827) * Initial copy of debug logic * It seems as though pushing all cucumber options to the end of the command invocation also works! * Update rails bundles for fixtures * Attempt to fix specs --- CHANGELOG.md | 3 ++- lib/parallel_tests/gherkin/runner.rb | 4 ++-- spec/fixtures/rails60/Gemfile.lock | 4 ++-- spec/fixtures/rails61/Gemfile.lock | 4 ++-- spec/parallel_tests/gherkin/runner_behaviour.rb | 12 ++++++------ 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9571c1a7e..ce24b5c92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ ### Fixed -- None +- All cucumber options are now pushed to the end of the command invocation + - Fixes an issue where the `--retry` flag wouldn't work correctly ## v3.7.0 - 2021-04-08 diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index 0253fd9ef..5e2b7bb0d 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -24,8 +24,8 @@ def run_tests(test_files, process_number, num_processes, options) cmd = [ executable, (runtime_logging if File.directory?(File.dirname(runtime_log))), - cucumber_opts(options[:test_options]), - *sanitized_test_files + *sanitized_test_files, + cucumber_opts(options[:test_options]) ].compact.reject(&:empty?).join(' ') execute_command(cmd, process_number, num_processes, options) end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index e27df67c7..56b811637 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.5.2) + parallel_tests (3.7.0) parallel GEM @@ -121,4 +121,4 @@ DEPENDENCIES tzinfo-data BUNDLED WITH - 2.2.15 + 2.2.19 diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index f261b9561..53ae4530b 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.5.2) + parallel_tests (3.7.0) parallel GEM @@ -122,4 +122,4 @@ DEPENDENCIES tzinfo-data BUNDLED WITH - 2.2.15 + 2.2.19 diff --git a/spec/parallel_tests/gherkin/runner_behaviour.rb b/spec/parallel_tests/gherkin/runner_behaviour.rb index f8b6eaad1..f6451bb0e 100644 --- a/spec/parallel_tests/gherkin/runner_behaviour.rb +++ b/spec/parallel_tests/gherkin/runner_behaviour.rb @@ -74,9 +74,9 @@ def call(*args) it "uses parallel profile" do if ParallelTests::WINDOWS - should_run_with %r{script/#{runner_name} .*foo bar --profile parallel "xxx"} + should_run_with %r{script/#{runner_name} "xxx" .*foo bar --profile parallel} else - should_run_with %r{script/#{runner_name} .*foo bar --profile parallel xxx} + should_run_with %r{script/#{runner_name} xxx .*foo bar --profile parallel} end call(['xxx'], 1, 22, test_options: 'foo bar') @@ -84,9 +84,9 @@ def call(*args) it "uses given profile via --profile" do if ParallelTests::WINDOWS - should_run_with %r{script/#{runner_name} .*--profile foo "xxx"$} + should_run_with %r{script/#{runner_name} "xxx" .*--profile foo$} else - should_run_with %r{script/#{runner_name} .*--profile foo xxx$} + should_run_with %r{script/#{runner_name} xxx .*--profile foo$} end call(['xxx'], 1, 22, test_options: '--profile foo') @@ -94,9 +94,9 @@ def call(*args) it "uses given profile via -p" do if ParallelTests::WINDOWS - should_run_with %r{script/#{runner_name} .*-p foo "xxx"$} + should_run_with %r{script/#{runner_name} "xxx" .*-p foo$} else - should_run_with %r{script/#{runner_name} .*-p foo xxx$} + should_run_with %r{script/#{runner_name} xxx .*-p foo$} end call(['xxx'], 1, 22, test_options: '-p foo') From 3faf81cd1bd11e36d1259c86cb994492c7331e64 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 13 Aug 2021 16:39:41 -0700 Subject: [PATCH 093/177] v3.7.1 --- Gemfile.lock | 4 ++-- lib/parallel_tests/version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 2f66c7948..0d3f481cf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.7.0) + parallel_tests (3.7.1) parallel GEM @@ -129,4 +129,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 2.2.15 + 2.2.16 diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index e4c871431..f81347df7 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.7.0' + VERSION = '3.7.1' end From 020ff977449f8162f66663251fea2425644cdc80 Mon Sep 17 00:00:00 2001 From: Pavel Lobashov Date: Mon, 16 Aug 2021 17:28:11 +0300 Subject: [PATCH 094/177] Fix missing v3.7.1 changelog entry (#828) --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce24b5c92..05302e7af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,20 @@ ### Fixed +- None + +## v3.7.1 - 2021-08-14 + +### Breaking Changes + +- None + +### Added + +- None + +### Fixed + - All cucumber options are now pushed to the end of the command invocation - Fixes an issue where the `--retry` flag wouldn't work correctly From 8fb07f49649b7c3e2a221076df6314f0443f00bd Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 24 Aug 2021 14:33:57 -0700 Subject: [PATCH 095/177] v3.7.2 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0d3f481cf..d9aeb87a6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.7.1) + parallel_tests (3.7.2) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index f81347df7..da3a2b590 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.7.1' + VERSION = '3.7.2' end From f7e7b8dcf1a5e205fa219ad857d290bd7b56d650 Mon Sep 17 00:00:00 2001 From: Sean <11340230+seanfcarroll@users.noreply.github.com> Date: Thu, 26 Aug 2021 21:16:49 +0200 Subject: [PATCH 096/177] Add documentation for `rake parallel:drop` (#830) --- Readme.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Readme.md b/Readme.md index 4caa9e511..3597a4b56 100644 --- a/Readme.md +++ b/Readme.md @@ -42,6 +42,9 @@ test: ### Setup environment from scratch (create db and loads schema, useful for CI) rake parallel:setup + +### Drop all test databases + rake parallel:drop ### Run! rake parallel:test # Test::Unit From 01218db8d43fab939fe5b53738af1fab771373dd Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 17 Sep 2021 15:57:25 -0700 Subject: [PATCH 097/177] allow running test files with multiple spaces (#832) --- lib/parallel_tests/test/runner.rb | 2 +- spec/integration_spec.rb | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 5b34ae21d..67283dfb2 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -24,7 +24,7 @@ def test_file_name end def run_tests(test_files, process_number, num_processes, options) - require_list = test_files.map { |file| file.sub(" ", "\\ ") }.join(" ") + require_list = test_files.map { |file| file.gsub(" ", "\\ ") }.join(" ") cmd = "#{executable} -Itest -e '%w[#{require_list}].each { |f| require %{./\#{f}} }' -- #{options[:test_options]}" execute_command(cmd, process_number, num_processes, options) end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index d4bc3d03c..b5c136080 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -465,6 +465,12 @@ def test_unicode ) end + it "can run with uncommon file names" do + skip if RUBY_PLATFORM == "java" # just too slow ... + write "test/long ( stuff ) _test.rb", "puts 'hey'" + expect(run_tests("test", processes: 2)).to include("hey") + end + context "RSpec" do it_runs_the_default_folder_if_it_exists "rspec", "spec" From e1bc5c5528e7a8542cee109571501f46cac712ba Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 17 Sep 2021 15:58:03 -0700 Subject: [PATCH 098/177] v3.7.3 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index d9aeb87a6..1da3a6bca 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (3.7.2) + parallel_tests (3.7.3) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index da3a2b590..ea84bda6f 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.7.2' + VERSION = '3.7.3' end From 9426f7b705f04a32fb3e1e97363688c8118dec00 Mon Sep 17 00:00:00 2001 From: Julio AG Date: Sat, 26 Mar 2022 16:43:33 +0100 Subject: [PATCH 099/177] Add Rails 7 to spec pool and fix deprecation warning (#842) * Adds Rails 7 skeleton app Generated with: ``` rails new spec/fixtures/rails70 --skip-listen --skip-spring --skip-bootsnap --skip-sprockets --skip-gemfile --skip-webpack-install rm -rf spec/fixtures/rails70/.git ``` And some gemfile cleanup * Add new rails version to the list * Check for Rails version in tasks to avoid deprecation warnings > rails parallel:create DEPRECATION WARNING: ActiveRecord::Base.schema_format is deprecated and will be removed in Rails 7.1. Use `ActiveRecord.schema_format` instead. (called from
at bin/rails:4) /Users/julio/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/parallel_tests-3.7.3/lib/parallel_tests/tasks.rb:124:in `block (2 levels) in ' * These changed after running rspec * Version bump and changelog entry * Remove active_storage from the stack * Add database configuration and content for specs to work This is a combination of: -> cd into the rails70 app folder -> change config/database.yml to support parallel specs -> rails db:create -> rails g model user name:string -> rails db:migrate -> rails db:drop (remove db for specs to run) -> cd back to the main gem folder * Add platforms bundle lock --add-platform x86_64-linux bundle lock --add-platform x64-mingw32 * Un-bump version and put changelog in unreleased * Clean up code after code review comments, extracting checks to methods Unsure ParallelTests::Tasks is the better place for those, tho * Rubocop fixes * Drop old Ruby versions, add 3.1 2.6 will be EOL in 9 days from now, so that's why I'm removing it * Drop compatibility for unmaintained ruby versions * Switch default for spec, since atm every run runs rubocop and it should only be 1 * Specify target ruby version compatible with gemspec requirement * Bundle with bundler 2.3.7 to try and solve issues with Ruby 3.1 builds * Run rubocop -A after the change in target rubocop version from 2.5 to 2.7 * Rebundle fixtures with bundler 2.3.7 * Leave Ruby 3.1 out --- .github/workflows/test.yml | 6 +- .rubocop.yml | 2 +- CHANGELOG.md | 5 +- Gemfile.lock | 2 +- lib/parallel_tests/cli.rb | 4 +- .../cucumber/scenario_line_logger.rb | 2 +- lib/parallel_tests/gherkin/runner.rb | 2 +- lib/parallel_tests/grouper.rb | 2 +- lib/parallel_tests/tasks.rb | 36 ++++- parallel_tests.gemspec | 2 +- spec/fixtures/rails60/Gemfile.lock | 50 +++---- spec/fixtures/rails61/Gemfile.lock | 50 +++---- spec/fixtures/rails70/.gitattributes | 7 + spec/fixtures/rails70/.gitignore | 35 +++++ spec/fixtures/rails70/.ruby-version | 1 + spec/fixtures/rails70/Gemfile | 18 +++ spec/fixtures/rails70/Gemfile.lock | 139 ++++++++++++++++++ spec/fixtures/rails70/README.md | 24 +++ spec/fixtures/rails70/Rakefile | 6 + .../rails70/app/assets/config/manifest.js | 4 + spec/fixtures/rails70/app/assets/images/.keep | 0 .../app/assets/stylesheets/application.css | 15 ++ .../app/channels/application_cable/channel.rb | 4 + .../channels/application_cable/connection.rb | 4 + .../app/controllers/application_controller.rb | 2 + .../rails70/app/controllers/concerns/.keep | 0 .../rails70/app/helpers/application_helper.rb | 2 + .../rails70/app/javascript/application.js | 3 + .../app/javascript/controllers/application.js | 9 ++ .../controllers/hello_controller.js | 7 + .../app/javascript/controllers/index.js | 11 ++ .../rails70/app/jobs/application_job.rb | 7 + .../rails70/app/mailers/application_mailer.rb | 4 + .../rails70/app/models/application_record.rb | 3 + .../rails70/app/models/concerns/.keep | 0 spec/fixtures/rails70/app/models/user.rb | 2 + .../app/views/layouts/application.html.erb | 16 ++ .../rails70/app/views/layouts/mailer.html.erb | 13 ++ .../rails70/app/views/layouts/mailer.text.erb | 1 + spec/fixtures/rails70/bin/bundle | 114 ++++++++++++++ spec/fixtures/rails70/bin/importmap | 4 + spec/fixtures/rails70/bin/rails | 4 + spec/fixtures/rails70/bin/rake | 4 + spec/fixtures/rails70/bin/setup | 33 +++++ spec/fixtures/rails70/config.ru | 6 + spec/fixtures/rails70/config/application.rb | 35 +++++ spec/fixtures/rails70/config/boot.rb | 3 + spec/fixtures/rails70/config/cable.yml | 10 ++ .../rails70/config/credentials.yml.enc | 1 + spec/fixtures/rails70/config/database.yml | 25 ++++ spec/fixtures/rails70/config/environment.rb | 5 + .../config/environments/development.rb | 70 +++++++++ .../rails70/config/environments/production.rb | 93 ++++++++++++ .../rails70/config/environments/test.rb | 60 ++++++++ spec/fixtures/rails70/config/importmap.rb | 7 + .../rails70/config/initializers/assets.rb | 12 ++ .../initializers/content_security_policy.rb | 26 ++++ .../initializers/filter_parameter_logging.rb | 8 + .../config/initializers/inflections.rb | 16 ++ .../config/initializers/permissions_policy.rb | 11 ++ spec/fixtures/rails70/config/locales/en.yml | 33 +++++ spec/fixtures/rails70/config/puma.rb | 43 ++++++ spec/fixtures/rails70/config/routes.rb | 6 + spec/fixtures/rails70/config/storage.yml | 34 +++++ .../db/migrate/20220322153446_create_users.rb | 9 ++ spec/fixtures/rails70/db/schema.rb | 20 +++ spec/fixtures/rails70/db/seeds.rb | 7 + spec/fixtures/rails70/lib/assets/.keep | 0 spec/fixtures/rails70/lib/tasks/.keep | 0 spec/fixtures/rails70/log/.keep | 0 spec/fixtures/rails70/public/404.html | 67 +++++++++ spec/fixtures/rails70/public/422.html | 67 +++++++++ spec/fixtures/rails70/public/500.html | 66 +++++++++ .../public/apple-touch-icon-precomposed.png | 0 .../rails70/public/apple-touch-icon.png | 0 spec/fixtures/rails70/public/favicon.ico | 0 spec/fixtures/rails70/public/robots.txt | 1 + spec/fixtures/rails70/storage/.keep | 0 .../test/application_system_test_case.rb | 5 + .../application_cable/connection_test.rb | 11 ++ spec/fixtures/rails70/test/controllers/.keep | 0 .../rails70/test/fixtures/files/.keep | 0 spec/fixtures/rails70/test/fixtures/users.yml | 11 ++ spec/fixtures/rails70/test/helpers/.keep | 0 spec/fixtures/rails70/test/integration/.keep | 0 spec/fixtures/rails70/test/mailers/.keep | 0 spec/fixtures/rails70/test/models/.keep | 0 .../fixtures/rails70/test/models/user_test.rb | 7 + spec/fixtures/rails70/test/system/.keep | 0 spec/fixtures/rails70/test/test_helper.rb | 13 ++ spec/fixtures/rails70/vendor/.keep | 0 spec/fixtures/rails70/vendor/javascript/.keep | 0 spec/rails_spec.rb | 2 +- spec/spec_helper.rb | 2 +- 94 files changed, 1379 insertions(+), 72 deletions(-) create mode 100644 spec/fixtures/rails70/.gitattributes create mode 100644 spec/fixtures/rails70/.gitignore create mode 100644 spec/fixtures/rails70/.ruby-version create mode 100644 spec/fixtures/rails70/Gemfile create mode 100644 spec/fixtures/rails70/Gemfile.lock create mode 100644 spec/fixtures/rails70/README.md create mode 100644 spec/fixtures/rails70/Rakefile create mode 100644 spec/fixtures/rails70/app/assets/config/manifest.js create mode 100644 spec/fixtures/rails70/app/assets/images/.keep create mode 100644 spec/fixtures/rails70/app/assets/stylesheets/application.css create mode 100644 spec/fixtures/rails70/app/channels/application_cable/channel.rb create mode 100644 spec/fixtures/rails70/app/channels/application_cable/connection.rb create mode 100644 spec/fixtures/rails70/app/controllers/application_controller.rb create mode 100644 spec/fixtures/rails70/app/controllers/concerns/.keep create mode 100644 spec/fixtures/rails70/app/helpers/application_helper.rb create mode 100644 spec/fixtures/rails70/app/javascript/application.js create mode 100644 spec/fixtures/rails70/app/javascript/controllers/application.js create mode 100644 spec/fixtures/rails70/app/javascript/controllers/hello_controller.js create mode 100644 spec/fixtures/rails70/app/javascript/controllers/index.js create mode 100644 spec/fixtures/rails70/app/jobs/application_job.rb create mode 100644 spec/fixtures/rails70/app/mailers/application_mailer.rb create mode 100644 spec/fixtures/rails70/app/models/application_record.rb create mode 100644 spec/fixtures/rails70/app/models/concerns/.keep create mode 100644 spec/fixtures/rails70/app/models/user.rb create mode 100644 spec/fixtures/rails70/app/views/layouts/application.html.erb create mode 100644 spec/fixtures/rails70/app/views/layouts/mailer.html.erb create mode 100644 spec/fixtures/rails70/app/views/layouts/mailer.text.erb create mode 100755 spec/fixtures/rails70/bin/bundle create mode 100755 spec/fixtures/rails70/bin/importmap create mode 100755 spec/fixtures/rails70/bin/rails create mode 100755 spec/fixtures/rails70/bin/rake create mode 100755 spec/fixtures/rails70/bin/setup create mode 100644 spec/fixtures/rails70/config.ru create mode 100644 spec/fixtures/rails70/config/application.rb create mode 100644 spec/fixtures/rails70/config/boot.rb create mode 100644 spec/fixtures/rails70/config/cable.yml create mode 100644 spec/fixtures/rails70/config/credentials.yml.enc create mode 100644 spec/fixtures/rails70/config/database.yml create mode 100644 spec/fixtures/rails70/config/environment.rb create mode 100644 spec/fixtures/rails70/config/environments/development.rb create mode 100644 spec/fixtures/rails70/config/environments/production.rb create mode 100644 spec/fixtures/rails70/config/environments/test.rb create mode 100644 spec/fixtures/rails70/config/importmap.rb create mode 100644 spec/fixtures/rails70/config/initializers/assets.rb create mode 100644 spec/fixtures/rails70/config/initializers/content_security_policy.rb create mode 100644 spec/fixtures/rails70/config/initializers/filter_parameter_logging.rb create mode 100644 spec/fixtures/rails70/config/initializers/inflections.rb create mode 100644 spec/fixtures/rails70/config/initializers/permissions_policy.rb create mode 100644 spec/fixtures/rails70/config/locales/en.yml create mode 100644 spec/fixtures/rails70/config/puma.rb create mode 100644 spec/fixtures/rails70/config/routes.rb create mode 100644 spec/fixtures/rails70/config/storage.yml create mode 100644 spec/fixtures/rails70/db/migrate/20220322153446_create_users.rb create mode 100644 spec/fixtures/rails70/db/schema.rb create mode 100644 spec/fixtures/rails70/db/seeds.rb create mode 100644 spec/fixtures/rails70/lib/assets/.keep create mode 100644 spec/fixtures/rails70/lib/tasks/.keep create mode 100644 spec/fixtures/rails70/log/.keep create mode 100644 spec/fixtures/rails70/public/404.html create mode 100644 spec/fixtures/rails70/public/422.html create mode 100644 spec/fixtures/rails70/public/500.html create mode 100644 spec/fixtures/rails70/public/apple-touch-icon-precomposed.png create mode 100644 spec/fixtures/rails70/public/apple-touch-icon.png create mode 100644 spec/fixtures/rails70/public/favicon.ico create mode 100644 spec/fixtures/rails70/public/robots.txt create mode 100644 spec/fixtures/rails70/storage/.keep create mode 100644 spec/fixtures/rails70/test/application_system_test_case.rb create mode 100644 spec/fixtures/rails70/test/channels/application_cable/connection_test.rb create mode 100644 spec/fixtures/rails70/test/controllers/.keep create mode 100644 spec/fixtures/rails70/test/fixtures/files/.keep create mode 100644 spec/fixtures/rails70/test/fixtures/users.yml create mode 100644 spec/fixtures/rails70/test/helpers/.keep create mode 100644 spec/fixtures/rails70/test/integration/.keep create mode 100644 spec/fixtures/rails70/test/mailers/.keep create mode 100644 spec/fixtures/rails70/test/models/.keep create mode 100644 spec/fixtures/rails70/test/models/user_test.rb create mode 100644 spec/fixtures/rails70/test/system/.keep create mode 100644 spec/fixtures/rails70/test/test_helper.rb create mode 100644 spec/fixtures/rails70/vendor/.keep create mode 100644 spec/fixtures/rails70/vendor/javascript/.keep diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b68b0b662..d6cbf2b00 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,11 +13,11 @@ jobs: strategy: fail-fast: false matrix: - ruby: ['3.0', '2.7', '2.6', '2.5', head, jruby-head] + ruby: ['3.0', '2.7', head, jruby-head] os: [ubuntu-latest, windows-latest] - task: [default] + task: [spec] include: - - ruby: '2.5' # lowest supported version + - ruby: '2.7' # lowest supported version os: ubuntu-latest task: rubocop env: diff --git a/.rubocop.yml b/.rubocop.yml index 67bb29d84..7c4a4f965 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,6 @@ AllCops: NewCops: enable - TargetRubyVersion: 2.5 + TargetRubyVersion: 2.7 SuggestExtensions: false Exclude: - '**/vendor/bundle/**/*' diff --git a/CHANGELOG.md b/CHANGELOG.md index 05302e7af..726883cd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ ### Fixed -- None +- Added Rails 7.0 to fixtures +- Fixes deprecation warning around the usage of `ActiveRecord::Base.schema_format` and deprecation in Rails 7.1 ## v3.7.1 - 2021-08-14 @@ -27,7 +28,7 @@ ### Fixed - All cucumber options are now pushed to the end of the command invocation - - Fixes an issue where the `--retry` flag wouldn't work correctly + - Fixes an issue where the `--retry` flag wouldn't work correctly ## v3.7.0 - 2021-04-08 diff --git a/Gemfile.lock b/Gemfile.lock index 1da3a6bca..bfcb090f8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -129,4 +129,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 2.2.16 + 2.3.7 diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 860f8ff29..ce31e979a 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -322,12 +322,12 @@ def parse_options!(argv) def extract_file_paths(argv) dash_index = argv.rindex("--") file_args_at = (dash_index || -1) + 1 - [argv[file_args_at..-1], argv[0...(dash_index || 0)]] + [argv[file_args_at..], argv[0...(dash_index || 0)]] end def extract_test_options(argv) dash_index = argv.index("--") || -1 - argv[dash_index + 1..-1] + argv[dash_index + 1..] end def append_test_options(options, argv) diff --git a/lib/parallel_tests/cucumber/scenario_line_logger.rb b/lib/parallel_tests/cucumber/scenario_line_logger.rb index 74a99b52a..bd47b7ada 100644 --- a/lib/parallel_tests/cucumber/scenario_line_logger.rb +++ b/lib/parallel_tests/cucumber/scenario_line_logger.rb @@ -27,7 +27,7 @@ def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) example_tags = example.tags.map(&:name) example_tags = scenario_tags + example_tags next unless matches_tags?(example_tags) - example.rows[1..-1].each do |row| + example.rows[1..].each do |row| test_line = row.source_line next if line_numbers.any? && !line_numbers.include?(test_line) diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index 5e2b7bb0d..7718b5197 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -62,7 +62,7 @@ def summarize_results(results) plural = "s" if (word == group) && (number != 1) "#{number} #{word}#{plural}" end - "#{sums[0]} (#{sums[1..-1].join(", ")})" + "#{sums[0]} (#{sums[1..].join(", ")})" end.compact.join("\n") end diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index 959339f16..fd2229d97 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -38,7 +38,7 @@ def in_even_groups_by_size(items, num_groups, options = {}) # add all files that should run in a multiple isolated processes to their own groups group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)]) # group the non-isolated by size - group_features_by_size(items_to_group(items), groups[isolate_count..-1]) + group_features_by_size(items_to_group(items), groups[isolate_count..]) else # add all files that should run in a single non-isolated process to first group single_items.each { |item, size| add_to_group(groups.first, item, size) } diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index ee900c3a6..57cc4f99d 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -92,6 +92,32 @@ def parse_args(args) [num_processes, pattern.to_s, options.to_s, pass_through.to_s] end + + def schema_format_based_on_rails_version + if rails_7_or_greater? + ActiveRecord.schema_format + else + ActiveRecord::Base.schema_format + end + end + + def schema_type_based_on_rails_version + if rails_61_or_greater? || schema_format_based_on_rails_version == :ruby + "schema" + else + "structure" + end + end + + private + + def rails_7_or_greater? + Gem::Version.new(Rails.version) >= Gem::Version.new('7.0') + end + + def rails_61_or_greater? + Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') + end end end end @@ -121,14 +147,10 @@ def parse_args(args) desc "Update test databases by dumping and loading --> parallel:prepare[num_cpus]" task(:prepare, [:count]) do |_, args| ParallelTests::Tasks.check_for_pending_migrations - if defined?(ActiveRecord::Base) && [:ruby, :sql].include?(ActiveRecord::Base.schema_format) + + if defined?(ActiveRecord) && [:ruby, :sql].include?(ParallelTests::Tasks.schema_format_based_on_rails_version) # fast: dump once, load in parallel - type = - if Gem::Version.new(Rails.version) >= Gem::Version.new('6.1.0') - "schema" - else - ActiveRecord::Base.schema_format == :ruby ? "schema" : "structure" - end + type = ParallelTests::Tasks.schema_type_based_on_rails_version Rake::Task["db:#{type}:dump"].invoke diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index b6d5f3f9d..3eb00e26c 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,5 +17,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.5.0' + s.required_ruby_version = '>= 2.7.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 56b811637..73bba341c 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.7.0) + parallel_tests (3.7.3) parallel GEM @@ -45,35 +45,33 @@ GEM tzinfo (~> 1.1) zeitwerk (~> 2.2, >= 2.2.2) builder (3.2.4) - concurrent-ruby (1.1.8) + concurrent-ruby (1.1.10) crass (1.0.6) erubi (1.10.0) - globalid (0.4.2) - activesupport (>= 4.2.0) - i18n (1.8.9) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.10.0) concurrent-ruby (~> 1.0) - loofah (2.9.0) + loofah (2.15.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) method_source (1.0.0) - mini_mime (1.0.2) - minitest (5.14.4) - nio4r (2.5.7) - nokogiri (1.11.2-x64-mingw32) - racc (~> 1.4) - nokogiri (1.11.2-x86_64-linux) + mini_mime (1.1.2) + minitest (5.15.0) + nio4r (2.5.8) + nokogiri (1.13.3-x86_64-darwin) racc (~> 1.4) - parallel (1.20.1) - racc (1.5.2) + parallel (1.22.0) + racc (1.6.0) rack (2.2.3) rack-test (1.1.0) rack (>= 1.0, < 3) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.2) loofah (~> 2.3) railties (6.0.3) actionpack (= 6.0.3) @@ -81,28 +79,30 @@ GEM method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) - rake (13.0.3) - sprockets (4.0.2) + rake (13.0.6) + sprockets (4.0.3) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) sqlite3 (1.4.2) - thor (1.1.0) + thor (1.2.1) thread_safe (0.3.6) tzinfo (1.2.9) thread_safe (~> 0.1) - tzinfo-data (1.2021.1) + tzinfo-data (1.2022.1) tzinfo (>= 1.0.0) - websocket-driver (0.7.3) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.4.2) + zeitwerk (2.5.4) PLATFORMS x64-mingw32 + x86_64-darwin-20 + x86_64-darwin-21 x86_64-linux DEPENDENCIES @@ -121,4 +121,4 @@ DEPENDENCIES tzinfo-data BUNDLED WITH - 2.2.19 + 2.3.7 diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 53ae4530b..b5830be3c 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.7.0) + parallel_tests (3.7.3) parallel GEM @@ -47,35 +47,33 @@ GEM tzinfo (~> 2.0) zeitwerk (~> 2.3) builder (3.2.4) - concurrent-ruby (1.1.8) + concurrent-ruby (1.1.10) crass (1.0.6) erubi (1.10.0) - globalid (0.4.2) - activesupport (>= 4.2.0) - i18n (1.8.9) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.10.0) concurrent-ruby (~> 1.0) - loofah (2.9.0) + loofah (2.15.0) crass (~> 1.0.2) nokogiri (>= 1.5.9) mail (2.7.1) mini_mime (>= 0.1.1) method_source (1.0.0) - mini_mime (1.0.2) - minitest (5.14.4) - nio4r (2.5.7) - nokogiri (1.11.2-x64-mingw32) - racc (~> 1.4) - nokogiri (1.11.2-x86_64-linux) + mini_mime (1.1.2) + minitest (5.15.0) + nio4r (2.5.8) + nokogiri (1.13.3-x86_64-darwin) racc (~> 1.4) - parallel (1.20.1) - racc (1.5.2) + parallel (1.22.0) + racc (1.6.0) rack (2.2.3) rack-test (1.1.0) rack (>= 1.0, < 3) rails-dom-testing (2.0.3) activesupport (>= 4.2.0) nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) + rails-html-sanitizer (1.4.2) loofah (~> 2.3) railties (6.1.3) actionpack (= 6.1.3) @@ -83,27 +81,29 @@ GEM method_source rake (>= 0.8.7) thor (~> 1.0) - rake (13.0.3) - sprockets (4.0.2) + rake (13.0.6) + sprockets (4.0.3) concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) sqlite3 (1.4.2) - thor (1.1.0) + thor (1.2.1) tzinfo (2.0.4) concurrent-ruby (~> 1.0) - tzinfo-data (1.2021.1) + tzinfo-data (1.2022.1) tzinfo (>= 1.0.0) - websocket-driver (0.7.3) + websocket-driver (0.7.5) websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) - zeitwerk (2.4.2) + zeitwerk (2.5.4) PLATFORMS x64-mingw32 + x86_64-darwin-20 + x86_64-darwin-21 x86_64-linux DEPENDENCIES @@ -122,4 +122,4 @@ DEPENDENCIES tzinfo-data BUNDLED WITH - 2.2.19 + 2.3.7 diff --git a/spec/fixtures/rails70/.gitattributes b/spec/fixtures/rails70/.gitattributes new file mode 100644 index 000000000..31eeee0b6 --- /dev/null +++ b/spec/fixtures/rails70/.gitattributes @@ -0,0 +1,7 @@ +# See https://git-scm.com/docs/gitattributes for more about git attribute files. + +# Mark the database schema as having been generated. +db/schema.rb linguist-generated + +# Mark any vendored files as having been vendored. +vendor/* linguist-vendored diff --git a/spec/fixtures/rails70/.gitignore b/spec/fixtures/rails70/.gitignore new file mode 100644 index 000000000..886f714b4 --- /dev/null +++ b/spec/fixtures/rails70/.gitignore @@ -0,0 +1,35 @@ +# See https://help.github.com/articles/ignoring-files for more about ignoring files. +# +# If you find yourself ignoring temporary files generated by your text editor +# or operating system, you probably want to add a global ignore instead: +# git config --global core.excludesfile '~/.gitignore_global' + +# Ignore bundler config. +/.bundle + +# Ignore the default SQLite database. +/db/*.sqlite3 +/db/*.sqlite3-* + +# Ignore all logfiles and tempfiles. +/log/* +/tmp/* +!/log/.keep +!/tmp/.keep + +# Ignore pidfiles, but keep the directory. +/tmp/pids/* +!/tmp/pids/ +!/tmp/pids/.keep + +# Ignore uploaded files in development. +/storage/* +!/storage/.keep +/tmp/storage/* +!/tmp/storage/ +!/tmp/storage/.keep + +/public/assets + +# Ignore master key for decrypting credentials and more. +/config/master.key diff --git a/spec/fixtures/rails70/.ruby-version b/spec/fixtures/rails70/.ruby-version new file mode 100644 index 000000000..4a36342fc --- /dev/null +++ b/spec/fixtures/rails70/.ruby-version @@ -0,0 +1 @@ +3.0.0 diff --git a/spec/fixtures/rails70/Gemfile b/spec/fixtures/rails70/Gemfile new file mode 100644 index 000000000..11c1058d0 --- /dev/null +++ b/spec/fixtures/rails70/Gemfile @@ -0,0 +1,18 @@ +# frozen_string_literal: true +source "https://rubygems.org" + +rails_version = '7.0.2.3' + +gem 'actioncable', rails_version +gem 'actionmailer', rails_version +gem 'actionpack', rails_version +gem 'actionview', rails_version +gem 'activejob', rails_version +gem 'activemodel', rails_version +gem 'activerecord', rails_version +gem 'activesupport', rails_version +gem 'railties', rails_version + +gem 'sqlite3' +gem 'tzinfo-data' +gem 'parallel_tests', path: "../../../", group: :development diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock new file mode 100644 index 000000000..bfad14ecd --- /dev/null +++ b/spec/fixtures/rails70/Gemfile.lock @@ -0,0 +1,139 @@ +PATH + remote: ../../.. + specs: + parallel_tests (3.7.3) + parallel + +GEM + remote: https://rubygems.org/ + specs: + actioncable (7.0.2.3) + actionpack (= 7.0.2.3) + activesupport (= 7.0.2.3) + nio4r (~> 2.0) + websocket-driver (>= 0.6.1) + actionmailer (7.0.2.3) + actionpack (= 7.0.2.3) + actionview (= 7.0.2.3) + activejob (= 7.0.2.3) + activesupport (= 7.0.2.3) + mail (~> 2.5, >= 2.5.4) + net-imap + net-pop + net-smtp + rails-dom-testing (~> 2.0) + actionpack (7.0.2.3) + actionview (= 7.0.2.3) + activesupport (= 7.0.2.3) + rack (~> 2.0, >= 2.2.0) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.0, >= 1.2.0) + actionview (7.0.2.3) + activesupport (= 7.0.2.3) + builder (~> 3.1) + erubi (~> 1.4) + rails-dom-testing (~> 2.0) + rails-html-sanitizer (~> 1.1, >= 1.2.0) + activejob (7.0.2.3) + activesupport (= 7.0.2.3) + globalid (>= 0.3.6) + activemodel (7.0.2.3) + activesupport (= 7.0.2.3) + activerecord (7.0.2.3) + activemodel (= 7.0.2.3) + activesupport (= 7.0.2.3) + activesupport (7.0.2.3) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (>= 1.6, < 2) + minitest (>= 5.1) + tzinfo (~> 2.0) + builder (3.2.4) + concurrent-ruby (1.1.10) + crass (1.0.6) + digest (3.1.0) + erubi (1.10.0) + globalid (1.0.0) + activesupport (>= 5.0) + i18n (1.10.0) + concurrent-ruby (~> 1.0) + io-wait (0.2.1) + loofah (2.15.0) + crass (~> 1.0.2) + nokogiri (>= 1.5.9) + mail (2.7.1) + mini_mime (>= 0.1.1) + method_source (1.0.0) + mini_mime (1.1.2) + minitest (5.15.0) + net-imap (0.2.3) + digest + net-protocol + strscan + net-pop (0.1.1) + digest + net-protocol + timeout + net-protocol (0.1.2) + io-wait + timeout + net-smtp (0.3.1) + digest + net-protocol + timeout + nio4r (2.5.8) + nokogiri (1.13.3-x86_64-darwin) + racc (~> 1.4) + parallel (1.22.0) + racc (1.6.0) + rack (2.2.3) + rack-test (1.1.0) + rack (>= 1.0, < 3) + rails-dom-testing (2.0.3) + activesupport (>= 4.2.0) + nokogiri (>= 1.6) + rails-html-sanitizer (1.4.2) + loofah (~> 2.3) + railties (7.0.2.3) + actionpack (= 7.0.2.3) + activesupport (= 7.0.2.3) + method_source + rake (>= 12.2) + thor (~> 1.0) + zeitwerk (~> 2.5) + rake (13.0.6) + sqlite3 (1.4.2) + strscan (3.0.1) + thor (1.2.1) + timeout (0.2.0) + tzinfo (2.0.4) + concurrent-ruby (~> 1.0) + tzinfo-data (1.2022.1) + tzinfo (>= 1.0.0) + websocket-driver (0.7.5) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.5) + zeitwerk (2.5.4) + +PLATFORMS + x64-mingw32 + x86_64-darwin-20 + x86_64-darwin-21 + x86_64-linux + +DEPENDENCIES + actioncable (= 7.0.2.3) + actionmailer (= 7.0.2.3) + actionpack (= 7.0.2.3) + actionview (= 7.0.2.3) + activejob (= 7.0.2.3) + activemodel (= 7.0.2.3) + activerecord (= 7.0.2.3) + activesupport (= 7.0.2.3) + parallel_tests! + railties (= 7.0.2.3) + sqlite3 + tzinfo-data + +BUNDLED WITH + 2.3.7 diff --git a/spec/fixtures/rails70/README.md b/spec/fixtures/rails70/README.md new file mode 100644 index 000000000..7db80e4ca --- /dev/null +++ b/spec/fixtures/rails70/README.md @@ -0,0 +1,24 @@ +# README + +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... diff --git a/spec/fixtures/rails70/Rakefile b/spec/fixtures/rails70/Rakefile new file mode 100644 index 000000000..9a5ea7383 --- /dev/null +++ b/spec/fixtures/rails70/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative "config/application" + +Rails.application.load_tasks diff --git a/spec/fixtures/rails70/app/assets/config/manifest.js b/spec/fixtures/rails70/app/assets/config/manifest.js new file mode 100644 index 000000000..ddd546a0b --- /dev/null +++ b/spec/fixtures/rails70/app/assets/config/manifest.js @@ -0,0 +1,4 @@ +//= link_tree ../images +//= link_directory ../stylesheets .css +//= link_tree ../../javascript .js +//= link_tree ../../../vendor/javascript .js diff --git a/spec/fixtures/rails70/app/assets/images/.keep b/spec/fixtures/rails70/app/assets/images/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/app/assets/stylesheets/application.css b/spec/fixtures/rails70/app/assets/stylesheets/application.css new file mode 100644 index 000000000..288b9ab71 --- /dev/null +++ b/spec/fixtures/rails70/app/assets/stylesheets/application.css @@ -0,0 +1,15 @@ +/* + * This is a manifest file that'll be compiled into application.css, which will include all the files + * listed below. + * + * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's + * vendor/assets/stylesheets directory can be referenced here using a relative path. + * + * You're free to add application-wide styles to this file and they'll appear at the bottom of the + * compiled file so the styles you add here take precedence over styles defined in any other CSS + * files in this directory. Styles in this file should be added after the last require_* statement. + * It is generally better to create a new file per style scope. + * + *= require_tree . + *= require_self + */ diff --git a/spec/fixtures/rails70/app/channels/application_cable/channel.rb b/spec/fixtures/rails70/app/channels/application_cable/channel.rb new file mode 100644 index 000000000..d67269728 --- /dev/null +++ b/spec/fixtures/rails70/app/channels/application_cable/channel.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Channel < ActionCable::Channel::Base + end +end diff --git a/spec/fixtures/rails70/app/channels/application_cable/connection.rb b/spec/fixtures/rails70/app/channels/application_cable/connection.rb new file mode 100644 index 000000000..0ff5442f4 --- /dev/null +++ b/spec/fixtures/rails70/app/channels/application_cable/connection.rb @@ -0,0 +1,4 @@ +module ApplicationCable + class Connection < ActionCable::Connection::Base + end +end diff --git a/spec/fixtures/rails70/app/controllers/application_controller.rb b/spec/fixtures/rails70/app/controllers/application_controller.rb new file mode 100644 index 000000000..09705d12a --- /dev/null +++ b/spec/fixtures/rails70/app/controllers/application_controller.rb @@ -0,0 +1,2 @@ +class ApplicationController < ActionController::Base +end diff --git a/spec/fixtures/rails70/app/controllers/concerns/.keep b/spec/fixtures/rails70/app/controllers/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/app/helpers/application_helper.rb b/spec/fixtures/rails70/app/helpers/application_helper.rb new file mode 100644 index 000000000..de6be7945 --- /dev/null +++ b/spec/fixtures/rails70/app/helpers/application_helper.rb @@ -0,0 +1,2 @@ +module ApplicationHelper +end diff --git a/spec/fixtures/rails70/app/javascript/application.js b/spec/fixtures/rails70/app/javascript/application.js new file mode 100644 index 000000000..0d7b49404 --- /dev/null +++ b/spec/fixtures/rails70/app/javascript/application.js @@ -0,0 +1,3 @@ +// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails +import "@hotwired/turbo-rails" +import "controllers" diff --git a/spec/fixtures/rails70/app/javascript/controllers/application.js b/spec/fixtures/rails70/app/javascript/controllers/application.js new file mode 100644 index 000000000..1213e85c7 --- /dev/null +++ b/spec/fixtures/rails70/app/javascript/controllers/application.js @@ -0,0 +1,9 @@ +import { Application } from "@hotwired/stimulus" + +const application = Application.start() + +// Configure Stimulus development experience +application.debug = false +window.Stimulus = application + +export { application } diff --git a/spec/fixtures/rails70/app/javascript/controllers/hello_controller.js b/spec/fixtures/rails70/app/javascript/controllers/hello_controller.js new file mode 100644 index 000000000..5975c0789 --- /dev/null +++ b/spec/fixtures/rails70/app/javascript/controllers/hello_controller.js @@ -0,0 +1,7 @@ +import { Controller } from "@hotwired/stimulus" + +export default class extends Controller { + connect() { + this.element.textContent = "Hello World!" + } +} diff --git a/spec/fixtures/rails70/app/javascript/controllers/index.js b/spec/fixtures/rails70/app/javascript/controllers/index.js new file mode 100644 index 000000000..54ad4cad4 --- /dev/null +++ b/spec/fixtures/rails70/app/javascript/controllers/index.js @@ -0,0 +1,11 @@ +// Import and register all your controllers from the importmap under controllers/* + +import { application } from "controllers/application" + +// Eager load all controllers defined in the import map under controllers/**/*_controller +import { eagerLoadControllersFrom } from "@hotwired/stimulus-loading" +eagerLoadControllersFrom("controllers", application) + +// Lazy load controllers as they appear in the DOM (remember not to preload controllers in import map!) +// import { lazyLoadControllersFrom } from "@hotwired/stimulus-loading" +// lazyLoadControllersFrom("controllers", application) diff --git a/spec/fixtures/rails70/app/jobs/application_job.rb b/spec/fixtures/rails70/app/jobs/application_job.rb new file mode 100644 index 000000000..d394c3d10 --- /dev/null +++ b/spec/fixtures/rails70/app/jobs/application_job.rb @@ -0,0 +1,7 @@ +class ApplicationJob < ActiveJob::Base + # Automatically retry jobs that encountered a deadlock + # retry_on ActiveRecord::Deadlocked + + # Most jobs are safe to ignore if the underlying records are no longer available + # discard_on ActiveJob::DeserializationError +end diff --git a/spec/fixtures/rails70/app/mailers/application_mailer.rb b/spec/fixtures/rails70/app/mailers/application_mailer.rb new file mode 100644 index 000000000..3c34c8148 --- /dev/null +++ b/spec/fixtures/rails70/app/mailers/application_mailer.rb @@ -0,0 +1,4 @@ +class ApplicationMailer < ActionMailer::Base + default from: "from@example.com" + layout "mailer" +end diff --git a/spec/fixtures/rails70/app/models/application_record.rb b/spec/fixtures/rails70/app/models/application_record.rb new file mode 100644 index 000000000..b63caeb8a --- /dev/null +++ b/spec/fixtures/rails70/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + primary_abstract_class +end diff --git a/spec/fixtures/rails70/app/models/concerns/.keep b/spec/fixtures/rails70/app/models/concerns/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/app/models/user.rb b/spec/fixtures/rails70/app/models/user.rb new file mode 100644 index 000000000..379658a50 --- /dev/null +++ b/spec/fixtures/rails70/app/models/user.rb @@ -0,0 +1,2 @@ +class User < ApplicationRecord +end diff --git a/spec/fixtures/rails70/app/views/layouts/application.html.erb b/spec/fixtures/rails70/app/views/layouts/application.html.erb new file mode 100644 index 000000000..0d2f3c9bd --- /dev/null +++ b/spec/fixtures/rails70/app/views/layouts/application.html.erb @@ -0,0 +1,16 @@ + + + + Rails70 + + <%= csrf_meta_tags %> + <%= csp_meta_tag %> + + <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> + <%= javascript_importmap_tags %> + + + + <%= yield %> + + diff --git a/spec/fixtures/rails70/app/views/layouts/mailer.html.erb b/spec/fixtures/rails70/app/views/layouts/mailer.html.erb new file mode 100644 index 000000000..cbd34d2e9 --- /dev/null +++ b/spec/fixtures/rails70/app/views/layouts/mailer.html.erb @@ -0,0 +1,13 @@ + + + + + + + + + <%= yield %> + + diff --git a/spec/fixtures/rails70/app/views/layouts/mailer.text.erb b/spec/fixtures/rails70/app/views/layouts/mailer.text.erb new file mode 100644 index 000000000..37f0bddbd --- /dev/null +++ b/spec/fixtures/rails70/app/views/layouts/mailer.text.erb @@ -0,0 +1 @@ +<%= yield %> diff --git a/spec/fixtures/rails70/bin/bundle b/spec/fixtures/rails70/bin/bundle new file mode 100755 index 000000000..25dfd64d8 --- /dev/null +++ b/spec/fixtures/rails70/bin/bundle @@ -0,0 +1,114 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "rubygems" + +m = Module.new do + module_function + + def invoked_as_script? + File.expand_path($0) == File.expand_path(__FILE__) + end + + def env_var_version + ENV["BUNDLER_VERSION"] + end + + def cli_arg_version + return unless invoked_as_script? # don't want to hijack other binstubs + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil + update_index = nil + ARGV.each_with_index do |a, i| + if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN + bundler_version = a + end + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/ + bundler_version = Regexp.last_match(1) + update_index = i + end + bundler_version + end + + def gemfile + gemfile = ENV["BUNDLE_GEMFILE"] + return gemfile if gemfile && !gemfile.empty? + + File.expand_path('../Gemfile', __dir__) + end + + def lockfile + lockfile = + case File.basename(gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) + else "#{gemfile}.lock" + end + File.expand_path(lockfile) + end + + def lockfile_version + return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/ + Regexp.last_match(1) + end + + def bundler_version + @bundler_version ||= + env_var_version || cli_arg_version || + lockfile_version + end + + def bundler_requirement + return "#{Gem::Requirement.default}.a" unless bundler_version + + bundler_gem_version = Gem::Version.new(bundler_version) + + requirement = bundler_gem_version.approximate_recommendation + + return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") + + requirement += ".a" if bundler_gem_version.prerelease? + + requirement + end + + def load_bundler! + ENV["BUNDLE_GEMFILE"] ||= gemfile + + activate_bundler + end + + def activate_bundler + gem_error = activation_error_handling do + gem "bundler", bundler_requirement + end + return if gem_error.nil? + require_error = activation_error_handling do + require "bundler/version" + end + return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" + exit 42 + end + + def activation_error_handling + yield + nil + rescue StandardError, LoadError => e + e + end +end + +m.load_bundler! + +if m.invoked_as_script? + load Gem.bin_path("bundler", "bundle") +end diff --git a/spec/fixtures/rails70/bin/importmap b/spec/fixtures/rails70/bin/importmap new file mode 100755 index 000000000..36502ab16 --- /dev/null +++ b/spec/fixtures/rails70/bin/importmap @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby + +require_relative "../config/application" +require "importmap/commands" diff --git a/spec/fixtures/rails70/bin/rails b/spec/fixtures/rails70/bin/rails new file mode 100755 index 000000000..efc037749 --- /dev/null +++ b/spec/fixtures/rails70/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/spec/fixtures/rails70/bin/rake b/spec/fixtures/rails70/bin/rake new file mode 100755 index 000000000..4fbf10b96 --- /dev/null +++ b/spec/fixtures/rails70/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "rake" +Rake.application.run diff --git a/spec/fixtures/rails70/bin/setup b/spec/fixtures/rails70/bin/setup new file mode 100755 index 000000000..ec47b79b3 --- /dev/null +++ b/spec/fixtures/rails70/bin/setup @@ -0,0 +1,33 @@ +#!/usr/bin/env ruby +require "fileutils" + +# path to your application root. +APP_ROOT = File.expand_path("..", __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. + + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") + + # puts "\n== Copying sample files ==" + # unless File.exist?("config/database.yml") + # FileUtils.cp "config/database.yml.sample", "config/database.yml" + # end + + puts "\n== Preparing database ==" + system! "bin/rails db:prepare" + + puts "\n== Removing old logs and tempfiles ==" + system! "bin/rails log:clear tmp:clear" + + puts "\n== Restarting application server ==" + system! "bin/rails restart" +end diff --git a/spec/fixtures/rails70/config.ru b/spec/fixtures/rails70/config.ru new file mode 100644 index 000000000..4a3c09a68 --- /dev/null +++ b/spec/fixtures/rails70/config.ru @@ -0,0 +1,6 @@ +# This file is used by Rack-based servers to start the application. + +require_relative "config/environment" + +run Rails.application +Rails.application.load_server diff --git a/spec/fixtures/rails70/config/application.rb b/spec/fixtures/rails70/config/application.rb new file mode 100644 index 000000000..ac5c513b2 --- /dev/null +++ b/spec/fixtures/rails70/config/application.rb @@ -0,0 +1,35 @@ +require_relative "boot" + +require "rails" +# Pick the frameworks you want: +require "active_model/railtie" +require "active_job/railtie" +require "active_record/railtie" +# require "active_storage/engine" +require "action_controller/railtie" +require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" +require "action_view/railtie" +require "action_cable/engine" +# require "sprockets/railtie" +require "rails/test_unit/railtie" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module Rails70 + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 7.0 + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + end +end diff --git a/spec/fixtures/rails70/config/boot.rb b/spec/fixtures/rails70/config/boot.rb new file mode 100644 index 000000000..282011619 --- /dev/null +++ b/spec/fixtures/rails70/config/boot.rb @@ -0,0 +1,3 @@ +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. diff --git a/spec/fixtures/rails70/config/cable.yml b/spec/fixtures/rails70/config/cable.yml new file mode 100644 index 000000000..8ea8617f5 --- /dev/null +++ b/spec/fixtures/rails70/config/cable.yml @@ -0,0 +1,10 @@ +development: + adapter: async + +test: + adapter: test + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: rails70_production diff --git a/spec/fixtures/rails70/config/credentials.yml.enc b/spec/fixtures/rails70/config/credentials.yml.enc new file mode 100644 index 000000000..00455271a --- /dev/null +++ b/spec/fixtures/rails70/config/credentials.yml.enc @@ -0,0 +1 @@ +Hf5WtG5Ycg/SndPHUS0iSmW45dzUSvrchVGgjvSrvDCEcaa8D3tsTh/VFmTP8Gv75jVJplktDXAQxQC9D3BHrMAn8f0vjgG0iqpdnqWSmextXZPYePg6UGCfCWQ+VTFH/SY+epnO7Aa9VER0Ln5CVFRAURrxUNxqbXYIPQElgAdmGnI2LGJtoH/yyOq8cklCCt4bT5jzjiTMhEaA/o6kqLA2gN94oYoHGqsQZTYvo4Jv2S+gWiPOlbGEQbgOtEtnsy4akPpzjOxcGWGqP9cUDZtmO0fIxPI4OjXmlKmdzGa+UWvmWiku8hEu/rdhHU0kn8jqGh5Yoz7jgHY/XQyrRWSqNln+2rS3KwRcJ2dOgx8Nh7vV+zIgb0bQX0ZRGH5AdFdOoVdZaPFjSZIi0YWleXeuGvtfiTZuVpGc--EizbcaQddFxMXHC2--oZbQNGBHn4CVXLXLazOMdw== \ No newline at end of file diff --git a/spec/fixtures/rails70/config/database.yml b/spec/fixtures/rails70/config/database.yml new file mode 100644 index 000000000..ef6415822 --- /dev/null +++ b/spec/fixtures/rails70/config/database.yml @@ -0,0 +1,25 @@ +# SQLite. Versions 3.8.0 and up are supported. +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem "sqlite3" +# +default: &default + adapter: sqlite3 + pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test<%= ENV['TEST_ENV_NUMBER'] %>.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/spec/fixtures/rails70/config/environment.rb b/spec/fixtures/rails70/config/environment.rb new file mode 100644 index 000000000..cac531577 --- /dev/null +++ b/spec/fixtures/rails70/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative "application" + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/spec/fixtures/rails70/config/environments/development.rb b/spec/fixtures/rails70/config/environments/development.rb new file mode 100644 index 000000000..ff1a7b29b --- /dev/null +++ b/spec/fixtures/rails70/config/environments/development.rb @@ -0,0 +1,70 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable server timing + config.server_timing = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options). + # config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raise an error on page load if there are pending migrations. + config.active_record.migration_error = :page_load + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + # Suppress logger output for asset requests. + # config.assets.quiet = true + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true +end diff --git a/spec/fixtures/rails70/config/environments/production.rb b/spec/fixtures/rails70/config/environments/production.rb new file mode 100644 index 000000000..a2a2c660a --- /dev/null +++ b/spec/fixtures/rails70/config/environments/production.rb @@ -0,0 +1,93 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? + + # Compress CSS using a preprocessor. + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + # config.assets.compile = false + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = "http://assets.example.com" + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for Apache + # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options). + # config.active_storage.service = :local + + # Mount Action Cable outside main process or domain. + # config.action_cable.mount_path = nil + # config.action_cable.url = "wss://example.com/cable" + # config.action_cable.allowed_request_origins = [ "http://example.com", /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Include generic and useful information about system operation, but avoid logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). + config.log_level = :info + + # Prepend all log lines with the following tags. + config.log_tags = [:request_id] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "rails70_production" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Don't log any deprecations. + config.active_support.report_deprecations = false + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require "syslog/logger" + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new "app-name") + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/spec/fixtures/rails70/config/environments/test.rb b/spec/fixtures/rails70/config/environments/test.rb new file mode 100644 index 000000000..a792df787 --- /dev/null +++ b/spec/fixtures/rails70/config/environments/test.rb @@ -0,0 +1,60 @@ +require "active_support/core_ext/integer/time" + +# The test environment is used exclusively to run your application's +# test suite. You never need to work with it otherwise. Remember that +# your test database is "scratch space" for the test suite and is wiped +# and recreated between test runs. Don't rely on the data there! + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Turn false under Spring and add config.action_view.cache_template_loading = true. + config.cache_classes = true + + # Eager loading loads your whole application. When running a single test locally, + # this probably isn't necessary. It's a good idea to do in a continuous integration + # system, or in some way before deploying your code. + config.eager_load = ENV["CI"].present? + + # Configure public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{1.hour.to_i}" + } + + # Show full error reports and disable caching. + config.consider_all_requests_local = true + config.action_controller.perform_caching = false + config.cache_store = :null_store + + # Raise exceptions instead of rendering exception templates. + config.action_dispatch.show_exceptions = false + + # Disable request forgery protection in test environment. + config.action_controller.allow_forgery_protection = false + + # Store uploaded files on the local file system in a temporary directory. + # config.active_storage.service = :test + + config.action_mailer.perform_caching = false + + # Tell Action Mailer not to deliver emails to the real world. + # The :test delivery method accumulates sent emails in the + # ActionMailer::Base.deliveries array. + config.action_mailer.delivery_method = :test + + # Print deprecation notices to the stderr. + config.active_support.deprecation = :stderr + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true +end diff --git a/spec/fixtures/rails70/config/importmap.rb b/spec/fixtures/rails70/config/importmap.rb new file mode 100644 index 000000000..8dce42d40 --- /dev/null +++ b/spec/fixtures/rails70/config/importmap.rb @@ -0,0 +1,7 @@ +# Pin npm packages by running ./bin/importmap + +pin "application", preload: true +pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true +pin "@hotwired/stimulus", to: "stimulus.min.js", preload: true +pin "@hotwired/stimulus-loading", to: "stimulus-loading.js", preload: true +pin_all_from "app/javascript/controllers", under: "controllers" diff --git a/spec/fixtures/rails70/config/initializers/assets.rb b/spec/fixtures/rails70/config/initializers/assets.rb new file mode 100644 index 000000000..d6156df01 --- /dev/null +++ b/spec/fixtures/rails70/config/initializers/assets.rb @@ -0,0 +1,12 @@ +# Be sure to restart your server when you modify this file. + +# Version of your assets, change this if you want to expire all your assets. +# Rails.application.config.assets.version = "1.0" + +# Add additional assets to the asset load path. +# Rails.application.config.assets.paths << Emoji.images_path + +# Precompile additional assets. +# application.js, application.css, and all non-JS/CSS in the app/assets +# folder are already added. +# Rails.application.config.assets.precompile += %w( admin.js admin.css ) diff --git a/spec/fixtures/rails70/config/initializers/content_security_policy.rb b/spec/fixtures/rails70/config/initializers/content_security_policy.rb new file mode 100644 index 000000000..3621f97f8 --- /dev/null +++ b/spec/fixtures/rails70/config/initializers/content_security_policy.rb @@ -0,0 +1,26 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.configure do +# config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end +# +# # Generate session nonces for permitted importmap and inline scripts +# config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } +# config.content_security_policy_nonce_directives = %w(script-src) +# +# # Report CSP violations to a specified URI. See: +# # https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# # config.content_security_policy_report_only = true +# end diff --git a/spec/fixtures/rails70/config/initializers/filter_parameter_logging.rb b/spec/fixtures/rails70/config/initializers/filter_parameter_logging.rb new file mode 100644 index 000000000..adc6568ce --- /dev/null +++ b/spec/fixtures/rails70/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# Configure parameters to be filtered from the log file. Use this to limit dissemination of +# sensitive information. See the ActiveSupport::ParameterFilter documentation for supported +# notations and behaviors. +Rails.application.config.filter_parameters += [ + :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/spec/fixtures/rails70/config/initializers/inflections.rb b/spec/fixtures/rails70/config/initializers/inflections.rb new file mode 100644 index 000000000..3860f659e --- /dev/null +++ b/spec/fixtures/rails70/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/spec/fixtures/rails70/config/initializers/permissions_policy.rb b/spec/fixtures/rails70/config/initializers/permissions_policy.rb new file mode 100644 index 000000000..00f64d71b --- /dev/null +++ b/spec/fixtures/rails70/config/initializers/permissions_policy.rb @@ -0,0 +1,11 @@ +# Define an application-wide HTTP permissions policy. For further +# information see https://developers.google.com/web/updates/2018/06/feature-policy +# +# Rails.application.config.permissions_policy do |f| +# f.camera :none +# f.gyroscope :none +# f.microphone :none +# f.usb :none +# f.fullscreen :self +# f.payment :self, "https://secure.example.com" +# end diff --git a/spec/fixtures/rails70/config/locales/en.yml b/spec/fixtures/rails70/config/locales/en.yml new file mode 100644 index 000000000..8ca56fc74 --- /dev/null +++ b/spec/fixtures/rails70/config/locales/en.yml @@ -0,0 +1,33 @@ +# Files in the config/locales directory are used for internationalization +# and are automatically loaded by Rails. If you want to use locales other +# than English, add the necessary files in this directory. +# +# To use the locales, use `I18n.t`: +# +# I18n.t "hello" +# +# In views, this is aliased to just `t`: +# +# <%= t("hello") %> +# +# To use a different locale, set it with `I18n.locale`: +# +# I18n.locale = :es +# +# This would use the information in config/locales/es.yml. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# "true": "foo" +# +# To learn more, please read the Rails Internationalization guide +# available at https://guides.rubyonrails.org/i18n.html. + +en: + hello: "Hello world" diff --git a/spec/fixtures/rails70/config/puma.rb b/spec/fixtures/rails70/config/puma.rb new file mode 100644 index 000000000..ce4878f47 --- /dev/null +++ b/spec/fixtures/rails70/config/puma.rb @@ -0,0 +1,43 @@ +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +max_threads_count = ENV.fetch("RAILS_MAX_THREADS", 5) +min_threads_count = ENV.fetch("RAILS_MIN_THREADS") { max_threads_count } +threads min_threads_count, max_threads_count + +# Specifies the `worker_timeout` threshold that Puma will use to wait before +# terminating a worker in development environments. +# +worker_timeout 3600 if ENV.fetch("RAILS_ENV", "development") == "development" + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT", 3000) + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the `pidfile` that Puma will use. +pidfile ENV.fetch("PIDFILE") { "tmp/pids/server.pid" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked web server processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. +# +# preload_app! + +# Allow puma to be restarted by `bin/rails restart` command. +plugin :tmp_restart diff --git a/spec/fixtures/rails70/config/routes.rb b/spec/fixtures/rails70/config/routes.rb new file mode 100644 index 000000000..262ffd547 --- /dev/null +++ b/spec/fixtures/rails70/config/routes.rb @@ -0,0 +1,6 @@ +Rails.application.routes.draw do + # Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html + + # Defines the root path route ("/") + # root "articles#index" +end diff --git a/spec/fixtures/rails70/config/storage.yml b/spec/fixtures/rails70/config/storage.yml new file mode 100644 index 000000000..4942ab669 --- /dev/null +++ b/spec/fixtures/rails70/config/storage.yml @@ -0,0 +1,34 @@ +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use bin/rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket-<%= Rails.env %> + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket-<%= Rails.env %> + +# Use bin/rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name-<%= Rails.env %> + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/spec/fixtures/rails70/db/migrate/20220322153446_create_users.rb b/spec/fixtures/rails70/db/migrate/20220322153446_create_users.rb new file mode 100644 index 000000000..dd02b096c --- /dev/null +++ b/spec/fixtures/rails70/db/migrate/20220322153446_create_users.rb @@ -0,0 +1,9 @@ +class CreateUsers < ActiveRecord::Migration[7.0] + def change + create_table :users do |t| + t.string :name + + t.timestamps + end + end +end diff --git a/spec/fixtures/rails70/db/schema.rb b/spec/fixtures/rails70/db/schema.rb new file mode 100644 index 000000000..fa2607bf9 --- /dev/null +++ b/spec/fixtures/rails70/db/schema.rb @@ -0,0 +1,20 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Active Record to +# incrementally modify your database, and then regenerate this schema definition. +# +# This file is the source Rails uses to define your schema when running `bin/rails +# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to +# be faster and is potentially less error prone than running all of your +# migrations from scratch. Old migrations may fail to apply correctly if those +# migrations use external dependencies or application code. +# +# It's strongly recommended that you check this file into your version control system. + +ActiveRecord::Schema[7.0].define(version: 2022_03_22_153446) do + create_table "users", force: :cascade do |t| + t.string "name" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + +end diff --git a/spec/fixtures/rails70/db/seeds.rb b/spec/fixtures/rails70/db/seeds.rb new file mode 100644 index 000000000..bc25fce30 --- /dev/null +++ b/spec/fixtures/rails70/db/seeds.rb @@ -0,0 +1,7 @@ +# This file should contain all the record creation needed to seed the database with its default values. +# The data can then be loaded with the bin/rails db:seed command (or created alongside the database with db:setup). +# +# Examples: +# +# movies = Movie.create([{ name: "Star Wars" }, { name: "Lord of the Rings" }]) +# Character.create(name: "Luke", movie: movies.first) diff --git a/spec/fixtures/rails70/lib/assets/.keep b/spec/fixtures/rails70/lib/assets/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/lib/tasks/.keep b/spec/fixtures/rails70/lib/tasks/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/log/.keep b/spec/fixtures/rails70/log/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/public/404.html b/spec/fixtures/rails70/public/404.html new file mode 100644 index 000000000..2be3af26f --- /dev/null +++ b/spec/fixtures/rails70/public/404.html @@ -0,0 +1,67 @@ + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/fixtures/rails70/public/422.html b/spec/fixtures/rails70/public/422.html new file mode 100644 index 000000000..c08eac0d1 --- /dev/null +++ b/spec/fixtures/rails70/public/422.html @@ -0,0 +1,67 @@ + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/fixtures/rails70/public/500.html b/spec/fixtures/rails70/public/500.html new file mode 100644 index 000000000..78a030af2 --- /dev/null +++ b/spec/fixtures/rails70/public/500.html @@ -0,0 +1,66 @@ + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/spec/fixtures/rails70/public/apple-touch-icon-precomposed.png b/spec/fixtures/rails70/public/apple-touch-icon-precomposed.png new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/public/apple-touch-icon.png b/spec/fixtures/rails70/public/apple-touch-icon.png new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/public/favicon.ico b/spec/fixtures/rails70/public/favicon.ico new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/public/robots.txt b/spec/fixtures/rails70/public/robots.txt new file mode 100644 index 000000000..c19f78ab6 --- /dev/null +++ b/spec/fixtures/rails70/public/robots.txt @@ -0,0 +1 @@ +# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file diff --git a/spec/fixtures/rails70/storage/.keep b/spec/fixtures/rails70/storage/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/application_system_test_case.rb b/spec/fixtures/rails70/test/application_system_test_case.rb new file mode 100644 index 000000000..d19212abd --- /dev/null +++ b/spec/fixtures/rails70/test/application_system_test_case.rb @@ -0,0 +1,5 @@ +require "test_helper" + +class ApplicationSystemTestCase < ActionDispatch::SystemTestCase + driven_by :selenium, using: :chrome, screen_size: [1400, 1400] +end diff --git a/spec/fixtures/rails70/test/channels/application_cable/connection_test.rb b/spec/fixtures/rails70/test/channels/application_cable/connection_test.rb new file mode 100644 index 000000000..800405f15 --- /dev/null +++ b/spec/fixtures/rails70/test/channels/application_cable/connection_test.rb @@ -0,0 +1,11 @@ +require "test_helper" + +class ApplicationCable::ConnectionTest < ActionCable::Connection::TestCase + # test "connects with cookies" do + # cookies.signed[:user_id] = 42 + # + # connect + # + # assert_equal connection.user_id, "42" + # end +end diff --git a/spec/fixtures/rails70/test/controllers/.keep b/spec/fixtures/rails70/test/controllers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/fixtures/files/.keep b/spec/fixtures/rails70/test/fixtures/files/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/fixtures/users.yml b/spec/fixtures/rails70/test/fixtures/users.yml new file mode 100644 index 000000000..d7a332924 --- /dev/null +++ b/spec/fixtures/rails70/test/fixtures/users.yml @@ -0,0 +1,11 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/spec/fixtures/rails70/test/helpers/.keep b/spec/fixtures/rails70/test/helpers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/integration/.keep b/spec/fixtures/rails70/test/integration/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/mailers/.keep b/spec/fixtures/rails70/test/mailers/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/models/.keep b/spec/fixtures/rails70/test/models/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/models/user_test.rb b/spec/fixtures/rails70/test/models/user_test.rb new file mode 100644 index 000000000..5c07f4900 --- /dev/null +++ b/spec/fixtures/rails70/test/models/user_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/spec/fixtures/rails70/test/system/.keep b/spec/fixtures/rails70/test/system/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/test/test_helper.rb b/spec/fixtures/rails70/test/test_helper.rb new file mode 100644 index 000000000..d713e377c --- /dev/null +++ b/spec/fixtures/rails70/test/test_helper.rb @@ -0,0 +1,13 @@ +ENV["RAILS_ENV"] ||= "test" +require_relative "../config/environment" +require "rails/test_help" + +class ActiveSupport::TestCase + # Run tests in parallel with specified workers + parallelize(workers: :number_of_processors) + + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + + # Add more helper methods to be used by all tests here... +end diff --git a/spec/fixtures/rails70/vendor/.keep b/spec/fixtures/rails70/vendor/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/fixtures/rails70/vendor/javascript/.keep b/spec/fixtures/rails70/vendor/javascript/.keep new file mode 100644 index 000000000..e69de29bb diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index e73640520..7bc9196ad 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -13,7 +13,7 @@ def sh(command, options = {}) result end - ['rails60', 'rails61'].each do |rails| + ['rails60', 'rails61', 'rails70'].each do |rails| it "can create and run #{rails}" do skip 'rails fixtures are not set up for java' if RUBY_PLATFORM == "java" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index aeec78d56..dbd103382 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -81,7 +81,7 @@ def test_tests_in_groups(klass, suffix) def setup_runtime_log # rubocop:disable Lint/NestedMethodDefinition File.open(log, 'w') do |f| - @files[1..-1].each { |file| f.puts "#{file}:#{@files.index(file)}" } + @files[1..].each { |file| f.puts "#{file}:#{@files.index(file)}" } f.puts "#{@files[0]}:10" end end From 8fa1c99f972441af8cd3a48383ea6ca88ca467df Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 26 Mar 2022 10:09:57 -0700 Subject: [PATCH 100/177] update gems (#845) * update gems * rubocop --- Gemfile.lock | 72 +++++++++---------- lib/parallel_tests/pids.rb | 4 +- lib/parallel_tests/tasks.rb | 6 +- spec/fixtures/rails60/Gemfile.lock | 9 +++ spec/fixtures/rails61/Gemfile.lock | 9 +++ spec/fixtures/rails70/Gemfile.lock | 9 +++ spec/integration_spec.rb | 6 +- spec/parallel_tests/grouper_spec.rb | 2 +- .../rspec/runtime_logger_spec.rb | 2 +- 9 files changed, 73 insertions(+), 46 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index bfcb090f8..73bebbd0e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -7,17 +7,16 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (6.1.3) + activesupport (7.0.2.3) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - zeitwerk (~> 2.3) - ast (2.4.1) + ast (2.4.2) builder (3.2.4) - bump (0.9.0) + bump (0.10.0) colorize (0.8.1) - concurrent-ruby (1.1.8) + concurrent-ruby (1.1.10) cucumber (4.1.0) builder (~> 3.2, >= 3.2.3) cucumber-core (~> 7.1, >= 7.1.0) @@ -49,54 +48,54 @@ GEM cucumber-core (~> 7.1, >= 7.1.0) cucumber-cucumber-expressions (~> 10.1, >= 10.1.0) cucumber-messages (~> 12.2, >= 12.2.0) - cuke_modeler (3.7.0) - cucumber-gherkin (< 18.0) + cuke_modeler (3.15.0) + cucumber-gherkin (< 23.0) diff-lcs (1.3) - ffi (1.15.0) + ffi (1.15.5) gherkin-ruby (0.3.2) - i18n (1.8.9) + i18n (1.10.0) concurrent-ruby (~> 1.0) - json (2.3.0) + json (2.6.1) middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) - parallel (1.20.1) - parser (3.0.0.0) + parallel (1.22.1) + parser (3.1.1.0) ast (~> 2.4.1) - power_assert (1.2.0) + power_assert (2.0.1) protobuf-cucumber (3.10.8) activesupport (>= 3.2) middleware thor thread_safe - rainbow (3.0.0) - rake (13.0.1) - regexp_parser (2.0.3) - rexml (3.2.4) - rspec (3.9.0) - rspec-core (~> 3.9.0) - rspec-expectations (~> 3.9.0) - rspec-mocks (~> 3.9.0) - rspec-core (3.9.2) - rspec-support (~> 3.9.3) - rspec-expectations (3.9.2) + rainbow (3.1.1) + rake (13.0.6) + regexp_parser (2.2.1) + rexml (3.2.5) + rspec (3.11.0) + rspec-core (~> 3.11.0) + rspec-expectations (~> 3.11.0) + rspec-mocks (~> 3.11.0) + rspec-core (3.11.0) + rspec-support (~> 3.11.0) + rspec-expectations (3.11.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-mocks (3.9.1) + rspec-support (~> 3.11.0) + rspec-mocks (3.11.0) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.9.0) - rspec-support (3.9.3) - rubocop (1.8.1) + rspec-support (~> 3.11.0) + rspec-support (3.11.0) + rubocop (1.26.1) parallel (~> 1.10) - parser (>= 3.0.0.0) + parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) rexml - rubocop-ast (>= 1.2.0, < 2.0) + rubocop-ast (>= 1.16.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.4.0) - parser (>= 2.7.1.5) + rubocop-ast (1.16.0) + parser (>= 3.1.1.0) ruby-progressbar (1.11.0) spinach (0.11.0) colorize @@ -104,14 +103,13 @@ GEM json sys-uname (1.2.2) ffi (~> 1.1) - test-unit (3.3.6) + test-unit (3.5.3) power_assert - thor (1.1.0) + thor (1.2.1) thread_safe (0.3.6) tzinfo (2.0.4) concurrent-ruby (~> 1.0) - unicode-display_width (2.0.0) - zeitwerk (2.4.2) + unicode-display_width (2.1.0) PLATFORMS ruby diff --git a/lib/parallel_tests/pids.rb b/lib/parallel_tests/pids.rb index 45834cbc1..46153ce2d 100644 --- a/lib/parallel_tests/pids.rb +++ b/lib/parallel_tests/pids.rb @@ -43,14 +43,14 @@ def clear def read sync do - contents = IO.read(file_path) + contents = File.read(file_path) return if contents.empty? @pids = JSON.parse(contents) end end def save - sync { IO.write(file_path, pids.to_json) } + sync { File.write(file_path, pids.to_json) } end def sync(&block) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 57cc4f99d..93dc77379 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -185,7 +185,8 @@ def rails_61_or_greater? # just load the schema (good for integration server <-> no development db) desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" task :load_schema, :count do |_, args| - command = "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ + command = + "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ "db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1" ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end @@ -233,7 +234,8 @@ def rails_61_or_greater? # Using the relative path to find the binary allow to run a specific version of it executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') - command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} " \ + command = + "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} " \ "--type #{test_framework} " \ "-n #{count} " \ "--pattern '#{pattern}' " \ diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 73bba341c..13914fcc9 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -59,10 +59,18 @@ GEM mini_mime (>= 0.1.1) method_source (1.0.0) mini_mime (1.1.2) + mini_portile2 (2.8.0) minitest (5.15.0) nio4r (2.5.8) + nokogiri (1.13.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + nokogiri (1.13.3-x64-mingw32) + racc (~> 1.4) nokogiri (1.13.3-x86_64-darwin) racc (~> 1.4) + nokogiri (1.13.3-x86_64-linux) + racc (~> 1.4) parallel (1.22.0) racc (1.6.0) rack (2.2.3) @@ -100,6 +108,7 @@ GEM zeitwerk (2.5.4) PLATFORMS + ruby x64-mingw32 x86_64-darwin-20 x86_64-darwin-21 diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index b5830be3c..e922feefa 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -61,10 +61,18 @@ GEM mini_mime (>= 0.1.1) method_source (1.0.0) mini_mime (1.1.2) + mini_portile2 (2.8.0) minitest (5.15.0) nio4r (2.5.8) + nokogiri (1.13.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + nokogiri (1.13.3-x64-mingw32) + racc (~> 1.4) nokogiri (1.13.3-x86_64-darwin) racc (~> 1.4) + nokogiri (1.13.3-x86_64-linux) + racc (~> 1.4) parallel (1.22.0) racc (1.6.0) rack (2.2.3) @@ -101,6 +109,7 @@ GEM zeitwerk (2.5.4) PLATFORMS + ruby x64-mingw32 x86_64-darwin-20 x86_64-darwin-21 diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index bfad14ecd..3bd924a16 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -65,6 +65,7 @@ GEM mini_mime (>= 0.1.1) method_source (1.0.0) mini_mime (1.1.2) + mini_portile2 (2.8.0) minitest (5.15.0) net-imap (0.2.3) digest @@ -82,8 +83,15 @@ GEM net-protocol timeout nio4r (2.5.8) + nokogiri (1.13.3) + mini_portile2 (~> 2.8.0) + racc (~> 1.4) + nokogiri (1.13.3-x64-mingw32) + racc (~> 1.4) nokogiri (1.13.3-x86_64-darwin) racc (~> 1.4) + nokogiri (1.13.3-x86_64-linux) + racc (~> 1.4) parallel (1.22.0) racc (1.6.0) rack (2.2.3) @@ -116,6 +124,7 @@ GEM zeitwerk (2.5.4) PLATFORMS + ruby x64-mingw32 x86_64-darwin-20 x86_64-darwin-21 diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index b5c136080..5d48e6902 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -17,7 +17,7 @@ def folder def write(file, content) path = "#{folder}/#{file}" ensure_folder File.dirname(path) - File.open(path, 'w') { |f| f.write content } + File.write(path, content) path end @@ -298,7 +298,7 @@ def test_unicode context "with given commands" do it "can exec given commands with ENV['TEST_ENV_NUMBER']" do result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4` - expect(result.gsub('"', '').split('').sort).to eq(['0', '2', '3', '4']) + expect(result.gsub('"', '').chars.sort).to eq(['0', '2', '3', '4']) end it "can exec given command non-parallel" do @@ -308,7 +308,7 @@ def test_unicode it "can exec given command with a restricted set of groups" do result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4 --only-group 1,3` - expect(result.gsub('"', '').split('').sort).to eq(['0', '3']) + expect(result.gsub('"', '').chars.sort).to eq(['0', '3']) end it "can serialize stdout" do diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index ee8ed583f..e6982e64c 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -7,7 +7,7 @@ describe ParallelTests::Grouper do describe '.by_steps' do def write(file, content) - File.open(file, 'w') { |f| f.write content } + File.write(file, content) end it "sorts features by steps" do diff --git a/spec/parallel_tests/rspec/runtime_logger_spec.rb b/spec/parallel_tests/rspec/runtime_logger_spec.rb index 2332d40b1..992177392 100644 --- a/spec/parallel_tests/rspec/runtime_logger_spec.rb +++ b/spec/parallel_tests/rspec/runtime_logger_spec.rb @@ -67,7 +67,7 @@ def log_for_a_file(_options = {}) def write(file, content) FileUtils.mkdir_p(File.dirname(file)) - File.open(file, 'w') { |f| f.write content } + File.write(file, content) end it "logs shared examples into the running files" do From 7c575c3fab5e0a8b57b3d5b748af5f1d30a2885a Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 26 Mar 2022 11:28:03 -0700 Subject: [PATCH 101/177] simplify ci (#844) * simplify ci * use spinach without json --- .github/workflows/test.yml | 19 +++++-------------- Gemfile | 2 +- Gemfile.lock | 16 ++++++++++------ 3 files changed, 16 insertions(+), 21 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d6cbf2b00..3ce444913 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,16 +2,14 @@ name: test on: push: - branches: - - master - + branches: [master] pull_request: jobs: build: runs-on: ${{ matrix.os }} strategy: - fail-fast: false + fail-fast: false # run all tests so we see which gem/ruby combinations break matrix: ruby: ['3.0', '2.7', head, jruby-head] os: [ubuntu-latest, windows-latest] @@ -20,21 +18,14 @@ jobs: - ruby: '2.7' # lowest supported version os: ubuntu-latest task: rubocop - env: - RUBYOPT: -W0 - # avoid warnings from https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/ - ACTIONS_ALLOW_UNSECURE_COMMANDS: true steps: - uses: actions/checkout@master - - name: Setup OS dependencies - uses: MSP-Greg/setup-ruby-pkgs@v1 + - uses: ruby/setup-ruby@v1 with: ruby-version: ${{ matrix.ruby }} - apt-get: libsqlite3-dev - - name: Install dependencies - run: bundle install --jobs 4 + bundler-cache: true # runs 'bundle install' and caches installed gems automatically - name: rake ${{ matrix.task }} - run: bundle exec rake ${{ matrix.task }} # allow ruby/jruby-head to fail since they are moving targets # TODO: this will always show green, fix once https://github.com/actions/toolkit/issues/399 is resolved continue-on-error: ${{ endsWith(matrix.ruby, 'head') }} + run: bundle exec rake ${{ matrix.task }} diff --git a/Gemfile b/Gemfile index 846a67753..9f3d04f44 100644 --- a/Gemfile +++ b/Gemfile @@ -8,6 +8,6 @@ gem 'minitest', '~> 5.5.0' gem 'rspec', '~> 3.3' gem 'cucumber', "~> 4.0" gem 'cuke_modeler', '~> 3.0' -gem 'spinach' +gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 gem 'rake' gem 'rubocop' diff --git a/Gemfile.lock b/Gemfile.lock index 73bebbd0e..2afe62992 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,3 +1,12 @@ +GIT + remote: https://github.com/grosser/spinach.git + revision: e4e08ffd6d0877d139d602f3f5ccba3c97d69a36 + branch: grosser/json + specs: + spinach (0.11.0) + colorize + gherkin-ruby (>= 0.3.2) + PATH remote: . specs: @@ -55,7 +64,6 @@ GEM gherkin-ruby (0.3.2) i18n (1.10.0) concurrent-ruby (~> 1.0) - json (2.6.1) middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) @@ -97,10 +105,6 @@ GEM rubocop-ast (1.16.0) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) - spinach (0.11.0) - colorize - gherkin-ruby (>= 0.3.2) - json sys-uname (1.2.2) ffi (~> 1.1) test-unit (3.5.3) @@ -123,7 +127,7 @@ DEPENDENCIES rake rspec (~> 3.3) rubocop - spinach + spinach! test-unit BUNDLED WITH From f23dec95695bd908c2564521de59f3e415d265c2 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 26 Mar 2022 12:54:20 -0700 Subject: [PATCH 102/177] test on 3.1 (#843) * test on 3.1 * run all rails folders we have * bundle update helper * rails 6 and ruby 3.1 do not mix --- .github/workflows/test.yml | 2 +- Rakefile | 14 ++++++++++++++ spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- spec/rails_spec.rb | 5 ++++- 6 files changed, 22 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3ce444913..354e4c73f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: strategy: fail-fast: false # run all tests so we see which gem/ruby combinations break matrix: - ruby: ['3.0', '2.7', head, jruby-head] + ruby: ['3.1', '3.0', '2.7', head, jruby-head] os: [ubuntu-latest, windows-latest] task: [spec] include: diff --git a/Rakefile b/Rakefile index 8d6df7471..bd38572a8 100644 --- a/Rakefile +++ b/Rakefile @@ -13,3 +13,17 @@ desc "Run rubocop" task :rubocop do sh "rubocop --parallel" end + +desc "bundle all gemfiles [EXTRA=]" +task :bundle_all do + extra = ENV["EXTRA"] || "install" + + gemfiles = (["Gemfile"] + Dir["spec/fixtures/rails*/Gemfile"]) + raise if gemfiles.size < 3 + + gemfiles.each do |gemfile| + Bundler.with_unbundled_env do + sh "GEMFILE=#{gemfile} bundle #{extra}" + end + end +end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 13914fcc9..ac861e919 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -71,7 +71,7 @@ GEM racc (~> 1.4) nokogiri (1.13.3-x86_64-linux) racc (~> 1.4) - parallel (1.22.0) + parallel (1.22.1) racc (1.6.0) rack (2.2.3) rack-test (1.1.0) diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index e922feefa..ed151470a 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -73,7 +73,7 @@ GEM racc (~> 1.4) nokogiri (1.13.3-x86_64-linux) racc (~> 1.4) - parallel (1.22.0) + parallel (1.22.1) racc (1.6.0) rack (2.2.3) rack-test (1.1.0) diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 3bd924a16..2a8e4697f 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -92,7 +92,7 @@ GEM racc (~> 1.4) nokogiri (1.13.3-x86_64-linux) racc (~> 1.4) - parallel (1.22.0) + parallel (1.22.1) racc (1.6.0) rack (2.2.3) rack-test (1.1.0) diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 7bc9196ad..b7a110d54 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -13,7 +13,10 @@ def sh(command, options = {}) result end - ['rails60', 'rails61', 'rails70'].each do |rails| + Dir["spec/fixtures/rails*"].each do |folder| + rails = File.basename(folder) + next if RUBY_VERSION >= "3.1.0" && rails < "rails70" # https://github.com/rails/rails/issues/43998 + it "can create and run #{rails}" do skip 'rails fixtures are not set up for java' if RUBY_PLATFORM == "java" From fa5e9c86960a0e17b6d4338ea03741ae14404733 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 26 Mar 2022 12:54:48 -0700 Subject: [PATCH 103/177] v3.8.0 --- CHANGELOG.md | 12 ++++++++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 726883cd7..a45fe46a9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,18 @@ ### Fixed +## 3.8.0 - 2022-03-26 + +### Breaking Changes + +- Drop support for ruby 2.5 / 2.6 + +### Added + +- Tesed on ruby 3.0 and 3.1 + +### Fixed + - Added Rails 7.0 to fixtures - Fixes deprecation warning around the usage of `ActiveRecord::Base.schema_format` and deprecation in Rails 7.1 diff --git a/Gemfile.lock b/Gemfile.lock index 2afe62992..33946c646 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.7.3) + parallel_tests (3.8.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index ea84bda6f..476f63c0f 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.7.3' + VERSION = '3.8.0' end From 43fb0476de40b66798beac4a580331124117201f Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 28 Mar 2022 09:19:25 -0700 Subject: [PATCH 104/177] support old rubies because dependency management sucks (#847) --- .github/workflows/test.yml | 4 ++-- .rubocop.yml | 2 +- CHANGELOG.md | 2 +- Gemfile.lock | 4 +++- lib/parallel_tests/cli.rb | 4 ++-- .../cucumber/scenario_line_logger.rb | 2 +- lib/parallel_tests/gherkin/runner.rb | 2 +- lib/parallel_tests/grouper.rb | 2 +- parallel_tests.gemspec | 2 +- spec/fixtures/rails60/Gemfile.lock | 14 +++++++------- spec/fixtures/rails61/Gemfile.lock | 14 +++++++------- spec/rails_spec.rb | 1 + spec/spec_helper.rb | 2 +- 13 files changed, 29 insertions(+), 26 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 354e4c73f..06e7bfdd5 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,11 +11,11 @@ jobs: strategy: fail-fast: false # run all tests so we see which gem/ruby combinations break matrix: - ruby: ['3.1', '3.0', '2.7', head, jruby-head] + ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', head, jruby-head] os: [ubuntu-latest, windows-latest] task: [spec] include: - - ruby: '2.7' # lowest supported version + - ruby: '2.5' # lowest supported version os: ubuntu-latest task: rubocop steps: diff --git a/.rubocop.yml b/.rubocop.yml index 7c4a4f965..67bb29d84 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,6 @@ AllCops: NewCops: enable - TargetRubyVersion: 2.7 + TargetRubyVersion: 2.5 SuggestExtensions: false Exclude: - '**/vendor/bundle/**/*' diff --git a/CHANGELOG.md b/CHANGELOG.md index a45fe46a9..28bd5ad9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ ### Added -- None +- Support Ruby 2.5 / 2.6 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index 33946c646..d40b4af6a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -16,11 +16,12 @@ PATH GEM remote: https://rubygems.org/ specs: - activesupport (7.0.2.3) + activesupport (6.1.5) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) + zeitwerk (~> 2.3) ast (2.4.2) builder (3.2.4) bump (0.10.0) @@ -114,6 +115,7 @@ GEM tzinfo (2.0.4) concurrent-ruby (~> 1.0) unicode-display_width (2.1.0) + zeitwerk (2.5.4) PLATFORMS ruby diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index ce31e979a..860f8ff29 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -322,12 +322,12 @@ def parse_options!(argv) def extract_file_paths(argv) dash_index = argv.rindex("--") file_args_at = (dash_index || -1) + 1 - [argv[file_args_at..], argv[0...(dash_index || 0)]] + [argv[file_args_at..-1], argv[0...(dash_index || 0)]] end def extract_test_options(argv) dash_index = argv.index("--") || -1 - argv[dash_index + 1..] + argv[dash_index + 1..-1] end def append_test_options(options, argv) diff --git a/lib/parallel_tests/cucumber/scenario_line_logger.rb b/lib/parallel_tests/cucumber/scenario_line_logger.rb index bd47b7ada..74a99b52a 100644 --- a/lib/parallel_tests/cucumber/scenario_line_logger.rb +++ b/lib/parallel_tests/cucumber/scenario_line_logger.rb @@ -27,7 +27,7 @@ def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) example_tags = example.tags.map(&:name) example_tags = scenario_tags + example_tags next unless matches_tags?(example_tags) - example.rows[1..].each do |row| + example.rows[1..-1].each do |row| test_line = row.source_line next if line_numbers.any? && !line_numbers.include?(test_line) diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index 7718b5197..5e2b7bb0d 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -62,7 +62,7 @@ def summarize_results(results) plural = "s" if (word == group) && (number != 1) "#{number} #{word}#{plural}" end - "#{sums[0]} (#{sums[1..].join(", ")})" + "#{sums[0]} (#{sums[1..-1].join(", ")})" end.compact.join("\n") end diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index fd2229d97..959339f16 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -38,7 +38,7 @@ def in_even_groups_by_size(items, num_groups, options = {}) # add all files that should run in a multiple isolated processes to their own groups group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)]) # group the non-isolated by size - group_features_by_size(items_to_group(items), groups[isolate_count..]) + group_features_by_size(items_to_group(items), groups[isolate_count..-1]) else # add all files that should run in a single non-isolated process to first group single_items.each { |item, size| add_to_group(groups.first, item, size) } diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 3eb00e26c..b6d5f3f9d 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,5 +17,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.7.0' + s.required_ruby_version = '>= 2.5.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index ac861e919..f5169820e 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.7.3) + parallel_tests (3.8.0) parallel GEM @@ -59,17 +59,17 @@ GEM mini_mime (>= 0.1.1) method_source (1.0.0) mini_mime (1.1.2) - mini_portile2 (2.8.0) + mini_portile2 (2.6.1) minitest (5.15.0) nio4r (2.5.8) - nokogiri (1.13.3) - mini_portile2 (~> 2.8.0) + nokogiri (1.12.5) + mini_portile2 (~> 2.6.1) racc (~> 1.4) - nokogiri (1.13.3-x64-mingw32) + nokogiri (1.12.5-x64-mingw32) racc (~> 1.4) - nokogiri (1.13.3-x86_64-darwin) + nokogiri (1.12.5-x86_64-darwin) racc (~> 1.4) - nokogiri (1.13.3-x86_64-linux) + nokogiri (1.12.5-x86_64-linux) racc (~> 1.4) parallel (1.22.1) racc (1.6.0) diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index ed151470a..1307803a7 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.7.3) + parallel_tests (3.8.0) parallel GEM @@ -61,17 +61,17 @@ GEM mini_mime (>= 0.1.1) method_source (1.0.0) mini_mime (1.1.2) - mini_portile2 (2.8.0) + mini_portile2 (2.6.1) minitest (5.15.0) nio4r (2.5.8) - nokogiri (1.13.3) - mini_portile2 (~> 2.8.0) + nokogiri (1.12.5) + mini_portile2 (~> 2.6.1) racc (~> 1.4) - nokogiri (1.13.3-x64-mingw32) + nokogiri (1.12.5-x64-mingw32) racc (~> 1.4) - nokogiri (1.13.3-x86_64-darwin) + nokogiri (1.12.5-x86_64-darwin) racc (~> 1.4) - nokogiri (1.13.3-x86_64-linux) + nokogiri (1.12.5-x86_64-linux) racc (~> 1.4) parallel (1.22.1) racc (1.6.0) diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index b7a110d54..3aa9ec953 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -16,6 +16,7 @@ def sh(command, options = {}) Dir["spec/fixtures/rails*"].each do |folder| rails = File.basename(folder) next if RUBY_VERSION >= "3.1.0" && rails < "rails70" # https://github.com/rails/rails/issues/43998 + next if RUBY_VERSION < "2.7.0" && rails >= "rails70" it "can create and run #{rails}" do skip 'rails fixtures are not set up for java' if RUBY_PLATFORM == "java" diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index dbd103382..aeec78d56 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -81,7 +81,7 @@ def test_tests_in_groups(klass, suffix) def setup_runtime_log # rubocop:disable Lint/NestedMethodDefinition File.open(log, 'w') do |f| - @files[1..].each { |file| f.puts "#{file}:#{@files.index(file)}" } + @files[1..-1].each { |file| f.puts "#{file}:#{@files.index(file)}" } f.puts "#{@files[0]}:10" end end From b85a17ebd9cf920b2052623b28f0839bc35885de Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 28 Mar 2022 09:19:38 -0700 Subject: [PATCH 105/177] v3.8.1 --- CHANGELOG.md | 6 ++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28bd5ad9e..dcfe0b399 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,12 @@ ### Fixed +## 3.8.1 - 2022-03-28 + +### Added + +- Support Ruby 2.5 / 2.6 + ## 3.8.0 - 2022-03-26 ### Breaking Changes diff --git a/Gemfile.lock b/Gemfile.lock index d40b4af6a..abfe24233 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.8.0) + parallel_tests (3.8.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 476f63c0f..3f43f85f3 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.8.0' + VERSION = '3.8.1' end From 1a52e4343842cc717e0831cac48bd166a09250e4 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 14 May 2022 15:01:36 -0700 Subject: [PATCH 106/177] Require "set" module in spec/parallel_tests/test/runner_spec.rb (#848) Fixes the following failure when running the test in isolation: $ bundle exec rspec spec/parallel_tests/test/runner_spec.rb 1) ParallelTests::Test::Runner.test_in_groups when passed runtime groups by size and uses specified groups of specs in specific order in specific processes Failure/Error: actual = groups.map(&:to_set).to_set NoMethodError: undefined method `to_set' for ["ddd", "eee"]:Array actual = groups.map(&:to_set).to_set ^^^^ --- spec/parallel_tests/test/runner_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 1b40e79a2..2ad9e6a74 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +require "set" require "spec_helper" require "parallel_tests/test/runner" From bc7469cea07c6696996764ccf0205482076029d8 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 14 May 2022 15:56:31 -0700 Subject: [PATCH 107/177] Remove obsolete export statement filter in lib/parallel_tests/cli.rb (#850) Obsolete since e36fa9f8235844afabba624eb58549ad58ddc9ef. The subprocesses were switched to using IO.popen which passes environment variables. The subprocess command no longer includes export. --- lib/parallel_tests/cli.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 860f8ff29..cf05eaabe 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -140,7 +140,6 @@ def report_failure_rerun_commmand(test_results, options) puts "\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\n" failing_sets.each do |failing_set| command = failing_set[:command] - command = command.gsub(/;export [A-Z_]+;/, ' ') # remove ugly export statements command = @runner.command_with_seed(command, failing_set[:seed]) if failing_set[:seed] puts command end From 0b93e4d6cf8af2bc9d3a3d3bddd2f13df30cede0 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 14 May 2022 15:57:45 -0700 Subject: [PATCH 108/177] Remove redundant File.exists? checks in specs (#849) FileUtils.mkpath already checks if a directory exists before creating it, so there is no need to do so again. Avoid the extra system call when it is unnecessary. --- spec/integration_spec.rb | 10 +++------- spec/spec_helper.rb | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 5d48e6902..a22d1bf7e 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -16,7 +16,7 @@ def folder def write(file, content) path = "#{folder}/#{file}" - ensure_folder File.dirname(path) + FileUtils.mkpath File.dirname(path) File.write(path, content) path end @@ -33,12 +33,8 @@ def executable(options = {}) "ruby #{bin_folder}/parallel_#{options[:type] || 'test'}" end - def ensure_folder(folder) - FileUtils.mkpath(folder) unless File.exist?(folder) - end - def run_tests(test_folder, options = {}) - ensure_folder folder + FileUtils.mkpath folder processes = "-n #{options[:processes] || 2}" unless options[:processes] == false command = "#{executable(options)} #{test_folder} #{processes} #{options[:add]}" result = '' @@ -57,7 +53,7 @@ def run_tests(test_folder, options = {}) def self.it_runs_the_default_folder_if_it_exists(type, test_folder) it "runs the default folder if it exists" do full_path_to_test_folder = File.join(folder, test_folder) - ensure_folder full_path_to_test_folder + FileUtils.mkpath full_path_to_test_folder results = run_tests("", fail: false, type: type) expect(results).to_not include("Pass files or folders to run") diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index aeec78d56..d352d1de2 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -44,7 +44,7 @@ def with_files(files) Dir.mktmpdir do |root| files.each do |file| parent = "#{root}/#{File.dirname(file)}" - FileUtils.mkpath(parent) unless File.exist?(parent) + FileUtils.mkpath(parent) FileUtils.touch(File.join(root, file)) end yield root From 87a6630ccb01349724a488a8dc9ff32419504202 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 14 May 2022 20:54:02 -0700 Subject: [PATCH 109/177] Use FileUtils.rm_f to delete files in specs (#851) Avoid a subprocess and shell to the rm program. Slightly more effiencient to delete directly. --- spec/rails_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 3aa9ec953..1b88d8205 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +require 'fileutils' require 'spec_helper' describe 'rails' do @@ -29,7 +30,7 @@ def sh(command, options = {}) sh "bundle config --local path vendor/bundle" sh "bundle install" - sh "rm -rf db/*.sqlite3" + FileUtils.rm_f(Dir['db/*.sqlite3']) sh "bundle exec rake db:setup parallel:create --trace 2>&1" # Also test the case where the DBs need to be dropped sh "bundle exec rake parallel:drop parallel:create" From 5d91f2410f2558aaf6216689e66fc8a5cfa27898 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 14 May 2022 20:54:15 -0700 Subject: [PATCH 110/177] =?UTF-8?q?Fix=20typo:=20corectly=20=E2=86=92=20co?= =?UTF-8?q?rrectly=20(#852)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- spec/parallel_tests/cli_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 0e821336a..0a6cd1579 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -147,7 +147,7 @@ def call(*args) expect(call(['--', 'test', '--foo', 'test2'])).to eq(files: ['test', '--foo', 'test2']) end - it "corectly handles arguments with spaces" do + it "correctly handles arguments with spaces" do expect(call(['--', 'file name with space'])).to eq(files: ['file name with space']) end @@ -168,7 +168,7 @@ def call(*args) it "appends the new options" do expect(call(['-o', "'-f'", '--', '-r', 'foo.rb', '--', 'test'])).to eq(files: ['test'], test_options: "'-f' -r foo.rb") end - it "corectly handles argument values with spaces" do + it "correctly handles argument values with spaces" do argv = ["-o 'path with spaces1'", '--', '--out', 'path with spaces2', '--', 'foo'] expected_test_options = "'path with spaces1' --out path\\ with\\ spaces2" expect(call(argv)).to eq(files: ['foo'], test_options: expected_test_options) From e5af18d763b242e5b316eb84b4968c173c3df74e Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 15 May 2022 09:24:02 -0700 Subject: [PATCH 111/177] Run GitHub actions on all branches (#853) Make is simple for contributors to run the GitHub actions on their fork before opening a pull request. --- .github/workflows/test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 06e7bfdd5..37487669d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,7 +2,6 @@ name: test on: push: - branches: [master] pull_request: jobs: From e7e9ba39423876f9189bad12e5063f5bfc6d825f Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 15 May 2022 10:04:18 -0700 Subject: [PATCH 112/177] Avoid using a shell for subprocesses during tests (#854) Treat subprocesses commands as an array of strings. This avoid the need to include a shell in the subprocess. Instead, the commands execute directly. As well, there is no need to parse or format shell syntax (such as string quoting). --- lib/parallel_tests/tasks.rb | 5 +- spec/integration_spec.rb | 148 ++++++++++-------- .../rspec/runtime_logger_spec.rb | 4 +- spec/parallel_tests/tasks_spec.rb | 2 +- spec/parallel_tests/test/runner_spec.rb | 4 +- .../test/runtime_logger_spec.rb | 6 +- spec/rails_spec.rb | 21 ++- 7 files changed, 99 insertions(+), 91 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 93dc77379..76b13aed9 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -55,9 +55,8 @@ def suppress_output(command, ignore_regex) remove_ignored_lines = %{(grep -v "#{ignore_regex}" || test 1)} if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1") - # We need to shell escape single quotes (' becomes '"'"') because - # run_in_parallel wraps command in single quotes - %{/bin/bash -c '"'"'#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}'"'"'} + shell_command = "#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}" + %(/bin/bash -c #{Shellwords.escape(shell_command)}) else command end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index a22d1bf7e..29b0e6494 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -30,13 +30,16 @@ def bin_folder end def executable(options = {}) - "ruby #{bin_folder}/parallel_#{options[:type] || 'test'}" + ["ruby", "#{bin_folder}/parallel_#{options[:type] || 'test'}"] end def run_tests(test_folder, options = {}) FileUtils.mkpath folder - processes = "-n #{options[:processes] || 2}" unless options[:processes] == false - command = "#{executable(options)} #{test_folder} #{processes} #{options[:add]}" + + command = [*executable(options), *test_folder] + command += ["-n", (options[:processes] || 2).to_s] unless options[:processes] == false + command += options[:add] if options[:add] + result = '' Dir.chdir(folder) do env = options[:export] || {} @@ -54,11 +57,11 @@ def self.it_runs_the_default_folder_if_it_exists(type, test_folder) it "runs the default folder if it exists" do full_path_to_test_folder = File.join(folder, test_folder) FileUtils.mkpath full_path_to_test_folder - results = run_tests("", fail: false, type: type) + results = run_tests(nil, fail: false, type: type) expect(results).to_not include("Pass files or folders to run") FileUtils.remove_dir(full_path_to_test_folder, true) - results = run_tests("", fail: true, type: type) + results = run_tests(nil, fail: true, type: type) expect(results).to include("Pass files or folders to run") end end @@ -91,7 +94,7 @@ def self.it_runs_the_default_folder_if_it_exists(type, test_folder) describe("it"){it("should"){ expect(true).to be false }} SPEC - run_tests "spec", type: 'rspec', add: "--highest-exit-status", fail: 99 + run_tests "spec", type: 'rspec', add: ["--highest-exit-status"], fail: 99 end end @@ -140,20 +143,22 @@ def self.it_runs_the_default_folder_if_it_exists(type, test_folder) describe("it"){it("should"){ expect(true).to be false }} SPEC - run_tests "spec", type: 'rspec', processes: 4, add: "--highest-exit-status", fail: 99 + run_tests "spec", type: 'rspec', processes: 4, add: ["--highest-exit-status"], fail: 99 end end # Uses `Process.kill` under the hood, which on Windows doesn't work as expected. It kills all process group instead of just one process. describe "--fail-fast", unless: Gem.win_platform? do def run_tests(test_option: nil) + # group-by + order for stable execution ... doc and verbose to ease debugging + test_options = "--format doc --order defined" + test_options = "#{test_options} #{test_option}" if test_option super( "spec", fail: true, type: 'rspec', processes: 2, - # group-by + order for stable execution ... doc and verbose to ease debugging - add: "--group-by found --verbose --fail-fast --test-options '--format doc --order defined #{test_option}'" + add: ["--group-by", "found", "--verbose", "--fail-fast", "--test-options", test_options] ) end @@ -229,7 +234,7 @@ def test_unicode it "shows command and rerun with --verbose" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec --verbose", type: 'rspec', fail: true + result = run_tests ["spec", "--verbose"], type: 'rspec', fail: true expect(result).to match printed_commands expect(result).to include printed_rerun expect(result).to include "bundle exec rspec spec/xxx_spec.rb" @@ -238,14 +243,14 @@ def test_unicode it "shows only rerun with --verbose-rerun-command" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec --verbose-rerun-command", type: 'rspec', fail: true + result = run_tests ["spec", "--verbose-rerun-command"], type: 'rspec', fail: true expect(result).to include printed_rerun expect(result).to_not match printed_commands end it "shows only process with --verbose-process-command" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests "spec --verbose-process-command", type: 'rspec', fail: true + result = run_tests ["spec", "--verbose-process-command"], type: 'rspec', fail: true expect(result).to_not include printed_rerun expect(result).to match printed_commands end @@ -263,7 +268,7 @@ def test_unicode it "can serialize stdout" do write 'spec/xxx_spec.rb', '5.times{describe("it"){it("should"){sleep 0.01; puts "TEST1"}}}' write 'spec/xxx2_spec.rb', 'sleep 0.01; 5.times{describe("it"){it("should"){sleep 0.01; puts "TEST2"}}}' - result = run_tests "spec", type: 'rspec', add: "--serialize-stdout" + result = run_tests "spec", type: 'rspec', add: ["--serialize-stdout"] expect(result).not_to match(/TEST1.*TEST2.*TEST1/m) expect(result).not_to match(/TEST2.*TEST1.*TEST2/m) @@ -272,20 +277,20 @@ def test_unicode it "can show simulated output when serializing stdout" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 0.5; puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){sleep 1; puts "TEST2"}}' - result = run_tests "spec", type: 'rspec', add: "--serialize-stdout", export: { 'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01' } + result = run_tests "spec", type: 'rspec', add: ["--serialize-stdout"], export: { 'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.01' } expect(result).to match(/\.{4}.*TEST1.*\.{4}.*TEST2/m) end it "can show simulated output preceded by command when serializing stdout with verbose option" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){sleep 1.5; puts "TEST1"}}' - result = run_tests "spec --verbose", type: 'rspec', add: "--serialize-stdout", export: { 'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02' } + result = run_tests ["spec", "--verbose"], type: 'rspec', add: ["--serialize-stdout"], export: { 'PARALLEL_TEST_HEARTBEAT_INTERVAL' => '0.02' } expect(result).to match(/\.{5}.*\nbundle exec rspec spec\/xxx_spec\.rb\n.*^TEST1/m) end it "can serialize stdout and stderr" do write 'spec/xxx_spec.rb', '5.times{describe("it"){it("should"){sleep 0.01; $stderr.puts "errTEST1"; puts "TEST1"}}}' write 'spec/xxx2_spec.rb', 'sleep 0.01; 5.times{describe("it"){it("should"){sleep 0.01; $stderr.puts "errTEST2"; puts "TEST2"}}}' - result = run_tests "spec", type: 'rspec', add: "--serialize-stdout --combine-stderr" + result = run_tests ["spec"], type: 'rspec', add: ["--serialize-stdout", "--combine-stderr"] expect(result).not_to match(/TEST1.*TEST2.*TEST1/m) expect(result).not_to match(/TEST2.*TEST1.*TEST2/m) @@ -293,85 +298,92 @@ def test_unicode context "with given commands" do it "can exec given commands with ENV['TEST_ENV_NUMBER']" do - result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4` + result = run_tests ['-e', 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"'], processes: 4 expect(result.gsub('"', '').chars.sort).to eq(['0', '2', '3', '4']) end it "can exec given command non-parallel" do - result = `#{executable} -e 'ruby -e "sleep(rand(10)/100.0); puts ENV[:TEST_ENV_NUMBER.to_s].inspect"' -n 4 --non-parallel` + result = run_tests( + ['-e', 'ruby -e "sleep(rand(10)/100.0); puts ENV[:TEST_ENV_NUMBER.to_s].inspect"'], + processes: 4, + add: ['--non-parallel'] + ) expect(result.split(/\n+/)).to eq(['""', '"2"', '"3"', '"4"']) end it "can exec given command with a restricted set of groups" do - result = `#{executable} -e 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"' -n 4 --only-group 1,3` + result = run_tests( + ['-e', 'ruby -e "print ENV[:TEST_ENV_NUMBER.to_s].to_i"'], + process: 4, + add: ['--only-group', '1,3'] + ) expect(result.gsub('"', '').chars.sort).to eq(['0', '3']) end it "can serialize stdout" do - result = `#{executable} -e 'ruby -e "5.times{sleep 0.01;puts ENV[:TEST_ENV_NUMBER.to_s].to_i;STDOUT.flush}"' -n 2 --serialize-stdout` + result = run_tests( + ['-e', 'ruby -e "5.times{sleep 0.01;puts ENV[:TEST_ENV_NUMBER.to_s].to_i;STDOUT.flush}"'], + processes: 2, + add: ['--serialize-stdout'] + ) expect(result).not_to match(/0.*2.*0/m) expect(result).not_to match(/2.*0.*2/m) end it "exists with success if all sub-processes returned success" do - expect(system("#{executable} -e 'cat /dev/null' -n 4")).to eq(true) + expect(system(*executable, '-e', 'cat /dev/null', '-n', '4')).to eq(true) end it "exists with failure if any sub-processes returned failure" do - expect(system("#{executable} -e 'test -e xxxx' -n 4")).to eq(false) + expect(system(*executable, '-e', 'test -e xxxx', '-n', '4')).to eq(false) end end - it "runs through parallel_rspec" do - version = `#{executable} -v` - expect(`ruby #{bin_folder}/parallel_rspec -v`).to eq(version) - end - - it "runs through parallel_cucumber" do - version = `#{executable} -v` - expect(`ruby #{bin_folder}/parallel_cucumber -v`).to eq(version) - end - - it "runs through parallel_spinach" do - version = `#{executable} -v` - expect(`ruby #{bin_folder}/parallel_spinach -v`).to eq(version) + ['rspec', 'cucumber', 'spinach'].each do |type| + it "runs through parallel_#{type}" do + test_version = IO.popen([*executable, '-v'], &:read) + expect($?.success?).to be(true) + type_version = IO.popen(['ruby', "#{bin_folder}/parallel_#{type}", '-v'], &:read) + expect($?.success?).to be(true) + expect(type_version).to eq(test_version) + end end it "runs with --group-by found" do # it only tests that it does not blow up, as it did before fixing... write "spec/x1_spec.rb", "puts 'TEST111'" - run_tests "spec", type: 'rspec', add: '--group-by found' + run_tests ["spec"], type: 'rspec', add: ['--group-by', 'found'] end it "runs in parallel" do 2.times do |i| write "spec/xxx#{i}_spec.rb", 'STDOUT.sync = true; describe("it") { it("should"){ puts "START"; sleep 1; puts "END" } }' end - result = run_tests("spec", processes: 2, type: 'rspec') + result = run_tests(["spec"], processes: 2, type: 'rspec') expect(result.scan(/START|END/)).to eq(["START", "START", "END", "END"]) end it "disables spring so correct database is used" do write "spec/xxx_spec.rb", 'puts "SPRING: #{ENV["DISABLE_SPRING"]}"' - result = run_tests("spec", processes: 2, type: 'rspec') + result = run_tests(["spec"], processes: 2, type: 'rspec') expect(result).to include "SPRING: 1" end it "can enable spring" do write "spec/xxx_spec.rb", 'puts "SPRING: #{ENV["DISABLE_SPRING"]}"' - result = run_tests("spec", processes: 2, type: 'rspec', export: { "DISABLE_SPRING" => "0" }) + result = run_tests(["spec"], processes: 2, type: 'rspec', export: { "DISABLE_SPRING" => "0" }) expect(result).to include "SPRING: 0" end it "runs with files that have spaces" do write "test/xxx _test.rb", 'puts "TEST_SUCCESS"' - result = run_tests("test", processes: 2, type: 'test') + result = run_tests(["test"], processes: 2, type: 'test') expect(result).to include "TEST_SUCCESS" end it "uses relative paths for easy copying" do write "test/xxx_test.rb", 'puts "Test output: YES"' - result = run_tests("test", processes: 2, type: 'test', add: '--verbose') + result = run_tests(["test"], processes: 2, type: 'test', add: ['--verbose']) expect(result).to include "Test output: YES" expect(result).to include "[test/xxx_test.rb]" expect(result).not_to include Dir.pwd @@ -381,7 +393,7 @@ def test_unicode write "spec/x1_spec.rb", "puts 'TEST111'" write "spec/x2_spec.rb", "puts 'TEST222'" write "spec/x3_spec.rb", "puts 'TEST333'" - result = run_tests "spec/x1_spec.rb spec/x3_spec.rb", type: 'rspec' + result = run_tests ["spec/x1_spec.rb", "spec/x3_spec.rb"], type: 'rspec' expect(result).to include('TEST111') expect(result).to include('TEST333') expect(result).not_to include('TEST222') @@ -390,7 +402,7 @@ def test_unicode it "can run with test-options" do write "spec/x1_spec.rb", "111" write "spec/x2_spec.rb", "111" - result = run_tests "spec", add: "--test-options ' --version'", processes: 2, type: 'rspec' + result = run_tests ["spec"], add: ["--test-options", "--version"], processes: 2, type: 'rspec' expect(result).to match(/\d+\.\d+\.\d+.*\d+\.\d+\.\d+/m) # prints version twice end @@ -401,7 +413,7 @@ def test_unicode write "spec/x#{i}_spec.rb", "puts %{ENV-\#{ENV['TEST_ENV_NUMBER']}-}" end result = run_tests( - "spec", export: { "PARALLEL_TEST_PROCESSORS" => processes.to_s }, processes: processes, type: 'rspec' + ["spec"], export: { "PARALLEL_TEST_PROCESSORS" => processes.to_s }, processes: processes, type: 'rspec' ) expect(result.scan(/ENV-.?-/)).to match_array(["ENV--", "ENV-2-", "ENV-3-", "ENV-4-", "ENV-5-"]) end @@ -410,7 +422,7 @@ def test_unicode write "spec/x_spec.rb", "puts 'TESTXXX'" write "spec/y_spec.rb", "puts 'TESTYYY'" write "spec/z_spec.rb", "puts 'TESTZZZ'" - result = run_tests "spec", add: "-p '^spec/(x|z)'", type: "rspec" + result = run_tests ["spec"], add: ["-p", "^spec/(x|z)"], type: "rspec" expect(result).to include('TESTXXX') expect(result).not_to include('TESTYYY') expect(result).to include('TESTZZZ') @@ -420,7 +432,7 @@ def test_unicode write "spec/x_spec.rb", "puts 'TESTXXX'" write "spec/acceptance/y_spec.rb", "puts 'TESTYYY'" write "spec/integration/z_spec.rb", "puts 'TESTZZZ'" - result = run_tests "spec", add: "--exclude-pattern 'spec/(integration|acceptance)'", type: "rspec" + result = run_tests ["spec"], add: ["--exclude-pattern", "spec/(integration|acceptance)"], type: "rspec" expect(result).to include('TESTXXX') expect(result).not_to include('TESTYYY') expect(result).not_to include('TESTZZZ') @@ -432,7 +444,7 @@ def test_unicode write "test/b_test.rb", "sleep 1; puts 'OutputB'" write "test/c_test.rb", "sleep 1.5; puts 'OutputC'" write "test/d_test.rb", "sleep 2; puts 'OutputD'" - actual = run_tests("test", processes: 4).scan(/Output[ABCD]/) + actual = run_tests(["test"], processes: 4).scan(/Output[ABCD]/) actual_sorted = [*actual[0..2].sort, actual[3]] expect(actual_sorted).to match(["OutputB", "OutputC", "OutputD", "OutputA"]) end @@ -442,17 +454,17 @@ def test_unicode write "test/long_test.rb", "puts 'this is a long test'" write "test/short_test.rb", "puts 'short test'" - group_1_result = run_tests("test", processes: 2, add: '--only-group 1') + group_1_result = run_tests(["test"], processes: 2, add: ['--only-group', '1']) expect(group_1_result).to include("this is a long test") expect(group_1_result).not_to include("short test") - group_2_result = run_tests("test", processes: 2, add: '--only-group 2') + group_2_result = run_tests(["test"], processes: 2, add: ['--only-group', '2']) expect(group_2_result).not_to include("this is a long test") expect(group_2_result).to include("short test") end it "shows nice --help" do - result = run_tests "--help" + result = run_tests ["--help"] expect( result[/(.*)How many processes/, 1].size ).to( @@ -464,7 +476,7 @@ def test_unicode it "can run with uncommon file names" do skip if RUBY_PLATFORM == "java" # just too slow ... write "test/long ( stuff ) _test.rb", "puts 'hey'" - expect(run_tests("test", processes: 2)).to include("hey") + expect(run_tests(["test"], processes: 2)).to include("hey") end context "RSpec" do @@ -473,7 +485,7 @@ def test_unicode it "captures seed with random failures with --verbose" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){1.should == 2}}' - result = run_tests "spec --verbose", add: "--test-options '--seed 1234'", fail: true, type: 'rspec' + result = run_tests ["spec", "--verbose"], add: ["--test-options", "--seed 1234"], fail: true, type: 'rspec' expect(result).to include("Randomized with seed 1234") expect(result).to include("bundle exec rspec spec/xxx2_spec.rb --seed 1234") end @@ -482,13 +494,13 @@ def test_unicode context "Test::Unit" do it "runs" do write "test/x1_test.rb", "require 'test/unit'; class XTest < Test::Unit::TestCase; def test_xxx; end; end" - result = run_tests("test") + result = run_tests ["test"] expect(result).to include('1 test') end it "passes test options" do write "test/x1_test.rb", "require 'test/unit'; class XTest < Test::Unit::TestCase; def test_xxx; end; end" - result = run_tests("test", add: '--test-options "-v"') + result = run_tests(["test"], add: ['--test-options', '-v']) expect(result).to include('test_xxx') # verbose output of every test end @@ -508,7 +520,7 @@ def test_unicode it "runs tests which outputs accented characters" do write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I print accented characters" write "features/steps/a.rb", "#encoding: utf-8\nGiven('I print accented characters'){ puts \"I tu też\" }" - result = run_tests "features", type: "cucumber", add: '--pattern good' + result = run_tests ["features"], type: "cucumber", add: ['--pattern', 'good'] expect(result).to include('I tu też') end @@ -518,7 +530,7 @@ def test_unicode write "features/b.feature", "Feature: xxx\n Scenario: xxx\n Given I FAIL" write "features/steps/a.rb", "Given('I print TEST_ENV_NUMBER'){ puts \"YOUR TEST ENV IS \#{ENV['TEST_ENV_NUMBER']}!\" }" - result = run_tests "features", type: "cucumber", add: '--pattern good' + result = run_tests ["features"], type: "cucumber", add: ['--pattern', 'good'] expect(result).to include('YOUR TEST ENV IS 2!') expect(result).to include('YOUR TEST ENV IS !') @@ -534,7 +546,7 @@ def test_unicode # needs sleep so that runtime loggers dont overwrite each other initially write "features/good#{i}.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit" end - run_tests "features", type: "cucumber" + run_tests ["features"], type: "cucumber" expect(read(log).gsub(/\.\d+/, '').split("\n")).to match_array(["features/good0.feature:0", "features/good1.feature:0"]) end @@ -542,7 +554,7 @@ def test_unicode 2.times do |i| write "features/good#{i}.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" end - result = run_tests "features", type: "cucumber", add: '-n 3' + result = run_tests ["features"], type: "cucumber", add: ['-n', '3'] expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end @@ -552,7 +564,7 @@ def test_unicode write "features/pass.feature", "Feature: xxx\n Scenario: xxx\n Given I pass" write "features/fail1.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" write "features/fail2.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" - results = run_tests "features", processes: 3, type: "cucumber", fail: true + results = run_tests ["features"], processes: 3, type: "cucumber", fail: true failing_scenarios = if Gem.win_platform? ["cucumber features/fail1.feature:2 # Scenario: xxx", "cucumber features/fail2.feature:2 # Scenario: xxx"] @@ -587,7 +599,7 @@ def test_unicode | one | | two | EOS - result = run_tests "features", type: "cucumber", add: "--group-by scenarios" + result = run_tests ["features"], type: "cucumber", add: ["--group-by", "scenarios"] expect(result).to include("2 processes for 4 scenarios") end @@ -595,14 +607,14 @@ def test_unicode write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" write "features/good2.feature", "Feature: xxx\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" - result = run_tests "features", type: "cucumber", add: '--group-by steps' + result = run_tests ["features"], type: "cucumber", add: ['--group-by', 'steps'] expect(result).to include("2 processes for 2 features") end it "captures seed with random failures with --verbose" do write "features/good1.feature", "Feature: xxx\n Scenario: xxx\n Given I fail" - result = run_tests "features --verbose", type: "cucumber", add: '--test-options "--order random:1234"', fail: true + result = run_tests ["features", "--verbose"], type: "cucumber", add: ["--test-options", "--order random:1234"], fail: true expect(result).to include("Randomized with seed 1234") expect(result).to match(%r{bundle exec cucumber "?features/good1.feature"? --order random:1234}) end @@ -625,7 +637,7 @@ class A < Spinach::FeatureSteps it "runs tests which outputs accented characters" do write "features/good1.feature", "Feature: a\n Scenario: xxx\n Given I print accented characters" write "features/steps/a.rb", "#encoding: utf-8\nclass A < Spinach::FeatureSteps\nGiven 'I print accented characters' do\n puts \"I tu też\" \n end\nend" - result = run_tests "features", type: "spinach", add: 'features/good1.feature' # , :add => '--pattern good' + result = run_tests ["features"], type: "spinach", add: ['features/good1.feature'] # , :add => '--pattern good' expect(result).to include('I tu też') end @@ -634,7 +646,7 @@ class A < Spinach::FeatureSteps write "features/good2.feature", "Feature: a\n Scenario: xxx\n Given I print TEST_ENV_NUMBER" write "features/b.feature", "Feature: b\n Scenario: xxx\n Given I FAIL" # Expect this not to be run - result = run_tests "features", type: "spinach", add: '--pattern good' + result = run_tests ["features"], type: "spinach", add: ['--pattern', 'good'] expect(result).to include('YOUR TEST ENV IS 2!') expect(result).to include('YOUR TEST ENV IS !') @@ -650,7 +662,7 @@ class A < Spinach::FeatureSteps # needs sleep so that runtime loggers dont overwrite each other initially write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n And I sleep a bit" end - run_tests "features", type: "spinach" + run_tests ["features"], type: "spinach" expect(read(log).gsub(/\.\d+/, '').split("\n")).to match_array(["features/good0.feature:0", "features/good1.feature:0"]) end @@ -658,7 +670,7 @@ class A < Spinach::FeatureSteps 2.times do |i| write "features/good#{i}.feature", "Feature: A\n Scenario: xxx\n Given I print TEST_ENV_NUMBER\n" end - result = run_tests "features", type: "spinach", add: '-n 3' + result = run_tests ["features"], type: "spinach", add: ['-n', '3'] expect(result.scan(/YOUR TEST ENV IS \d?!/).sort).to eq(["YOUR TEST ENV IS !", "YOUR TEST ENV IS 2!"]) end @@ -672,7 +684,7 @@ class A < Spinach::FeatureSteps write "spec/test_spec.rb", "sleep #{timeout}; describe { specify { 'Should not get here' }; specify { p 'Should not get here either'} }" pid = nil Thread.new { sleep timeout - 0.5; Process.kill("INT", pid) } - result = run_tests("spec", processes: 2, type: 'rspec', fail: true) { |io| pid = io.pid } + result = run_tests(["spec"], processes: 2, type: 'rspec', fail: true) { |io| pid = io.pid } expect(result).to include("RSpec is shutting down") expect(result).to_not include("Should not get here") @@ -686,7 +698,7 @@ class A < Spinach::FeatureSteps pid = nil Thread.new { sleep timeout - 0.5; Process.kill("INT", pid) } Thread.new { sleep timeout - 0.3; Process.kill("INT", pid) } - result = run_tests("spec", processes: 2, type: 'rspec', fail: false) { |io| pid = io.pid } + result = run_tests(["spec"], processes: 2, type: 'rspec', fail: false) { |io| pid = io.pid } expect(result).to_not include("Should not get here") end end diff --git a/spec/parallel_tests/rspec/runtime_logger_spec.rb b/spec/parallel_tests/rspec/runtime_logger_spec.rb index 992177392..23f62e5c6 100644 --- a/spec/parallel_tests/rspec/runtime_logger_spec.rb +++ b/spec/parallel_tests/rspec/runtime_logger_spec.rb @@ -90,7 +90,7 @@ def write(file, content) system( { 'TEST_ENV_NUMBER' => '1' }, - "rspec spec -I #{Bundler.root.join("lib")} --format ParallelTests::RSpec::RuntimeLogger --out runtime.log 2>&1" + "rspec", "spec", "-I", Bundler.root.join("lib").to_s, "--format", "ParallelTests::RSpec::RuntimeLogger", "--out", "runtime.log" ) || raise("nope") result = File.read("runtime.log") @@ -122,7 +122,7 @@ def write(file, content) system( { 'TEST_ENV_NUMBER' => '1' }, - "rspec spec -I #{Bundler.root.join("lib")} --format ParallelTests::RSpec::RuntimeLogger --out runtime.log 2>&1" + "rspec", "spec", "-I", Bundler.root.join("lib").to_s, "--format", "ParallelTests::RSpec::RuntimeLogger", "--out", "runtime.log" ) || raise("nope") result = File.read("runtime.log") diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index 688ae5151..eeff41554 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -92,7 +92,7 @@ def call(command, grep) # Explictly run as a parameter to /bin/sh to simulate how # the command will be run by parallel_test --exec # This also tests shell escaping of single quotes - result = `/bin/sh -c '#{ParallelTests::Tasks.suppress_output(command, grep)}'` + result = IO.popen(['/bin/sh', '-c', ParallelTests::Tasks.suppress_output(command, grep)], &:read) [result, $?.success?] end diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 2ad9e6a74..800720026 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -264,7 +264,7 @@ def call(*args) it "finds test files nested in symlinked folders" do with_files(['a/a_test.rb', 'b/b_test.rb']) do |root| - `ln -s #{root}/a #{root}/b/link` + File.symlink("#{root}/a", "#{root}/b/link") expect(call(["#{root}/b"]).sort).to eq( [ "#{root}/b/b_test.rb", @@ -277,7 +277,7 @@ def call(*args) it "finds test files but ignores those in symlinked folders" do skip if RUBY_PLATFORM == "java" || Gem.win_platform? with_files(['a/a_test.rb', 'b/b_test.rb']) do |root| - `ln -s #{root}/a #{root}/b/link` + File.symlink("#{root}/a", "#{root}/b/link") expect(call(["#{root}/b"], symlinks: false).sort).to eq(["#{root}/b/b_test.rb"]) end end diff --git a/spec/parallel_tests/test/runtime_logger_spec.rb b/spec/parallel_tests/test/runtime_logger_spec.rb index ad856bb51..f609fdd53 100644 --- a/spec/parallel_tests/test/runtime_logger_spec.rb +++ b/spec/parallel_tests/test/runtime_logger_spec.rb @@ -2,13 +2,13 @@ require 'spec_helper' describe ParallelTests::Test::RuntimeLogger do - def sh(command) - result = `#{command} 2>&1` + def run(command) + result = IO.popen(command, err: [:child, :out], &:read) raise "FAILED: #{result}" unless $?.success? end def run_tests - sh "ruby #{Bundler.root}/bin/parallel_test test -n 2" + run ["ruby", "#{Bundler.root}/bin/parallel_test", "test", "-n", "2"] end it "writes a correct log on minitest-5" do diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index 1b88d8205..bbd764e39 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -5,11 +5,8 @@ describe 'rails' do let(:test_timeout) { 800 } # this can take very long on fresh bundle ... - def sh(command, options = {}) - result = '' - IO.popen(options.fetch(:environment, {}), command, err: [:child, :out]) do |io| - result = io.read - end + def run(command, options = {}) + result = IO.popen(options.fetch(:environment, {}), command, err: [:child, :out], &:read) raise "FAILED #{command}\n#{result}" if $?.success? == !!options[:fail] result end @@ -28,15 +25,15 @@ def sh(command, options = {}) ENV.delete("RAILS_ENV") ENV.delete("RACK_ENV") - sh "bundle config --local path vendor/bundle" - sh "bundle install" + run ["bundle", "config", "--local", "path", "vendor/bundle"] + run ["bundle", "install"] FileUtils.rm_f(Dir['db/*.sqlite3']) - sh "bundle exec rake db:setup parallel:create --trace 2>&1" + run ["bundle", "exec", "rake", "db:setup", "parallel:create"] # Also test the case where the DBs need to be dropped - sh "bundle exec rake parallel:drop parallel:create" - sh "bundle exec rake parallel:prepare" - sh "bundle exec rails runner User.create", environment: { 'RAILS_ENV' => 'test' } # pollute the db - out = sh "bundle exec rake parallel:prepare parallel:test" + run ["bundle", "exec", "rake", "parallel:drop", "parallel:create"] + run ["bundle", "exec", "rake", "parallel:prepare"] + run ["bundle", "exec", "rails", "runner", "User.create"], environment: { 'RAILS_ENV' => 'test' } # pollute the db + out = run ["bundle", "exec", "rake", "parallel:prepare", "parallel:test"] expect(out).to match(/ 2 (tests|runs)/) end end From 5ac27e9f551840722c830cf72bec64a3e2ef325d Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 15 May 2022 15:13:15 -0700 Subject: [PATCH 113/177] Changed subprocesses to execute without a shell. (#855) Treat subprocess commands as an array of strings. This avoid the need to include a shell in the subprocess. Instead, the commands execute directly. As well, there is less need to parse or format shell syntax (such as string quoting). Continue to handle IO redirection through IO.popen. As a caution, this may be considered a backward incompatible change if users are relying on injecting shell features through the CLI. I don't expect this to be an issue in practice, but am raising it just in case. It would be best to apply a major version bump before release to maintain semantic versioning. --- CHANGELOG.md | 2 +- lib/parallel_tests.rb | 2 +- lib/parallel_tests/cli.rb | 10 +-- lib/parallel_tests/cucumber/runner.rb | 4 +- lib/parallel_tests/cucumber/scenarios.rb | 3 +- lib/parallel_tests/gherkin/runner.rb | 25 +++----- lib/parallel_tests/rspec/runner.rb | 21 +++---- lib/parallel_tests/tasks.rb | 28 +++++---- lib/parallel_tests/test/runner.rb | 58 ++++++++++++++--- spec/integration_spec.rb | 4 +- spec/parallel_tests/cli_spec.rb | 30 ++++----- spec/parallel_tests/cucumber/runner_spec.rb | 10 +-- .../parallel_tests/cucumber/scenarios_spec.rb | 40 ++++++------ .../gherkin/runner_behaviour.rb | 63 ++++++------------- spec/parallel_tests/rspec/runner_spec.rb | 43 +++++++------ spec/parallel_tests/tasks_spec.rb | 26 +++++--- spec/parallel_tests/test/runner_spec.rb | 58 ++++++++--------- spec/parallel_tests_spec.rb | 2 +- spec/spec_helper.rb | 11 ++-- 19 files changed, 226 insertions(+), 214 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcfe0b399..ad166fb8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ### Breaking Changes -- None +- Changed subprocesses to execute without a shell. ### Added diff --git a/lib/parallel_tests.rb b/lib/parallel_tests.rb index 84030f862..356ba7eff 100644 --- a/lib/parallel_tests.rb +++ b/lib/parallel_tests.rb @@ -76,7 +76,7 @@ def last_process? end def with_ruby_binary(command) - WINDOWS ? "#{RUBY_BINARY} -- #{command}" : command + WINDOWS ? [RUBY_BINARY, '--', command] : [command] end def wait_for_other_processes_to_finish diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index cf05eaabe..d056307b8 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -100,7 +100,7 @@ def run_tests_in_parallel(num_processes, options) def run_tests(group, process_number, num_processes, options) if group.empty? - { stdout: '', exit_status: 0, command: '', seed: nil } + { stdout: '', exit_status: 0, command: nil, seed: nil } else @runner.run_tests(group, process_number, num_processes, options) end @@ -141,7 +141,7 @@ def report_failure_rerun_commmand(test_results, options) failing_sets.each do |failing_set| command = failing_set[:command] command = @runner.command_with_seed(command, failing_set[:seed]) if failing_set[:seed] - puts command + puts Shellwords.shelljoin(command) end end end @@ -238,7 +238,7 @@ def parse_options!(argv) opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } - opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = arg.lstrip } + opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = Shellwords.shellsplit(arg) } opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber / spinach") do |type| @runner = load_runner(type) rescue NameError, LoadError => e @@ -333,8 +333,8 @@ def append_test_options(options, argv) new_opts = extract_test_options(argv) return if new_opts.empty? - prev_and_new = [options[:test_options], new_opts.shelljoin] - options[:test_options] = prev_and_new.compact.join(' ') + options[:test_options] ||= [] + options[:test_options] += new_opts end def load_runner(type) diff --git a/lib/parallel_tests/cucumber/runner.rb b/lib/parallel_tests/cucumber/runner.rb index a352b43d0..52805136e 100644 --- a/lib/parallel_tests/cucumber/runner.rb +++ b/lib/parallel_tests/cucumber/runner.rb @@ -35,8 +35,8 @@ def summarize_results(results) end def command_with_seed(cmd, seed) - clean = cmd.sub(/\s--order\s+random(:\d+)?\b/, '') - "#{clean} --order random:#{seed}" + clean = remove_command_arguments(cmd, '--order') + [*clean, '--order', "random:#{seed}"] end end end diff --git a/lib/parallel_tests/cucumber/scenarios.rb b/lib/parallel_tests/cucumber/scenarios.rb index 0b2574825..15852cdcd 100644 --- a/lib/parallel_tests/cucumber/scenarios.rb +++ b/lib/parallel_tests/cucumber/scenarios.rb @@ -4,7 +4,6 @@ require 'cucumber' require 'parallel_tests/cucumber/scenario_line_logger' require 'parallel_tests/gherkin/listener' -require 'shellwords' begin gem "cuke_modeler", "~> 3.0" @@ -20,7 +19,7 @@ class << self def all(files, options = {}) # Parse tag expression from given test options and ignore tag pattern. Refer here to understand how new tag expression syntax works - https://github.com/cucumber/cucumber/tree/master/tag-expressions tags = [] - words = options[:test_options].to_s.shellsplit + words = options[:test_options] || [] words.each_with_index { |w, i| tags << words[i + 1] if ["-t", "--tags"].include?(w) } if ignore = options[:ignore_tag_pattern] tags << "not (#{ignore})" diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index 5e2b7bb0d..b41463a36 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -1,6 +1,5 @@ # frozen_string_literal: true require "parallel_tests/test/runner" -require 'shellwords' module ParallelTests module Gherkin @@ -16,17 +15,13 @@ def run_tests(test_files, process_number, num_processes, options) end end - sanitized_test_files = combined_scenarios.map { |val| WINDOWS ? "\"#{val}\"" : Shellwords.escape(val) } - options[:env] ||= {} options[:env] = options[:env].merge({ 'AUTOTEST' => '1' }) if $stdout.tty? - cmd = [ - executable, - (runtime_logging if File.directory?(File.dirname(runtime_log))), - *sanitized_test_files, - cucumber_opts(options[:test_options]) - ].compact.reject(&:empty?).join(' ') + cmd = executable + cmd += runtime_logging if File.directory?(File.dirname(runtime_log)) + cmd += combined_scenarios + cmd += cucumber_opts(options[:test_options]) execute_command(cmd, process_number, num_processes, options) end @@ -67,17 +62,17 @@ def summarize_results(results) end def cucumber_opts(given) - if given =~ (/--profile/) || given =~ (/(^|\s)-p /) + if given&.include?('--profile') || given&.include?('-p') given else - [given, profile_from_config].compact.join(" ") + [*given, *profile_from_config] end end def profile_from_config # copied from https://github.com/cucumber/cucumber/blob/master/lib/cucumber/cli/profile_loader.rb#L85 config = Dir.glob("{,.config/,config/}#{name}{.yml,.yaml}").first - "--profile parallel" if config && File.read(config) =~ /^parallel:/ + ['--profile', 'parallel'] if config && File.read(config) =~ /^parallel:/ end def tests_in_groups(tests, num_groups, options = {}) @@ -91,7 +86,7 @@ def tests_in_groups(tests, num_groups, options = {}) end def runtime_logging - "--format ParallelTests::Gherkin::RuntimeLogger --out #{runtime_log}" + ['--format', 'ParallelTests::Gherkin::RuntimeLogger', '--out', runtime_log] end def runtime_log @@ -102,11 +97,11 @@ def determine_executable if File.exist?("bin/#{name}") ParallelTests.with_ruby_binary("bin/#{name}") elsif ParallelTests.bundler_enabled? - "bundle exec #{name}" + ["bundle", "exec", name] elsif File.file?("script/#{name}") ParallelTests.with_ruby_binary("script/#{name}") else - name.to_s + [name.to_s] end end end diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index 7c8b494cc..617d5f42f 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -7,8 +7,7 @@ class Runner < ParallelTests::Test::Runner DEV_NULL = (WINDOWS ? "NUL" : "/dev/null") class << self def run_tests(test_files, process_number, num_processes, options) - exe = executable # expensive, so we cache - cmd = [exe, options[:test_options], color, spec_opts, *test_files].compact.join(" ") + cmd = [*executable, *options[:test_options], *color, *spec_opts, *test_files] execute_command(cmd, process_number, num_processes, options) end @@ -16,9 +15,9 @@ def determine_executable if File.exist?("bin/rspec") ParallelTests.with_ruby_binary("bin/rspec") elsif ParallelTests.bundler_enabled? - "bundle exec rspec" + ["bundle", "exec", "rspec"] else - "rspec" + ["rspec"] end end @@ -48,8 +47,8 @@ def line_is_result?(line) # --order rand:1234 # --order random:1234 def command_with_seed(cmd, seed) - clean = cmd.sub(/\s--(seed\s+\d+|order\s+rand(om)?(:\d+)?)\b/, '') - "#{clean} --seed #{seed}" + clean = remove_command_arguments(cmd, '--seed', '--order') + [*clean, '--seed', seed] end # Summarize results from threads and colorize results based on failure and pending counts. @@ -71,19 +70,13 @@ def summarize_results(results) private - # so it can be stubbed.... - def run(cmd) - `#{cmd}` - end - def color - '--color --tty' if $stdout.tty? + ['--color', '--tty'] if $stdout.tty? end def spec_opts options_file = ['.rspec_parallel', 'spec/parallel_spec.opts', 'spec/spec.opts'].detect { |f| File.file?(f) } - return unless options_file - "-O #{options_file}" + ["-O", options_file] if options_file end end end diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 76b13aed9..d7948ba61 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -30,12 +30,15 @@ def purge_before_load def run_in_parallel(cmd, options = {}) load_lib - count = " -n #{options[:count]}" unless options[:count].to_s.empty? + # Using the relative path to find the binary allow to run a specific version of it executable = File.expand_path('../../bin/parallel_test', __dir__) - non_parallel = (options[:non_parallel] ? ' --non-parallel' : '') - command = "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} --exec '#{cmd}'#{count}#{non_parallel}" - abort unless system(command) + command = ParallelTests.with_ruby_binary(executable) + command += ['--exec', cmd] + command += ['-n', options[:count]] unless options[:count].to_s.empty? + command << '--non-parallel' if options[:non_parallel] + + abort unless system(*command) end # this is a crazy-complex solution for a very simple problem: @@ -89,7 +92,7 @@ def parse_args(args) options = args.shift pass_through = args.shift - [num_processes, pattern.to_s, options.to_s, pass_through.to_s] + [num_processes, pattern, options, pass_through] end def schema_format_based_on_rails_version @@ -233,14 +236,13 @@ def rails_61_or_greater? # Using the relative path to find the binary allow to run a specific version of it executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') - command = - "#{ParallelTests.with_ruby_binary(Shellwords.escape(executable))} #{type} " \ - "--type #{test_framework} " \ - "-n #{count} " \ - "--pattern '#{pattern}' " \ - "--test-options '#{options}' " \ - "#{pass_through}" - abort unless system(command) # allow to chain tasks e.g. rake parallel:spec parallel:features + command = [*ParallelTests.with_ruby_binary(executable), type, '--type', test_framework] + command += ['-n', count] if count + command += ['--pattern', pattern] if pattern + command += ['--test-options', options] if options + command << pass_through if pass_through + + abort unless system(*command) # allow to chain tasks e.g. rake parallel:spec parallel:features end end end diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 67283dfb2..e28e4e645 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true +require 'shellwords' require 'parallel_tests' module ParallelTests @@ -25,7 +26,14 @@ def test_file_name def run_tests(test_files, process_number, num_processes, options) require_list = test_files.map { |file| file.gsub(" ", "\\ ") }.join(" ") - cmd = "#{executable} -Itest -e '%w[#{require_list}].each { |f| require %{./\#{f}} }' -- #{options[:test_options]}" + cmd = [ + *executable, + '-Itest', + '-e', + "%w[#{require_list}].each { |f| require %{./\#{f}} }", + '--', + *options[:test_options] + ] execute_command(cmd, process_number, num_processes, options) end @@ -81,17 +89,20 @@ def execute_command(cmd, process_number, num_processes, options) "PARALLEL_TEST_GROUPS" => num_processes.to_s, "PARALLEL_PID_FILE" => ParallelTests.pid_file_path ) - cmd = "nice #{cmd}" if options[:nice] - cmd = "#{cmd} 2>&1" if options[:combine_stderr] + cmd = ["nice", *cmd] if options[:nice] - puts cmd if report_process_command?(options) && !options[:serialize_stdout] + puts command_string(cmd) if report_process_command?(options) && !options[:serialize_stdout] execute_command_and_capture_output(env, cmd, options) end def execute_command_and_capture_output(env, cmd, options) pid = nil - output = IO.popen(env, cmd) do |io| + + popen_options = {} + popen_options[:err] = [:child, :out] if options[:combine_stderr] + + output = IO.popen(env, cmd, popen_options) do |io| pid = io.pid ParallelTests.pids.add(pid) capture_output(io, env, options) @@ -100,7 +111,7 @@ def execute_command_and_capture_output(env, cmd, options) exitstatus = $?.exitstatus seed = output[/seed (\d+)/, 1] - output = [cmd, output].join("\n") if report_process_command?(options) && options[:serialize_stdout] + output = "#{command_string(cmd)}\n#{output}" if report_process_command?(options) && options[:serialize_stdout] { stdout: output, exit_status: exitstatus, command: cmd, seed: seed } end @@ -129,18 +140,22 @@ def summarize_results(results) # remove old seed and add new seed def command_with_seed(cmd, seed) - clean = cmd.sub(/\s--seed\s+\d+\b/, '') - "#{clean} --seed #{seed}" + clean = remove_command_arguments(cmd, '--seed') + [*clean, '--seed', seed] end protected def executable - ENV['PARALLEL_TESTS_EXECUTABLE'] || determine_executable + if ENV.include?('PARALLEL_TESTS_EXECUTABLE') + [ENV['PARALLEL_TESTS_EXECUTABLE']] + else + determine_executable + end end def determine_executable - "ruby" + ["ruby"] end def sum_up_results(results) @@ -237,6 +252,21 @@ def files_in_folder(folder, options = {}) Dir[File.join(folder, pattern)].uniq.sort end + def remove_command_arguments(command, *args) + remove_next = false + command.select do |arg| + if remove_next + remove_next = false + false + elsif args.include?(arg) + remove_next = true + false + else + true + end + end + end + private # fill gaps with unknown-runtime if given, average otherwise @@ -252,6 +282,14 @@ def set_unknown_runtime(tests, options) def report_process_command?(options) options[:verbose] || options[:verbose_process_command] end + + def command_string(command) + if command.is_a?(String) + command + else + Shellwords.shelljoin(command) + end + end end end end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 29b0e6494..f56d9e36b 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -385,7 +385,7 @@ def test_unicode write "test/xxx_test.rb", 'puts "Test output: YES"' result = run_tests(["test"], processes: 2, type: 'test', add: ['--verbose']) expect(result).to include "Test output: YES" - expect(result).to include "[test/xxx_test.rb]" + expect(result).to include "\\[test/xxx_test.rb\\]" expect(result).not_to include Dir.pwd end @@ -487,7 +487,7 @@ def test_unicode write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){1.should == 2}}' result = run_tests ["spec", "--verbose"], add: ["--test-options", "--seed 1234"], fail: true, type: 'rspec' expect(result).to include("Randomized with seed 1234") - expect(result).to include("bundle exec rspec spec/xxx2_spec.rb --seed 1234") + expect(result).to include("bundle exec rspec --seed 1234 spec/xxx2_spec.rb") end end diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 0a6cd1579..5404148e8 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -153,24 +153,24 @@ def call(*args) context "when the -o options has also been given" do it "merges the options together" do - expect(call(['-o', "'-f'", '--', 'test', '--foo', 'test2'])).to eq(files: ['test', '--foo', 'test2'], test_options: "'-f'") + expect(call(['-o', "'-f'", '--', 'test', '--foo', 'test2'])).to eq(files: ['test', '--foo', 'test2'], test_options: ['-f']) end end context "when a second -- option separator is used" do it "interprets the first set as test_options" do - expect(call(['--', '-r', 'foo', '--', 'test'])).to eq(files: ['test'], test_options: '-r foo') - expect(call(['--', '-r', 'foo', '--', 'test', 'test2'])).to eq(files: ['test', 'test2'], test_options: '-r foo') - expect(call(['--', '-r', 'foo', '-o', 'out.log', '--', 'test', 'test2'])).to eq(files: ['test', 'test2'], test_options: '-r foo -o out.log') + expect(call(['--', '-r', 'foo', '--', 'test'])).to eq(files: ['test'], test_options: ['-r', 'foo']) + expect(call(['--', '-r', 'foo', '--', 'test', 'test2'])).to eq(files: ['test', 'test2'], test_options: ['-r', 'foo']) + expect(call(['--', '-r', 'foo', '-o', 'out.log', '--', 'test', 'test2'])).to eq(files: ['test', 'test2'], test_options: ['-r', 'foo', '-o', 'out.log']) end context "when existing test_options have previously been given" do it "appends the new options" do - expect(call(['-o', "'-f'", '--', '-r', 'foo.rb', '--', 'test'])).to eq(files: ['test'], test_options: "'-f' -r foo.rb") + expect(call(['-o', '-f', '--', '-r', 'foo.rb', '--', 'test'])).to eq(files: ['test'], test_options: ['-f', '-r', 'foo.rb']) end it "correctly handles argument values with spaces" do argv = ["-o 'path with spaces1'", '--', '--out', 'path with spaces2', '--', 'foo'] - expected_test_options = "'path with spaces1' --out path\\ with\\ spaces2" + expected_test_options = ['path with spaces1', '--out', 'path with spaces2'] expect(call(argv)).to eq(files: ['foo'], test_options: expected_test_options) end end @@ -202,7 +202,7 @@ def call(*args) end describe ".report_failure_rerun_commmand" do - let(:single_failed_command) { [{ exit_status: 1, command: 'foo', seed: nil, output: 'blah' }] } + let(:single_failed_command) { [{ exit_status: 1, command: ['foo'], seed: nil, output: 'blah' }] } it "prints nothing if there are no failures" do expect($stdout).not_to receive(:puts) @@ -253,9 +253,9 @@ def self.it_prints_nothing_about_rerun_commands(options) subject.send( :report_failure_rerun_commmand, [ - { exit_status: 1, command: 'foo', seed: nil, output: 'blah' }, - { exit_status: 1, command: 'bar', seed: nil, output: 'blah' }, - { exit_status: 1, command: 'baz', seed: nil, output: 'blah' } + { exit_status: 1, command: ['foo'], seed: nil, output: 'blah' }, + { exit_status: 1, command: ['bar'], seed: nil, output: 'blah' }, + { exit_status: 1, command: ['baz'], seed: nil, output: 'blah' } ], { verbose: true } ) @@ -267,9 +267,9 @@ def self.it_prints_nothing_about_rerun_commands(options) subject.send( :report_failure_rerun_commmand, [ - { exit_status: 1, command: 'foo --color', seed: nil, output: 'blah' }, - { exit_status: 0, command: 'bar', seed: nil, output: 'blah' }, - { exit_status: 1, command: 'baz', seed: nil, output: 'blah' } + { exit_status: 1, command: ['foo', '--color'], seed: nil, output: 'blah' }, + { exit_status: 0, command: ['bar'], seed: nil, output: 'blah' }, + { exit_status: 1, command: ['baz'], seed: nil, output: 'blah' } ], { verbose: true } ) @@ -277,12 +277,12 @@ def self.it_prints_nothing_about_rerun_commands(options) end it "prints the command with the seed added by the runner" do - command = 'rspec --color spec/foo_spec.rb' + command = ['rspec', '--color', 'spec/foo_spec.rb'] seed = 555 subject.instance_variable_set(:@runner, ParallelTests::Test::Runner) expect(ParallelTests::Test::Runner).to receive(:command_with_seed).with(command, seed) - .and_return("my seeded command result --seed #{seed}") + .and_return(['my', 'seeded', 'command', 'result', '--seed', seed]) single_failed_command[0].merge!(seed: seed, command: command) expect do diff --git a/spec/parallel_tests/cucumber/runner_spec.rb b/spec/parallel_tests/cucumber/runner_spec.rb index 78d828e80..eb52cf851 100644 --- a/spec/parallel_tests/cucumber/runner_spec.rb +++ b/spec/parallel_tests/cucumber/runner_spec.rb @@ -37,20 +37,20 @@ def call(*args) end describe ".command_with_seed" do - def call(part) - ParallelTests::Cucumber::Runner.command_with_seed("cucumber#{part}", 555) + def call(*args) + ParallelTests::Cucumber::Runner.command_with_seed(['cucumber', *args], 555) end it "adds the randomized seed" do - expect(call("")).to eq("cucumber --order random:555") + expect(call).to eq(["cucumber", "--order", "random:555"]) end it "does not duplicate existing random command" do - expect(call(" --order random good1.feature")).to eq("cucumber good1.feature --order random:555") + expect(call("--order", "random", "good1.feature")).to eq(["cucumber", "good1.feature", "--order", "random:555"]) end it "does not duplicate existing random command with seed" do - expect(call(" --order random:123 good1.feature")).to eq("cucumber good1.feature --order random:555") + expect(call("--order", "random:123", "good1.feature")).to eq(["cucumber", "good1.feature", "--order", "random:555"]) end end end diff --git a/spec/parallel_tests/cucumber/scenarios_spec.rb b/spec/parallel_tests/cucumber/scenarios_spec.rb index 07caa13c6..598bd7a00 100644 --- a/spec/parallel_tests/cucumber/scenarios_spec.rb +++ b/spec/parallel_tests/cucumber/scenarios_spec.rb @@ -87,59 +87,59 @@ end it 'Single Feature Tag: colours' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @colours") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@colours"]) expect(scenarios.length).to eq 7 end it 'Single Scenario Tag: white' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @white") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@white"]) expect(scenarios.length).to eq 2 end it 'Multiple Scenario Tags 1: black && white' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@black and @white'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@black and @white"]) expect(scenarios.length).to eq 1 end it 'Multiple Scenario Tags 2: black || white scenarios' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@black or @white'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@black or @white"]) expect(scenarios.length).to eq 3 end it 'Scenario Outline Tag: red' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @red") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@red"]) expect(scenarios.length).to eq 4 end it 'Example Tag: blue' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t @blue") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@blue"]) expect(scenarios.length).to eq 3 end it 'Multiple Example Tags 1: blue && green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@blue and @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@blue and @green"]) expect(scenarios.length).to eq 1 end it 'Multiple Example Tags 2: blue || green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@blue or @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@blue or @green"]) expect(scenarios.length).to eq 4 end it 'Single Negative Feature Tag: !colours' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @colours'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "not @colours"]) expect(scenarios.length).to eq 0 end it 'Single Negative Scenario Tag: !black' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @black'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "not @black"]) expect(scenarios.length).to eq 5 end it 'Multiple Negative Scenario Tags And: !(black && white)' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "-t 'not (@black and @white)'" + test_options: ["-t", "not (@black and @white)"] ) expect(scenarios.length).to eq 6 end @@ -147,25 +147,25 @@ it 'Multiple Negative Scenario Tags Or: !(black || red)' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "-t 'not (@black or @red)'" + test_options: ["-t", "not (@black or @red)"] ) expect(scenarios.length).to eq 1 end it 'Negative Scenario Outline Tag: !red' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @red'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "not @red"]) expect(scenarios.length).to eq 3 end it 'Negative Example Tag: !blue' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t 'not @blue'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "not @blue"]) expect(scenarios.length).to eq 4 end it 'Multiple Negative Example Tags 1: !blue && !green' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "-t 'not @blue and not @green'" + test_options: ["-t", "not @blue and not @green"] ) expect(scenarios.length).to eq 3 end @@ -173,20 +173,20 @@ it 'Multiple Negative Example Tags 2: !blue || !green) ' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "-t 'not @blue or not @green'" + test_options: ["-t", "not @blue or not @green"] ) expect(scenarios.length).to eq 6 end it 'Scenario and Example Mixed Tags: black || green' do - scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: "-t '@black or @green'") + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path], test_options: ["-t", "@black or @green"]) expect(scenarios.length).to eq 4 end it 'Positive and Negative Mixed Tags: red && !blue' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "-t '@red and not @blue'" + test_options: ["-t", "@red and not @blue"] ) expect(scenarios.length).to eq 1 end @@ -194,7 +194,7 @@ it 'Multiple Positive and Negative Mixed Tags: (white && black) || (red && !blue)' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "--tags '(not @white and @black) or (@red and not @green)'" + test_options: ["--tags", "(not @white and @black) or (@red and not @green)"] ) expect(scenarios.length).to eq 3 end @@ -227,7 +227,7 @@ it 'Scenario Mixed tags: black && !blue with Ignore Tag Pattern Multiple Tags: red || white' do scenarios = ParallelTests::Cucumber::Scenarios.all( [feature_file.path], - test_options: "-t '@black and not @blue'", ignore_tag_pattern: "@red or @white" + test_options: ["-t", "@black and not @blue"], ignore_tag_pattern: "@red or @white" ) expect(scenarios.length).to eq 1 end diff --git a/spec/parallel_tests/gherkin/runner_behaviour.rb b/spec/parallel_tests/gherkin/runner_behaviour.rb index f6451bb0e..ab9863455 100644 --- a/spec/parallel_tests/gherkin/runner_behaviour.rb +++ b/spec/parallel_tests/gherkin/runner_behaviour.rb @@ -16,7 +16,7 @@ def call(*args) it "allows to override runner executable via PARALLEL_TESTS_EXECUTABLE" do ENV['PARALLEL_TESTS_EXECUTABLE'] = 'script/custom_rspec' - should_run_with(%r{script/custom_rspec}) + should_run_with ["script/custom_rspec"] call(['xxx'], 1, 22, {}) end @@ -29,39 +29,34 @@ def call(*args) it "runs bundle exec {runner_name} when on bundler 0.9" do allow(ParallelTests).to receive(:bundler_enabled?).and_return true - should_run_with /bundle exec #{runner_name}/ + should_run_with ["bundle", "exec", runner_name] call(['xxx'], 1, 22, {}) end it "runs script/{runner_name} when script/{runner_name} is found" do - should_run_with %r{script/#{runner_name}} + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}") call(['xxx'], 1, 22, {}) end it "runs {runner_name} by default" do allow(File).to receive(:file?).with("script/#{runner_name}").and_return false - should_run_with /^#{runner_name}/ + should_run_with [runner_name] call(['xxx'], 1, 22, {}) end it "uses bin/{runner_name} when present" do allow(File).to receive(:exist?).with("bin/#{runner_name}").and_return true - should_run_with %r{bin/#{runner_name}} + should_run_with ParallelTests.with_ruby_binary("bin/#{runner_name}") call(['xxx'], 1, 22, {}) end it "uses options passed in" do - should_run_with %r{script/#{runner_name} .*-p default} - call(['xxx'], 1, 22, test_options: '-p default') + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}"), "-p", "default" + call(['xxx'], 1, 22, test_options: ['-p', 'default']) end it "sanitizes dangerous file runner_names" do - if ParallelTests::WINDOWS - should_run_with /"xx x"/ - else - should_run_with /xx\\ x/ - end - + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}"), "xx x" call(['xx x'], 1, 22, {}) end @@ -73,46 +68,31 @@ def call(*args) end it "uses parallel profile" do - if ParallelTests::WINDOWS - should_run_with %r{script/#{runner_name} "xxx" .*foo bar --profile parallel} - else - should_run_with %r{script/#{runner_name} xxx .*foo bar --profile parallel} - end - - call(['xxx'], 1, 22, test_options: 'foo bar') + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}"), "xxx", "foo", "bar", "--profile", "parallel" + call(['xxx'], 1, 22, test_options: ['foo', 'bar']) end it "uses given profile via --profile" do - if ParallelTests::WINDOWS - should_run_with %r{script/#{runner_name} "xxx" .*--profile foo$} - else - should_run_with %r{script/#{runner_name} xxx .*--profile foo$} - end - - call(['xxx'], 1, 22, test_options: '--profile foo') + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}"), "--profile", "foo" + call(['xxx'], 1, 22, test_options: ['--profile', 'foo']) end it "uses given profile via -p" do - if ParallelTests::WINDOWS - should_run_with %r{script/#{runner_name} "xxx" .*-p foo$} - else - should_run_with %r{script/#{runner_name} xxx .*-p foo$} - end - - call(['xxx'], 1, 22, test_options: '-p foo') + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}"), "-p", "foo" + call(['xxx'], 1, 22, test_options: ['-p', 'foo']) end end it "does not use parallel profile if config/{runner_name}.yml does not contain it" do file_contents = 'blob: -f progress' - should_run_with %r{script/#{runner_name} .*foo bar} + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}"), "foo", "bar" expect(Dir).to receive(:glob).and_return ["config/#{runner_name}.yml"] expect(File).to receive(:read).with("config/#{runner_name}.yml").and_return file_contents - call(['xxx'], 1, 22, test_options: 'foo bar') + call(['xxx'], 1, 22, test_options: ['foo', 'bar']) end it "does not use the parallel profile if config/{runner_name}.yml does not exist" do - should_run_with %r{script/#{runner_name}} # TODO: this test looks useless... + should_run_with ParallelTests.with_ruby_binary("script/#{runner_name}") # TODO: this test looks useless... expect(Dir).to receive(:glob).and_return [] call(['xxx'], 1, 22, {}) end @@ -222,13 +202,8 @@ def call(*args) test_files = ['features/a.rb:23', 'features/a.rb:44', 'features/b.rb:12'] expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _b, _c, _d| - argv = a.split.last(2) - - if ParallelTests::WINDOWS - expect(argv).to eq(['"features/a.rb:23:44"', '"features/b.rb:12"']) - else - expect(argv).to eq(["features/a.rb:23:44", "features/b.rb:12"]) - end + argv = a.last(2) + expect(argv).to eq(["features/a.rb:23:44", "features/b.rb:12"]) end call(test_files, 1, 2, { group_by: :scenarios }) diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index 58312433a..ba354a220 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -20,7 +20,7 @@ def call(*args) it "runs command using nice when specifed" do ParallelTests.with_pid_file do expect(ParallelTests::Test::Runner).to receive(:execute_command_and_capture_output) do |_a, b, _c| - expect(b).to match(/^nice rspec/) + expect(b.first(2)).to eq(["nice", "rspec"]) end call('xxx', 1, 22, nice: true) @@ -28,26 +28,26 @@ def call(*args) end it "runs with color when called from cmdline" do - should_run_with(/ --tty/) + should_run_with ["rspec"], "--tty" expect($stdout).to receive(:tty?).and_return true call('xxx', 1, 22, {}) end it "runs without color when not called from cmdline" do - should_not_run_with(/ --tty/) + should_not_run_with('--tty') expect($stdout).to receive(:tty?).and_return false call('xxx', 1, 22, {}) end it "uses bin/rspec when present" do allow(File).to receive(:exist?).with('bin/rspec').and_return true - should_run_with %r{bin/rspec} + should_run_with ParallelTests.with_ruby_binary("bin/rspec") call('xxx', 1, 22, {}) end it "uses no -O when no opts where found" do allow(File).to receive(:file?).with('spec/spec.opts').and_return false - should_not_run_with %r{spec/spec.opts} + should_not_run_with 'spec/spec.opts' call('xxx', 1, 22, {}) end @@ -56,15 +56,14 @@ def call(*args) expect(File).to receive(:file?).with('spec/parallel_spec.opts').and_return true allow(ParallelTests).to receive(:bundler_enabled?).and_return true - allow(ParallelTests::RSpec::Runner).to receive(:run).with("bundle info rspec-core").and_return "/foo/bar/rspec-core-2.4.2" - should_run_with %r{rspec\s+(--color --tty )?-O spec/parallel_spec.opts} + should_run_with ["bundle", "exec", "rspec"], "-O", "spec/parallel_spec.opts", "xxx" call('xxx', 1, 22, {}) end it "uses options passed in" do - should_run_with /rspec -f n/ - call('xxx', 1, 22, test_options: '-f n') + should_run_with ["rspec"], "-f", "n" + call('xxx', 1, 22, test_options: ['-f', 'n']) end it "returns the output" do @@ -178,42 +177,42 @@ def call(*args) end describe ".command_with_seed" do - def call(args) - base = "ruby -Ilib:test test/minitest/test_minitest_unit.rb" - result = ParallelTests::RSpec::Runner.command_with_seed("#{base}#{args}", 555) - result.sub(base, '') + def call(*args) + base = ["ruby", "-Ilib:test", "test/minitest/test_minitest_unit.rb"] + result = ParallelTests::RSpec::Runner.command_with_seed([*base, *args], "555") + result[base.length..-1] end it "adds the randomized seed" do - expect(call("")).to eq(" --seed 555") + expect(call).to eq(["--seed", "555"]) end it "does not duplicate seed" do - expect(call(" --seed 123")).to eq(" --seed 555") + expect(call("--seed", "123")).to eq(["--seed", "555"]) end - it "does not match strange seeds stuff" do - expect(call(" --seed 123asdasd")).to eq(" --seed 123asdasd --seed 555") + it "does not duplicate strange seeds" do + expect(call("--seed", "123asdasd")).to eq(["--seed", "555"]) end it "does not match non seeds" do - expect(call(" --seedling 123")).to eq(" --seedling 123 --seed 555") + expect(call("--seedling", "123")).to eq(["--seedling", "123", "--seed", "555"]) end it "does not duplicate random" do - expect(call(" --order random")).to eq(" --seed 555") + expect(call("--order", "random")).to eq(["--seed", "555"]) end it "does not duplicate rand" do - expect(call(" --order rand")).to eq(" --seed 555") + expect(call("--order", "rand")).to eq(["--seed", "555"]) end it "does not duplicate rand with seed" do - expect(call(" --order rand:123")).to eq(" --seed 555") + expect(call("--order", "rand:123")).to eq(["--seed", "555"]) end it "does not duplicate random with seed" do - expect(call(" --order random:123")).to eq(" --seed 555") + expect(call("--order", "random:123")).to eq(["--seed", "555"]) end end end diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index eeff41554..c3439f95c 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -6,27 +6,27 @@ describe ".parse_args" do it "should return the count" do args = { count: 2 } - expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "", "", ""]) + expect(ParallelTests::Tasks.parse_args(args)).to eq([2, nil, nil, nil]) end it "should default to the prefix" do args = { count: "models" } - expect(ParallelTests::Tasks.parse_args(args)).to eq([nil, "models", "", ""]) + expect(ParallelTests::Tasks.parse_args(args)).to eq([nil, "models", nil, nil]) end it "should return the count and pattern" do args = { count: 2, pattern: "models" } - expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "models", "", ""]) + expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "models", nil, nil]) end it "should return the count, pattern, and options" do args = { count: 2, pattern: "plain", options: "-p default" } - expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default", ""]) + expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default", nil]) end it "should return the count, pattern, and options" do args = { count: 2, pattern: "plain", options: "-p default --group-by steps" } - expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default --group-by steps", ""]) + expect(ParallelTests::Tasks.parse_args(args)).to eq([2, "plain", "-p default --group-by steps", nil]) end it "should return the count, pattern, test options, and pass-through options" do @@ -61,22 +61,30 @@ end it "runs command in parallel" do - expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo'$/).and_return true + expect(ParallelTests::Tasks).to receive(:system) + .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo') + .and_return true ParallelTests::Tasks.run_in_parallel("echo") end it "runs command with :count option" do - expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo' -n 123$/).and_return true + expect(ParallelTests::Tasks).to receive(:system) + .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo', '-n', 123) + .and_return true ParallelTests::Tasks.run_in_parallel("echo", count: 123) end it "runs without -n with blank :count option" do - expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo'$/).and_return true + expect(ParallelTests::Tasks).to receive(:system) + .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo') + .and_return true ParallelTests::Tasks.run_in_parallel("echo", count: "") end it "runs command with :non_parallel option" do - expect(ParallelTests::Tasks).to receive(:system).with(/#{full_path} --exec 'echo' --non-parallel$/).and_return true + expect(ParallelTests::Tasks).to receive(:system) + .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo', '--non-parallel') + .and_return true ParallelTests::Tasks.run_in_parallel("echo", non_parallel: true) end diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 800720026..0fe468b22 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -22,7 +22,7 @@ def call(*args) it "uses options" do expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _, _, _d| - expect(a).to match(/ruby -Itest .* -- -v/) + expect(a).to eq(["ruby", "-Itest", "-e", "%w[xxx].each { |f| require %{./\#{f}} }", "--", "-v"]) end call(['xxx'], 1, 22, test_options: '-v') end @@ -446,7 +446,7 @@ def run_with_file(content) it "sets process number to 2 for 1" do run_with_file("puts ENV['TEST_ENV_NUMBER']") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result[:stdout].chomp).to eq '2' expect(result[:exit_status]).to eq 0 end @@ -454,7 +454,7 @@ def run_with_file(content) it "sets process number to '' for 0" do run_with_file("puts ENV['TEST_ENV_NUMBER'].inspect") do |path| - result = call("ruby #{path}", 0, 4, {}) + result = call(["ruby", path], 0, 4, {}) expect(result[:stdout].chomp).to eq '""' expect(result[:exit_status]).to eq 0 end @@ -462,7 +462,7 @@ def run_with_file(content) it "sets process number to 1 for 0 if requested" do run_with_file("puts ENV['TEST_ENV_NUMBER']") do |path| - result = call("ruby #{path}", 0, 4, first_is_1: true) + result = call(["ruby", path], 0, 4, first_is_1: true) expect(result[:stdout].chomp).to eq '1' expect(result[:exit_status]).to eq 0 end @@ -470,7 +470,7 @@ def run_with_file(content) it 'sets PARALLEL_TEST_GROUPS so child processes know that they are being run under parallel_tests' do run_with_file("puts ENV['PARALLEL_TEST_GROUPS']") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result[:stdout].chomp).to eq('4') expect(result[:exit_status]).to eq(0) end @@ -479,7 +479,7 @@ def run_with_file(content) it "skips reads from stdin" do skip "hangs on normal ruby, works on jruby" unless RUBY_PLATFORM == "java" run_with_file("$stdin.read; puts 123") do |path| - result = call("ruby #{path}", 1, 2, {}) + result = call(["ruby", path], 1, 2, {}) expect(result).to include( { stdout: "123\n", @@ -491,7 +491,7 @@ def run_with_file(content) it "waits for process to finish" do run_with_file("sleep 0.5; puts 123; sleep 0.5; puts 345") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result[:stdout].lines.map(&:chomp)).to eq ['123', '345'] expect(result[:exit_status]).to eq 0 end @@ -505,7 +505,7 @@ def run_with_file(content) received << x.strip end - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(received).to eq("123345567") expect(result[:stdout].lines.map(&:chomp)).to eq ['123', '345567'] expect(result[:exit_status]).to eq 0 @@ -514,7 +514,7 @@ def run_with_file(content) it "works with synced stdout" do run_with_file("$stdout.sync = true; puts 123; sleep 0.1; puts 345") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result[:stdout].lines.map(&:chomp)).to eq ['123', '345'] expect(result[:exit_status]).to eq 0 end @@ -523,7 +523,7 @@ def run_with_file(content) it "does not print to stdout with :serialize_stdout" do run_with_file("puts 123") do |path| expect($stdout).not_to receive(:print) - result = call("ruby #{path}", 1, 4, serialize_stdout: true) + result = call(["ruby", path], 1, 4, serialize_stdout: true) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 0 end @@ -532,7 +532,7 @@ def run_with_file(content) it "adds test env number to stdout with :prefix_output_with_test_env_number" do run_with_file("puts 123") do |path| expect($stdout).to receive(:print).with("[TEST GROUP 2] 123#{new_line_char}") - result = call("ruby #{path}", 1, 4, prefix_output_with_test_env_number: true) + result = call(["ruby", path], 1, 4, prefix_output_with_test_env_number: true) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 0 end @@ -541,7 +541,7 @@ def run_with_file(content) it "does not add test env number to stdout without :prefix_output_with_test_env_number" do run_with_file("puts 123") do |path| expect($stdout).to receive(:print).with("123#{new_line_char}") - result = call("ruby #{path}", 1, 4, prefix_output_with_test_env_number: false) + result = call(["ruby", path], 1, 4, prefix_output_with_test_env_number: false) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 0 end @@ -549,7 +549,7 @@ def run_with_file(content) it "returns correct exit status" do run_with_file("puts 123; exit 5") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result[:stdout].chomp).to eq '123' expect(result[:exit_status]).to eq 5 end @@ -558,7 +558,7 @@ def run_with_file(content) it "prints each stream to the correct stream" do skip "open3" _out, err = run_with_file("puts 123 ; $stderr.puts 345 ; exit 5") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result).to include( stdout: "123\n", exit_status: 5 @@ -569,29 +569,29 @@ def run_with_file(content) it "uses a lower priority process when the nice option is used", unless: Gem.win_platform? do priority_cmd = "puts Process.getpriority(Process::PRIO_PROCESS, 0)" - priority_without_nice = run_with_file(priority_cmd) { |cmd| call("ruby #{cmd}", 1, 4, {}) }.first.to_i - priority_with_nice = run_with_file(priority_cmd) { |cmd| call("ruby #{cmd}", 1, 4, nice: true) }.first.to_i + priority_without_nice = run_with_file(priority_cmd) { |cmd| call(["ruby", cmd], 1, 4, {}) }.first.to_i + priority_with_nice = run_with_file(priority_cmd) { |cmd| call(["ruby", cmd], 1, 4, nice: true) }.first.to_i expect(priority_without_nice).to be < priority_with_nice end it "returns command used" do run_with_file("puts 123; exit 5") do |path| - result = call("ruby #{path}", 1, 4, {}) - expect(result).to include(command: "ruby #{path}") + result = call(["ruby", path], 1, 4, {}) + expect(result).to include(command: ["ruby", path]) end end describe "rspec seed" do it "includes seed when provided" do run_with_file("puts 'Run options: --seed 555'") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result).to include(seed: "555") end end it "seed is nil when not provided" do run_with_file("puts 555") do |path| - result = call("ruby #{path}", 1, 4, {}) + result = call(["ruby", path], 1, 4, {}) expect(result).to include(seed: nil) end end @@ -599,26 +599,26 @@ def run_with_file(content) end describe ".command_with_seed" do - def call(args) - base = "ruby -Ilib:test test/minitest/test_minitest_unit.rb" - result = ParallelTests::Test::Runner.command_with_seed("#{base}#{args}", 555) - result.sub(base, '') + def call(*args) + base = ["ruby", "-Ilib:test", "test/minitest/test_minitest_unit.rb"] + result = ParallelTests::Test::Runner.command_with_seed([*base, *args], "555") + result[base.length..-1] end it "adds the randomized seed" do - expect(call("")).to eq(" --seed 555") + expect(call).to eq(["--seed", "555"]) end it "does not duplicate seed" do - expect(call(" --seed 123")).to eq(" --seed 555") + expect(call("--seed", "123")).to eq(["--seed", "555"]) end - it "does not match strange seeds stuff" do - expect(call(" --seed 123asdasd")).to eq(" --seed 123asdasd --seed 555") + it "does not duplicate strange seeds" do + expect(call("--seed", "123asdasd")).to eq(["--seed", "555"]) end it "does not match non seeds" do - expect(call(" --seedling 123")).to eq(" --seedling 123 --seed 555") + expect(call("--seedling", "123")).to eq(["--seedling", "123", "--seed", "555"]) end end end diff --git a/spec/parallel_tests_spec.rb b/spec/parallel_tests_spec.rb index 265fda709..fe87e4358 100644 --- a/spec/parallel_tests_spec.rb +++ b/spec/parallel_tests_spec.rb @@ -185,7 +185,7 @@ def with_running_processes(count, wait = 0.2) it 'kills the running child process', unless: Gem.win_platform? do ParallelTests.with_pid_file do Thread.new do - ParallelTests::Test::Runner.execute_command('sleep 3', 1, 1, {}) + ParallelTests::Test::Runner.execute_command(['sleep', '3'], 1, 1, {}) end sleep(0.2) expect(ParallelTests.pids.count).to eq(1) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index d352d1de2..405d93d01 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -51,15 +51,18 @@ def with_files(files) end end - def should_run_with(regex) + def should_run_with(command, *args) expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _b, _c, _d| - expect(a).to match(regex) + expect(a.first(command.length)).to eq(command) + args.each do |arg| + expect(a).to include(arg) + end end end - def should_not_run_with(regex) + def should_not_run_with(arg) expect(ParallelTests::Test::Runner).to receive(:execute_command) do |a, _b, _c, _d| - expect(a).to_not match(regex) + expect(a).to_not include(arg) end end end From 5e459d8bdb51df3112ea981c3a91e43be5a843ae Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 15 May 2022 15:52:43 -0700 Subject: [PATCH 114/177] Alwasy use expanded canonical paths (#856) In the event of a error or spec failure, it is often easier to debug a problem when the path is expanded to its canonical form rather than being many dots. These paths can sometimes appear in an error. --- lib/parallel_tests/tasks.rb | 4 ++-- spec/integration_spec.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index d7948ba61..7adbd450b 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -18,7 +18,7 @@ def rake_bin end def load_lib - $LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..')) + $LOAD_PATH << File.expand_path('..', __dir__) require "parallel_tests" end @@ -234,7 +234,7 @@ def rails_61_or_greater? type = 'features' if test_framework == 'spinach' # Using the relative path to find the binary allow to run a specific version of it - executable = File.join(File.dirname(__FILE__), '..', '..', 'bin', 'parallel_test') + executable = File.expand_path('../../bin/parallel_test', __dir__) command = [*ParallelTests.with_ruby_binary(executable), type, '--type', test_framework] command += ['-n', count] if count diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index f56d9e36b..3e364281f 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -26,7 +26,7 @@ def read(file) end def bin_folder - "#{__dir__}/../bin" + File.expand_path('../bin', __dir__) end def executable(options = {}) From 0bcd8155cf92c4c2a013ea5a75b5b5bb75155b24 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 21 May 2022 08:21:30 -0700 Subject: [PATCH 115/177] Trim trailing white space throughout the project (#858) Many editors clean up trailing white space on save. By removing it all in one go, it helps keep future diffs cleaner by avoiding spurious white space changes on unrelated lines. --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- Readme.md | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index a112c405a..bd757c1c7 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -3,6 +3,6 @@ Thank you for your contribution! ## Checklist - [ ] Feature branch is up-to-date with `master` (if not - rebase it). - [ ] Added tests. -- [ ] Added an entry to the [Changelog](../blob/master/CHANGELOG.md) if the new +- [ ] Added an entry to the [Changelog](../blob/master/CHANGELOG.md) if the new code introduces user-observable changes. - [ ] Update Readme.md when cli options are changed diff --git a/Readme.md b/Readme.md index 3597a4b56..8584b4201 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,7 @@ test: ### Setup environment from scratch (create db and loads schema, useful for CI) rake parallel:setup - + ### Drop all test databases rake parallel:drop @@ -193,15 +193,15 @@ Setup for non-rails - use `ENV['TEST_ENV_NUMBER']` inside your tests to select separate db/memcache/etc. (docker compose: expose it) - Only run a subset of files / folders: - + `parallel_test test/bar test/baz/foo_text.rb` - Pass test-options and files via `--`: - + `parallel_rspec -- -t acceptance -f progress -- spec/foo_spec.rb spec/acceptance` - + - Pass in test options, by using the -o flag (wrap everything in quotes): - + `parallel_cucumber -n 2 -o '-p foo_profile --tags @only_this_tag or @only_that_tag --format summary'` Options are: From 4ffcf1b2c92e12425819cd30d6d3960a736688f6 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 21 May 2022 08:41:44 -0700 Subject: [PATCH 116/177] Simplify use of command "test" in subprocesses (#859) `|| test 1` is equivalent to `true` which always returns a exit status of 0. Using true is more explicit. See: https://linux.die.net/man/1/true `&& test 1` is equivalent to using the exit status of the preceding command, so just use it and avoid the extra syntax. `&& test` is equivalent to `false` which always returns a exit status of 1. Using false is more explicit. See: https://linux.die.net/man/1/false --- lib/parallel_tests/tasks.rb | 4 ++-- spec/parallel_tests/tasks_spec.rb | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 7adbd450b..cf67a8c8a 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -55,9 +55,9 @@ def run_in_parallel(cmd, options = {}) # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0 def suppress_output(command, ignore_regex) activate_pipefail = "set -o pipefail" - remove_ignored_lines = %{(grep -v "#{ignore_regex}" || test 1)} + remove_ignored_lines = %{(grep -v "#{ignore_regex}" || true)} - if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null && test 1") + if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null") shell_command = "#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}" %(/bin/bash -c #{Shellwords.escape(shell_command)}) else diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index c3439f95c..781379668 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -106,7 +106,7 @@ def call(command, grep) context "with pipefail supported" do before :all do - unless system("/bin/bash", "-c", "set -o pipefail 2>/dev/null && test 1") + unless system("/bin/bash", "-c", "set -o pipefail 2>/dev/null") skip "pipefail is not supported on your system" end end @@ -120,11 +120,11 @@ def call(command, grep) end it "should fail if command fails and the pattern matches" do - expect(call("echo 123 && test", "123")).to eq(["", false]) + expect(call("echo 123 && false", "123")).to eq(["", false]) end it "should fail if command fails and the pattern fails" do - expect(call("echo 124 && test", "123")).to eq(["124\n", false]) + expect(call("echo 124 && false", "123")).to eq(["124\n", false]) end end @@ -132,7 +132,7 @@ def call(command, grep) before do expect(ParallelTests::Tasks).to receive(:system).with( '/bin/bash', '-c', - 'set -o pipefail 2>/dev/null && test 1' + 'set -o pipefail 2>/dev/null' ).and_return false end @@ -141,7 +141,7 @@ def call(command, grep) end it "should not filter and fail" do - expect(call("echo 123 && test", "123")).to eq(["123\n", false]) + expect(call("echo 123 && false", "123")).to eq(["123\n", false]) end end end From 7fd751839ee588c5fc8382027a842cf49ad0605c Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sat, 21 May 2022 14:32:16 -0700 Subject: [PATCH 117/177] Change --exec argument to run subprocesses without a shell (#857) * Change --exec argument to run subprocesses without a shell Continues the work from 5ac27e9f551840722c830cf72bec64a3e2ef325d. Treat subprocess commands originating from `--exec` as an array of strings. This avoid the need to include a shell in the subprocess. Instead, the commands execute directly. As well, there is less need to parse or format shell syntax (such as string quoting). This change is a backward incompatible change. When the argument parse sees the `--exec` argument, all remaining arguments are collected as the arguments to the subprocess to execute. Previously, it only consumed one argument, allowing for additional arguments after it. This change should come with a major version bump. * Change back to making --exec accept a single string argument Will not execute with a shell, though. --- lib/parallel_tests/cli.rb | 6 ++-- lib/parallel_tests/tasks.rb | 60 +++++++++++++++++++++---------- lib/parallel_tests/test/runner.rb | 12 ++----- spec/parallel_tests/cli_spec.rb | 2 +- spec/parallel_tests/tasks_spec.rb | 31 +++++++++------- 5 files changed, 65 insertions(+), 46 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index d056307b8..4baa10adf 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -20,7 +20,7 @@ def run(argv) options[:first_is_1] ||= first_is_1? if options[:execute] - execute_shell_command_in_parallel(options[:execute], num_processes, options) + execute_command_in_parallel(options[:execute], num_processes, options) else run_tests_in_parallel(num_processes, options) end @@ -237,7 +237,7 @@ def parse_options!(argv) opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } - opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |path| options[:execute] = path } + opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |arg| options[:execute] = Shellwords.shellsplit(arg) } opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = Shellwords.shellsplit(arg) } opts.on("-t", "--type [TYPE]", "test(default) / rspec / cucumber / spinach") do |type| @runner = load_runner(type) @@ -344,7 +344,7 @@ def load_runner(type) klass_name.split('::').inject(Object) { |x, y| x.const_get(y) } end - def execute_shell_command_in_parallel(command, num_processes, options) + def execute_command_in_parallel(command, num_processes, options) runs = if options[:only_group] options[:only_group].map { |g| g - 1 } else diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index cf67a8c8a..aa0030e50 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -34,7 +34,7 @@ def run_in_parallel(cmd, options = {}) # Using the relative path to find the binary allow to run a specific version of it executable = File.expand_path('../../bin/parallel_test', __dir__) command = ParallelTests.with_ruby_binary(executable) - command += ['--exec', cmd] + command += ['--exec', Shellwords.join(cmd)] command += ['-n', options[:count]] unless options[:count].to_s.empty? command << '--non-parallel' if options[:non_parallel] @@ -51,15 +51,14 @@ def run_in_parallel(cmd, options = {}) # - pipefail makes pipe fail with exitstatus of first failed command # - pipefail is not supported in (zsh) # - defining a new rake task like silence_schema would force users to load parallel_tests in test env - # - do not use ' since run_in_parallel uses them to quote stuff # - simple system "set -o pipefail" returns nil even though set -o pipefail exists with 0 def suppress_output(command, ignore_regex) activate_pipefail = "set -o pipefail" - remove_ignored_lines = %{(grep -v "#{ignore_regex}" || true)} + remove_ignored_lines = %{(grep -v #{Shellwords.escape(ignore_regex)} || true)} if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null") - shell_command = "#{activate_pipefail} && (#{command}) | #{remove_ignored_lines}" - %(/bin/bash -c #{Shellwords.escape(shell_command)}) + shell_command = "#{activate_pipefail} && (#{Shellwords.shelljoin(command)}) | #{remove_ignored_lines}" + ['/bin/bash', '-c', shell_command] else command end @@ -134,15 +133,21 @@ def rails_61_or_greater? desc "Create test databases via db:create --> parallel:create[num_cpus]" task :create, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:create RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [ParallelTests::Tasks.rake_bin, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end desc "Drop test databases via db:drop --> parallel:drop[num_cpus]" task :drop, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:drop RAILS_ENV=#{ParallelTests::Tasks.rails_env} " \ - "DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args + [ + ParallelTests::Tasks.rake_bin, + "db:drop", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + ], + args ) end @@ -164,7 +169,7 @@ def rails_61_or_greater? # slow: dump and load in in serial args = args.to_hash.merge(non_parallel: true) # normal merge returns nil task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' - ParallelTests::Tasks.run_in_parallel("#{ParallelTests::Tasks.rake_bin} #{task_name}", args) + ParallelTests::Tasks.run_in_parallel([ParallelTests::Tasks.rake_bin, task_name], args) next end end @@ -173,23 +178,29 @@ def rails_61_or_greater? desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]" task :migrate, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:migrate RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [ParallelTests::Tasks.rake_bin, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]" task :rollback, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:rollback RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [ParallelTests::Tasks.rake_bin, "db:rollback", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end # just load the schema (good for integration server <-> no development db) desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" task :load_schema, :count do |_, args| - command = - "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ - "db:schema:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + command = [ + ParallelTests::Tasks.rake_bin, + ParallelTests::Tasks.purge_before_load, + "db:schema:load", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + ] ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end @@ -198,23 +209,34 @@ def rails_61_or_greater? desc "Load structure for test databases via db:schema:load --> parallel:load_structure[num_cpus]" task :load_structure, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} #{ParallelTests::Tasks.purge_before_load} " \ - "db:structure:load RAILS_ENV=#{ParallelTests::Tasks.rails_env} DISABLE_DATABASE_ENVIRONMENT_CHECK=1", args + [ + ParallelTests::Tasks.rake_bin, + ParallelTests::Tasks.purge_before_load, + "db:structure:load", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", + "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" + ], + args ) end desc "Load the seed data from db/seeds.rb via db:seed --> parallel:seed[num_cpus]" task :seed, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "#{ParallelTests::Tasks.rake_bin} db:seed RAILS_ENV=#{ParallelTests::Tasks.rails_env}", args + [ + ParallelTests::Tasks.rake_bin, + "db:seed", + "RAILS_ENV=#{ParallelTests::Tasks.rails_env}" + ], + args ) end desc "Launch given rake command in parallel" task :rake, :command, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - "RAILS_ENV=#{ParallelTests::Tasks.rails_env} #{ParallelTests::Tasks.rake_bin} " \ - "#{args.command}", args + [ParallelTests::Tasks.rake_bin, args.command, "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + args ) end diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index e28e4e645..47ad4ba8e 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -91,7 +91,7 @@ def execute_command(cmd, process_number, num_processes, options) ) cmd = ["nice", *cmd] if options[:nice] - puts command_string(cmd) if report_process_command?(options) && !options[:serialize_stdout] + puts Shellwords.shelljoin(cmd) if report_process_command?(options) && !options[:serialize_stdout] execute_command_and_capture_output(env, cmd, options) end @@ -111,7 +111,7 @@ def execute_command_and_capture_output(env, cmd, options) exitstatus = $?.exitstatus seed = output[/seed (\d+)/, 1] - output = "#{command_string(cmd)}\n#{output}" if report_process_command?(options) && options[:serialize_stdout] + output = "#{Shellwords.shelljoin(cmd)}\n#{output}" if report_process_command?(options) && options[:serialize_stdout] { stdout: output, exit_status: exitstatus, command: cmd, seed: seed } end @@ -282,14 +282,6 @@ def set_unknown_runtime(tests, options) def report_process_command?(options) options[:verbose] || options[:verbose_process_command] end - - def command_string(command) - if command.is_a?(String) - command - else - Shellwords.shelljoin(command) - end - end end end end diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 5404148e8..b0ebf5f2f 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -23,7 +23,7 @@ def call(*args) end it "parses execute" do - expect(call(["--exec", "echo"])).to eq(execute: "echo") + expect(call(["--exec", "echo"])).to eq(execute: ["echo"]) end it "parses excludes pattern" do diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index 781379668..f50abcd16 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -64,43 +64,48 @@ expect(ParallelTests::Tasks).to receive(:system) .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo') .and_return true - ParallelTests::Tasks.run_in_parallel("echo") + ParallelTests::Tasks.run_in_parallel(["echo"]) end it "runs command with :count option" do expect(ParallelTests::Tasks).to receive(:system) .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo', '-n', 123) .and_return true - ParallelTests::Tasks.run_in_parallel("echo", count: 123) + ParallelTests::Tasks.run_in_parallel(["echo"], count: 123) end it "runs without -n with blank :count option" do expect(ParallelTests::Tasks).to receive(:system) .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo') .and_return true - ParallelTests::Tasks.run_in_parallel("echo", count: "") + ParallelTests::Tasks.run_in_parallel(["echo"], count: "") end it "runs command with :non_parallel option" do expect(ParallelTests::Tasks).to receive(:system) .with(*ParallelTests.with_ruby_binary(full_path), '--exec', 'echo', '--non-parallel') .and_return true - ParallelTests::Tasks.run_in_parallel("echo", non_parallel: true) + ParallelTests::Tasks.run_in_parallel(["echo"], non_parallel: true) end it "runs aborts if the command fails" do expect(ParallelTests::Tasks).to receive(:system).and_return false expect(ParallelTests::Tasks).to receive(:abort).and_return false - ParallelTests::Tasks.run_in_parallel("echo") + ParallelTests::Tasks.run_in_parallel(["echo"]) end end describe ".suppress_output", unless: Gem.win_platform? do def call(command, grep) - # Explictly run as a parameter to /bin/sh to simulate how + # Explictly run as a parameter to /bin/bash to simulate how # the command will be run by parallel_test --exec # This also tests shell escaping of single quotes - result = IO.popen(['/bin/sh', '-c', ParallelTests::Tasks.suppress_output(command, grep)], &:read) + shell_command = [ + '/bin/bash', + '-c', + Shellwords.shelljoin(ParallelTests::Tasks.suppress_output(command, grep)) + ] + result = IO.popen(shell_command, &:read) [result, $?.success?] end @@ -112,19 +117,19 @@ def call(command, grep) end it "should hide offending lines" do - expect(call("echo 123", "123")).to eq(["", true]) + expect(call(["echo", "123"], "123")).to eq(["", true]) end it "should not hide other lines" do - expect(call("echo 124", "123")).to eq(["124\n", true]) + expect(call(["echo", "124"], "123")).to eq(["124\n", true]) end it "should fail if command fails and the pattern matches" do - expect(call("echo 123 && false", "123")).to eq(["", false]) + expect(call(['/bin/bash', '-c', 'echo 123 && false'], "123")).to eq(["", false]) end it "should fail if command fails and the pattern fails" do - expect(call("echo 124 && false", "123")).to eq(["124\n", false]) + expect(call(['/bin/bash', '-c', 'echo 124 && false'], "123")).to eq(["124\n", false]) end end @@ -137,11 +142,11 @@ def call(command, grep) end it "should not filter and succeed" do - expect(call("echo 123", "123")).to eq(["123\n", true]) + expect(call(["echo", "123"], "123")).to eq(["123\n", true]) end it "should not filter and fail" do - expect(call("echo 123 && false", "123")).to eq(["123\n", false]) + expect(call(['/bin/bash', '-c', 'echo 123 && false'], "123")).to eq(["123\n", false]) end end end From e006718f251f869acce899f4a08400c60223dd3b Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 22 May 2022 07:38:02 -0700 Subject: [PATCH 118/177] Remove redundant File.executable?('/bin/bash') check (#860) If /bin/bash does not exist, system will return nil. Avoid checking twice to reduce the total number of system calls. https://ruby-doc.org/core-2.5.0/Kernel.html#method-i-system > system returns true if the command gives zero exit status, false for > non zero exit status. Returns nil if command execution fails. --- lib/parallel_tests/tasks.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index aa0030e50..cf6005319 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -56,7 +56,7 @@ def suppress_output(command, ignore_regex) activate_pipefail = "set -o pipefail" remove_ignored_lines = %{(grep -v #{Shellwords.escape(ignore_regex)} || true)} - if File.executable?('/bin/bash') && system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null") + if system('/bin/bash', '-c', "#{activate_pipefail} 2>/dev/null") shell_command = "#{activate_pipefail} && (#{Shellwords.shelljoin(command)}) | #{remove_ignored_lines}" ['/bin/bash', '-c', shell_command] else From 31f45698b414bdfbbafd9d732a3d935373117535 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 May 2022 16:06:56 -0700 Subject: [PATCH 119/177] v3.9.0 --- CHANGELOG.md | 10 ++++++---- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad166fb8d..58247edb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,16 @@ ### Breaking Changes -- Changed subprocesses to execute without a shell. - ### Added -- Support Ruby 2.5 / 2.6 - ### Fixed +## 3.9.0 - 2022-05-22 + +### Added + +- Subprocesses execute without a shell. + ## 3.8.1 - 2022-03-28 ### Added diff --git a/Gemfile.lock b/Gemfile.lock index abfe24233..c69dcf11d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.8.1) + parallel_tests (3.9.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 3f43f85f3..cf5843a53 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.8.1' + VERSION = '3.9.0' end From 0ec997be81e593f42ce23047a35a26848f79d9d8 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 22 May 2022 16:09:03 -0700 Subject: [PATCH 120/177] thanks for all the cleanup! --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 8584b4201..01c90089d 100644 --- a/Readme.md +++ b/Readme.md @@ -402,6 +402,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Vikram B Kumar](https://github.com/v-kumar) - [Joshua Pinter](https://github.com/joshuapinter) - [Zach Dennis](https://github.com/zdennis) + - [Jon Dufresne](https://github.com/jdufresne) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 4b8aa8f5d327902ca1ed96d6d86012f372e2997a Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 23 May 2022 07:47:46 -0700 Subject: [PATCH 121/177] Fix `parallel:setup` task (#862) Command should be an array of strings, not a single string. Missed in 7fd751839ee588c5fc8382027a842cf49ad0605c. Fixes #861 --- CHANGELOG.md | 2 ++ lib/parallel_tests/tasks.rb | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- spec/rails_spec.rb | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58247edb6..30b2b7410 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- Fixed `NoMethodError` exception when running Rake task `parallel:setup`. + ## 3.9.0 - 2022-05-22 ### Added diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index cf6005319..5c2ae1c80 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -126,7 +126,7 @@ def rails_61_or_greater? namespace :parallel do desc "Setup test databases via db:setup --> parallel:setup[num_cpus]" task :setup, :count do |_, args| - command = "#{ParallelTests::Tasks.rake_bin} db:setup RAILS_ENV=#{ParallelTests::Tasks.rails_env}" + command = [ParallelTests::Tasks.rake_bin, "db:setup", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"] ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 2a8e4697f..ffb7d8973 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.7.3) + parallel_tests (3.9.0) parallel GEM diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index bbd764e39..f1a70629a 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -31,6 +31,7 @@ def run(command, options = {}) run ["bundle", "exec", "rake", "db:setup", "parallel:create"] # Also test the case where the DBs need to be dropped run ["bundle", "exec", "rake", "parallel:drop", "parallel:create"] + run ["bundle", "exec", "rake", "parallel:setup"] run ["bundle", "exec", "rake", "parallel:prepare"] run ["bundle", "exec", "rails", "runner", "User.create"], environment: { 'RAILS_ENV' => 'test' } # pollute the db out = run ["bundle", "exec", "rake", "parallel:prepare", "parallel:test"] From 3a273806bc206ab4a737af4a2fb41ab1caa93bbf Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 23 May 2022 07:50:41 -0700 Subject: [PATCH 122/177] v3.9.1 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c69dcf11d..524fa3053 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.9.0) + parallel_tests (3.9.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index cf5843a53..0655a22bf 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.9.0' + VERSION = '3.9.1' end From 3250d0d87adac1aebae2357f1b3eb9c0fb207808 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 23 May 2022 07:52:05 -0700 Subject: [PATCH 123/177] changelog --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30b2b7410..e0756f325 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,12 @@ - Fixed `NoMethodError` exception when running Rake task `parallel:setup`. +## 3.9.1 - 2022-05-23 + +### Fixed + +- Fixed `NoMethodError` exception when running Rake task `parallel:setup`. + ## 3.9.0 - 2022-05-22 ### Added From c1b7643f85ba9990a8edfe235930b2635dd5e3cb Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 23 May 2022 08:42:26 -0700 Subject: [PATCH 124/177] Cleanup extra CHANGELOG.md entry (#864) --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0756f325..b89078730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,6 @@ ### Fixed -- Fixed `NoMethodError` exception when running Rake task `parallel:setup`. - ## 3.9.1 - 2022-05-23 ### Fixed From fe56bf8b6bccb47a4ae4c2a465553ec8a366efa8 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 23 May 2022 09:05:01 -0700 Subject: [PATCH 125/177] Install spec/fixtures/**/Gemfile in frozen mode (#863) Through the use of `bundle install` these files change on a test run if the parallel_tests version changes. For example, right now parallel_tests is version 3.8.1 but is specified as 3.8.0 in spec/fixtures/rails70/Gemfile.lock. Running rspec results in a undesired change to this file. When submitting pull requests, it is best practice to avoid unrelated changes, so this slightly slows down a contributor's workflow. Use the frozen configuration option to ensure that these files are always up to date. If they are not, CI will fail with a useful message. See https://bundler.io/man/bundle-config.1.html > frozen (BUNDLE_FROZEN): Disallow changes to the Gemfile. When the > Gemfile is changed and the lockfile has not been updated, running > Bundler commands will be blocked. Defaults to true when --deployment > is used. --- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/rails_spec.rb | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index f5169820e..7567d8f36 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.8.0) + parallel_tests (3.9.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 1307803a7..7f20732d3 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.8.0) + parallel_tests (3.9.0) parallel GEM diff --git a/spec/rails_spec.rb b/spec/rails_spec.rb index f1a70629a..d10ab13c0 100644 --- a/spec/rails_spec.rb +++ b/spec/rails_spec.rb @@ -26,6 +26,7 @@ def run(command, options = {}) ENV.delete("RACK_ENV") run ["bundle", "config", "--local", "path", "vendor/bundle"] + run ["bundle", "config", "--local", "frozen", "true"] run ["bundle", "install"] FileUtils.rm_f(Dir['db/*.sqlite3']) run ["bundle", "exec", "rake", "db:setup", "parallel:create"] From 68b56cf90bf6217a8418b0420fba8f40273c04ad Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Mon, 23 May 2022 09:22:38 -0700 Subject: [PATCH 126/177] Always execute a Rake subtask using the same Rake executable (#865) Rather than trying to find a suitable Rake executable, assume the currently running Rake is the user's preferred executable. It will allow for the most correctness in the subprocess environment. For documentation on $0, see: https://ruby-doc.org/core-3.1.2/doc/globals_rdoc.html > Contains the name of the script being executed. --- CHANGELOG.md | 3 +++ lib/parallel_tests/tasks.rb | 28 ++++++++++------------------ 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b89078730..6c960593f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ ### Added +- Changed Rake subtasks to always use the same Rake executable as the parent + process. + ### Fixed ## 3.9.1 - 2022-05-23 diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 5c2ae1c80..52f3c8346 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -9,14 +9,6 @@ def rails_env 'test' end - def rake_bin - # Prevent 'Exec format error' Errno::ENOEXEC on Windows - return "rake" if RUBY_PLATFORM =~ /mswin|mingw|cygwin/ - binstub_path = File.join('bin', 'rake') - return binstub_path if File.exist?(binstub_path) - "rake" - end - def load_lib $LOAD_PATH << File.expand_path('..', __dir__) require "parallel_tests" @@ -126,14 +118,14 @@ def rails_61_or_greater? namespace :parallel do desc "Setup test databases via db:setup --> parallel:setup[num_cpus]" task :setup, :count do |_, args| - command = [ParallelTests::Tasks.rake_bin, "db:setup", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"] + command = [$0, "db:setup", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"] ParallelTests::Tasks.run_in_parallel(ParallelTests::Tasks.suppress_schema_load_output(command), args) end desc "Create test databases via db:create --> parallel:create[num_cpus]" task :create, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - [ParallelTests::Tasks.rake_bin, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + [$0, "db:create", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], args ) end @@ -142,7 +134,7 @@ def rails_61_or_greater? task :drop, :count do |_, args| ParallelTests::Tasks.run_in_parallel( [ - ParallelTests::Tasks.rake_bin, + $0, "db:drop", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", "DISABLE_DATABASE_ENVIRONMENT_CHECK=1" @@ -169,7 +161,7 @@ def rails_61_or_greater? # slow: dump and load in in serial args = args.to_hash.merge(non_parallel: true) # normal merge returns nil task_name = Rake::Task.task_defined?('db:test:prepare') ? 'db:test:prepare' : 'app:db:test:prepare' - ParallelTests::Tasks.run_in_parallel([ParallelTests::Tasks.rake_bin, task_name], args) + ParallelTests::Tasks.run_in_parallel([$0, task_name], args) next end end @@ -178,7 +170,7 @@ def rails_61_or_greater? desc "Update test databases via db:migrate --> parallel:migrate[num_cpus]" task :migrate, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - [ParallelTests::Tasks.rake_bin, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + [$0, "db:migrate", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], args ) end @@ -186,7 +178,7 @@ def rails_61_or_greater? desc "Rollback test databases via db:rollback --> parallel:rollback[num_cpus]" task :rollback, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - [ParallelTests::Tasks.rake_bin, "db:rollback", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + [$0, "db:rollback", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], args ) end @@ -195,7 +187,7 @@ def rails_61_or_greater? desc "Load dumped schema for test databases via db:schema:load --> parallel:load_schema[num_cpus]" task :load_schema, :count do |_, args| command = [ - ParallelTests::Tasks.rake_bin, + $0, ParallelTests::Tasks.purge_before_load, "db:schema:load", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", @@ -210,7 +202,7 @@ def rails_61_or_greater? task :load_structure, :count do |_, args| ParallelTests::Tasks.run_in_parallel( [ - ParallelTests::Tasks.rake_bin, + $0, ParallelTests::Tasks.purge_before_load, "db:structure:load", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}", @@ -224,7 +216,7 @@ def rails_61_or_greater? task :seed, :count do |_, args| ParallelTests::Tasks.run_in_parallel( [ - ParallelTests::Tasks.rake_bin, + $0, "db:seed", "RAILS_ENV=#{ParallelTests::Tasks.rails_env}" ], @@ -235,7 +227,7 @@ def rails_61_or_greater? desc "Launch given rake command in parallel" task :rake, :command, :count do |_, args| ParallelTests::Tasks.run_in_parallel( - [ParallelTests::Tasks.rake_bin, args.command, "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], + [$0, args.command, "RAILS_ENV=#{ParallelTests::Tasks.rails_env}"], args ) end From 6f1e3fdd1192a2920dc3e9e200d522f2417a7ca7 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 23 May 2022 09:26:04 -0700 Subject: [PATCH 127/177] update bumped version in all lock files --- Rakefile | 3 +++ spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Rakefile b/Rakefile index bd38572a8..d184aff78 100644 --- a/Rakefile +++ b/Rakefile @@ -3,6 +3,9 @@ require 'bundler/setup' require 'bump/tasks' require 'bundler/gem_tasks' +# update all versions so bundling does not fail on CI +Bump.replace_in_default = Dir["spec/fixtures/rails*/Gemfile.lock"] + task default: [:spec, :rubocop] task :spec do diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 7567d8f36..c236a3080 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.9.0) + parallel_tests (3.9.1) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 7f20732d3..6fa3d91ba 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.9.0) + parallel_tests (3.9.1) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index ffb7d8973..78efef851 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.9.0) + parallel_tests (3.9.1) parallel GEM From 3f265ffc94dc82f78f9954957b0b26c9d0a7989e Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 23 May 2022 09:27:35 -0700 Subject: [PATCH 128/177] v3.10.0 --- CHANGELOG.md | 8 ++++++-- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 11 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c960593f..6c8856ae8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,15 @@ ### Added +### Fixed + +## 3.10.0 - 2022-05-23 + +### Added + - Changed Rake subtasks to always use the same Rake executable as the parent process. -### Fixed - ## 3.9.1 - 2022-05-23 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index 524fa3053..32c14c692 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.9.1) + parallel_tests (3.10.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 0655a22bf..c457c4e9f 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.9.1' + VERSION = '3.10.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index c236a3080..c8b801534 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.9.1) + parallel_tests (3.10.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 6fa3d91ba..c1db4e10a 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.9.1) + parallel_tests (3.10.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 78efef851..76f8c63c6 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.9.1) + parallel_tests (3.10.0) parallel GEM From 266a76066bcb73a9f47ec50dac47b54568e3b84c Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 23 May 2022 22:47:52 -0700 Subject: [PATCH 129/177] various task fixes (#867) * fil-fast on unknown test framework * integer count fails in system * passthrough needs to split --- lib/parallel_tests/tasks.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 52f3c8346..1a82ff7c5 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -244,17 +244,17 @@ def rails_61_or_greater? 'test' => 'test', 'features' => 'cucumber', 'features-spinach' => 'spinach' - }[type] + }.fetch(type) type = 'features' if test_framework == 'spinach' # Using the relative path to find the binary allow to run a specific version of it executable = File.expand_path('../../bin/parallel_test', __dir__) command = [*ParallelTests.with_ruby_binary(executable), type, '--type', test_framework] - command += ['-n', count] if count + command += ['-n', count.to_s] if count command += ['--pattern', pattern] if pattern command += ['--test-options', options] if options - command << pass_through if pass_through + command += Shellwords.shellsplit pass_through if pass_through abort unless system(*command) # allow to chain tasks e.g. rake parallel:spec parallel:features end From d4677677639a06c5d4968870fd59cc7bc4a21f24 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 23 May 2022 22:48:05 -0700 Subject: [PATCH 130/177] v3.10.1 --- CHANGELOG.md | 6 ++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c8856ae8..5c426ef80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ ### Fixed +## 3.10.1 - 2022-05-23 + +### Fixed + +- Running rake tasks with number of processes or extra args + ## 3.10.0 - 2022-05-23 ### Added diff --git a/Gemfile.lock b/Gemfile.lock index 32c14c692..2da06ca81 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.10.0) + parallel_tests (3.10.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index c457c4e9f..40bf9a542 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.10.0' + VERSION = '3.10.1' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index c8b801534..8c3607667 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.10.0) + parallel_tests (3.10.1) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index c1db4e10a..a302933d4 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.10.0) + parallel_tests (3.10.1) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 76f8c63c6..37cf0758e 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.10.0) + parallel_tests (3.10.1) parallel GEM From b5407cba232eb7db32d01adf101f1d5223551b18 Mon Sep 17 00:00:00 2001 From: Adis Osmonov Date: Wed, 25 May 2022 16:25:30 +0100 Subject: [PATCH 131/177] Update typo (#868) --- lib/parallel_tests/cli.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 4baa10adf..3b5c6ee52 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -228,7 +228,7 @@ def parse_options!(argv) processes in a specific formation. Commas indicate specs in the same process, pipes indicate specs in a new process. Cannot use with --single, --isolate, or --isolate-n. Ex. - $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' + $ parallel_test -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' Process 1 will contain 1_spec.rb and 2_spec.rb Process 2 will contain 3_spec.rb Process 3 will contain all other specs From 2a18ba069206e705391215e2d3ab0d4093bf2c29 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Thu, 26 May 2022 20:14:14 -0700 Subject: [PATCH 132/177] add tests for newly fixed bugs --- lib/parallel_tests/tasks.rb | 42 ++++++++++++++++++------------- spec/parallel_tests/tasks_spec.rb | 25 +++++++++++++++++- 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/lib/parallel_tests/tasks.rb b/lib/parallel_tests/tasks.rb index 1a82ff7c5..efda5cd45 100644 --- a/lib/parallel_tests/tasks.rb +++ b/lib/parallel_tests/tasks.rb @@ -102,6 +102,29 @@ def schema_type_based_on_rails_version end end + def build_run_command(type, args) + count, pattern, options, pass_through = ParallelTests::Tasks.parse_args(args) + test_framework = { + 'spec' => 'rspec', + 'test' => 'test', + 'features' => 'cucumber', + 'features-spinach' => 'spinach' + }.fetch(type) + + type = 'features' if test_framework == 'spinach' + + # Using the relative path to find the binary allow to run a specific version of it + executable = File.expand_path('../../bin/parallel_test', __dir__) + executable = ParallelTests.with_ruby_binary(executable) + + command = [*executable, type, '--type', test_framework] + command += ['-n', count.to_s] if count + command += ['--pattern', pattern] if pattern + command += ['--test-options', options] if options + command += Shellwords.shellsplit pass_through if pass_through + command + end + private def rails_7_or_greater? @@ -237,24 +260,7 @@ def rails_61_or_greater? task type, [:count, :pattern, :options, :pass_through] do |_t, args| ParallelTests::Tasks.check_for_pending_migrations ParallelTests::Tasks.load_lib - - count, pattern, options, pass_through = ParallelTests::Tasks.parse_args(args) - test_framework = { - 'spec' => 'rspec', - 'test' => 'test', - 'features' => 'cucumber', - 'features-spinach' => 'spinach' - }.fetch(type) - - type = 'features' if test_framework == 'spinach' - # Using the relative path to find the binary allow to run a specific version of it - executable = File.expand_path('../../bin/parallel_test', __dir__) - - command = [*ParallelTests.with_ruby_binary(executable), type, '--type', test_framework] - command += ['-n', count.to_s] if count - command += ['--pattern', pattern] if pattern - command += ['--test-options', options] if options - command += Shellwords.shellsplit pass_through if pass_through + command = ParallelTests::Tasks.build_run_command(type, args) abort unless system(*command) # allow to chain tasks e.g. rake parallel:spec parallel:features end diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index f50abcd16..04c3d8728 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -201,7 +201,7 @@ def call(command, grep) end end - describe '.purge_before_load' do + describe ".purge_before_load" do context 'Rails < 4.2.0' do before do stub_const('Rails', double(version: '3.2.1')) @@ -230,4 +230,27 @@ def call(command, grep) end end end + + describe ".build_run_command" do + it "builds simple command" do + expect(ParallelTests::Tasks.build_run_command("test", {})).to eq [ + "#{Dir.pwd}/bin/parallel_test", "test", "--type", "test" + ] + end + + it "fails on unknown" do + expect { ParallelTests::Tasks.build_run_command("foo", {}) }.to raise_error(KeyError) + end + + it "builds with all arguments" do + command = ParallelTests::Tasks.build_run_command( + "test", + count: 1, pattern: "foo", options: "bar", pass_through: "baz baz" + ) + expect(command).to eq [ + "#{Dir.pwd}/bin/parallel_test", "test", "--type", "test", + "-n", "1", "--pattern", "foo", "--test-options", "bar", "baz", "baz" + ] + end + end end From e6e1129e58ac74b01227e5726a2ba663388224c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Quenneville?= Date: Fri, 27 May 2022 13:47:42 -0400 Subject: [PATCH 133/177] Raise custom error when runtime log is too small (#869) Currently, we raise a generic `RuntimeError` when the runtime log is too small. This can make it hard for calling code to handle the situation. The best that can be done is attempting to match on the string error message. This change introduces a custom `RuntimeLogTooSmallError` that calling code can more easily rescue. This will make it easier for builds to log when this event occurs or automatically retry with a different grouping strategy. This is a breaking change for anyone who was relying on rescuing `RuntimeError`. --- CHANGELOG.md | 3 +++ lib/parallel_tests/test/runner.rb | 4 +++- spec/parallel_tests/test/runner_spec.rb | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c426ef80..cfe1b703f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ ### Breaking Changes +- Raise a custom `RuntimeLogTooSmallError` exception when the runtime log is too + small instead of a generic `RuntimeError`. + ### Added ### Fixed diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 47ad4ba8e..ec18693ec 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -5,6 +5,8 @@ module ParallelTests module Test class Runner + RuntimeLogTooSmallError = Class.new(StandardError) + class << self # --- usually overwritten by other runners @@ -199,7 +201,7 @@ def sort_by_runtime(tests, runtimes, options = {}) allowed_missing -= 1 unless time = runtimes[test] if allowed_missing < 0 log = options[:runtime_log] || runtime_log - raise "Runtime log file '#{log}' does not contain sufficient data to sort #{tests.size} test files, please update or remove it." + raise RuntimeLogTooSmallError, "Runtime log file '#{log}' does not contain sufficient data to sort #{tests.size} test files, please update or remove it." end [test, time] end diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 0fe468b22..256c85479 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -90,7 +90,7 @@ def call(*args) it "fails when there is too little log" do File.write("tmp/parallel_runtime_test.log", "xxx:123\nyyy:123\naaa:123") - expect { call(["aaa", "bbb", "ccc"], 3, group_by: :runtime) }.to raise_error(RuntimeError) + expect { call(["aaa", "bbb", "ccc"], 3, group_by: :runtime) }.to raise_error(ParallelTests::Test::Runner::RuntimeLogTooSmallError) end it "groups a lot of missing files when allow-missing is high" do From b8fe5d06afab80d44483072446a8c630fb75fc8e Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 27 May 2022 19:48:07 +0200 Subject: [PATCH 134/177] v3.11.0 --- CHANGELOG.md | 10 +++++++--- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cfe1b703f..4816dd411 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,13 +4,17 @@ ### Breaking Changes -- Raise a custom `RuntimeLogTooSmallError` exception when the runtime log is too - small instead of a generic `RuntimeError`. - ### Added ### Fixed +## 3.11.0 - 2022-05-27 + +### Changed + +- Raise a custom `RuntimeLogTooSmallError` exception when the runtime log is too + small instead of a generic `RuntimeError`. + ## 3.10.1 - 2022-05-23 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index 2da06ca81..3c5baf9de 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.10.1) + parallel_tests (3.11.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 40bf9a542..df57b3f0b 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.10.1' + VERSION = '3.11.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 8c3607667..f59d19160 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.10.1) + parallel_tests (3.11.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index a302933d4..c62b9a875 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.10.1) + parallel_tests (3.11.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 37cf0758e..1b6a1b2f7 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.10.1) + parallel_tests (3.11.0) parallel GEM From 40573f0c76e62aa43eeb644e3272f1e3def8461c Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 31 May 2022 22:09:40 +0200 Subject: [PATCH 135/177] dry up run_tests_in_parallel --- lib/parallel_tests/cli.rb | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 3b5c6ee52..6c0e6928b 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -61,20 +61,15 @@ def run_tests_in_parallel(num_processes, options) groups = @runner.tests_in_groups(options[:files], num_processes, options) groups.reject!(&:empty?) - test_results = if options[:only_group] - groups_to_run = options[:only_group].map { |i| groups[i - 1] }.compact - report_number_of_tests(groups_to_run) unless options[:quiet] - execute_in_parallel(groups_to_run, groups_to_run.size, options) do |group| - run_tests(group, groups_to_run.index(group), 1, options) - end - else - report_number_of_tests(groups) unless options[:quiet] - - execute_in_parallel(groups, groups.size, options) do |group| - run_tests(group, groups.index(group), num_processes, options) - end + if options[:only_group] + groups = options[:only_group].map { |i| groups[i - 1] }.compact + num_processes = 1 end + report_number_of_tests(groups) unless options[:quiet] + test_results = execute_in_parallel(groups, groups.size, options) do |group| + run_tests(group, groups.index(group), num_processes, options) + end report_results(test_results, options) unless options[:quiet] end From 0ce8272d49b24a8a77ea4f2423c9bc2df6afc412 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 12 Jun 2022 06:29:59 -0700 Subject: [PATCH 136/177] Fix several typos and spelling errors (#871) Discovered using codespell: https://github.com/codespell-project/codespell --- CHANGELOG.md | 4 ++-- spec/parallel_tests/cucumber/scenarios_spec.rb | 2 +- spec/parallel_tests/gherkin/runner_behaviour.rb | 2 +- spec/parallel_tests/grouper_spec.rb | 4 ++-- spec/parallel_tests/rspec/runner_spec.rb | 4 ++-- spec/parallel_tests/tasks_spec.rb | 2 +- spec/parallel_tests/test/runner_spec.rb | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4816dd411..1216a4a4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -54,7 +54,7 @@ ### Added -- Tesed on ruby 3.0 and 3.1 +- Tested on ruby 3.0 and 3.1 ### Fixed @@ -226,7 +226,7 @@ ## 2.29.2 - 2019-08-06 ### Fixed -- Eliminate some ruby warnings relating to ambigious arguments, unused variables, a redefined method, and uninitialized instance variables ([#712](https://github.com/grosser/parallel_tests/pull/712)). +- Eliminate some ruby warnings relating to ambiguous arguments, unused variables, a redefined method, and uninitialized instance variables ([#712](https://github.com/grosser/parallel_tests/pull/712)). ## 2.29.1 - 2019-06-13 diff --git a/spec/parallel_tests/cucumber/scenarios_spec.rb b/spec/parallel_tests/cucumber/scenarios_spec.rb index 598bd7a00..4799b31c3 100644 --- a/spec/parallel_tests/cucumber/scenarios_spec.rb +++ b/spec/parallel_tests/cucumber/scenarios_spec.rb @@ -70,7 +70,7 @@ Examples: | colour | | magenta | - | fuschia | + | fuchsia | @green Examples: diff --git a/spec/parallel_tests/gherkin/runner_behaviour.rb b/spec/parallel_tests/gherkin/runner_behaviour.rb index ab9863455..31e0b98cf 100644 --- a/spec/parallel_tests/gherkin/runner_behaviour.rb +++ b/spec/parallel_tests/gherkin/runner_behaviour.rb @@ -215,7 +215,7 @@ def call(*args) ParallelTests::Gherkin::Runner.send(:find_tests, *args) end - it "doesn't find bakup files with the same name as test files" do + it "doesn't find backup files with the same name as test files" do with_files(['a/x.feature', 'a/x.feature.bak']) do |root| expect(call(["#{root}/"])).to eq( [ diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index e6982e64c..cba9de287 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -96,7 +96,7 @@ def call(num_groups, options = {}) ) end - it "specify_groups aborts when spec passed in doesnt match existing specs" do + it "specify_groups aborts when spec passed in doesn't match existing specs" do expect do call(3, specify_groups: '1|2|6') end.to raise_error( @@ -104,7 +104,7 @@ def call(num_groups, options = {}) ) end - it "specify_groups aborts when spec passed in doesnt match existing specs again" do + it "specify_groups aborts when spec passed in doesn't match existing specs again" do expect do call(3, specify_groups: '1,6|2') end.to raise_error( diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index ba354a220..23c209725 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -17,7 +17,7 @@ def call(*args) ParallelTests::RSpec::Runner.run_tests(*args) end - it "runs command using nice when specifed" do + it "runs command using nice when specified" do ParallelTests.with_pid_file do expect(ParallelTests::Test::Runner).to receive(:execute_command_and_capture_output) do |_a, b, _c| expect(b.first(2)).to eq(["nice", "rspec"]) @@ -119,7 +119,7 @@ def call(*args) ParallelTests::RSpec::Runner.send(:find_tests, *args) end - it "doesn't find bakup files with the same name as test files" do + it "doesn't find backup files with the same name as test files" do with_files(['a/x_spec.rb', 'a/x_spec.rb.bak']) do |root| expect(call(["#{root}/"])).to eq(["#{root}/a/x_spec.rb"]) end diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index 04c3d8728..2e331c358 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -97,7 +97,7 @@ describe ".suppress_output", unless: Gem.win_platform? do def call(command, grep) - # Explictly run as a parameter to /bin/bash to simulate how + # Explicitly run as a parameter to /bin/bash to simulate how # the command will be run by parallel_test --exec # This also tests shell escaping of single quotes shell_command = [ diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 256c85479..5f53da0df 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -352,7 +352,7 @@ def call(*args) end end - it "doesn't find bakup files with the same name as test files" do + it "doesn't find backup files with the same name as test files" do with_files(['a/x_test.rb', 'a/x_test.rb.bak']) do |root| expect(call(["#{root}/"])).to eq( [ From 3fc0d4afbbaa3f0d01953cd4b7b3bfaaa43f332e Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 12 Jun 2022 15:29:32 +0200 Subject: [PATCH 137/177] fix widnows bug --- spec/parallel_tests/tasks_spec.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/spec/parallel_tests/tasks_spec.rb b/spec/parallel_tests/tasks_spec.rb index 2e331c358..5afc42c21 100644 --- a/spec/parallel_tests/tasks_spec.rb +++ b/spec/parallel_tests/tasks_spec.rb @@ -233,7 +233,9 @@ def call(command, grep) describe ".build_run_command" do it "builds simple command" do - expect(ParallelTests::Tasks.build_run_command("test", {})).to eq [ + command = ParallelTests::Tasks.build_run_command("test", {}) + command.shift 2 if command.include?("--") # windows prefixes ruby executable + expect(command).to eq [ "#{Dir.pwd}/bin/parallel_test", "test", "--type", "test" ] end @@ -247,6 +249,7 @@ def call(command, grep) "test", count: 1, pattern: "foo", options: "bar", pass_through: "baz baz" ) + command.shift 2 if command.include?("--") # windows prefixes ruby executable expect(command).to eq [ "#{Dir.pwd}/bin/parallel_test", "test", "--type", "test", "-n", "1", "--pattern", "foo", "--test-options", "bar", "baz", "baz" From 818b2962278e0ee51957be11619349c05554e79f Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 26 Jun 2022 00:51:39 +0200 Subject: [PATCH 138/177] bring back env replacement behavior (#875) --- lib/parallel_tests/test/runner.rb | 6 +++++- spec/parallel_tests/cli_spec.rb | 2 +- spec/parallel_tests/test/runner_spec.rb | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index ec18693ec..836630af1 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -86,13 +86,17 @@ def tests_with_size(tests, options) end def execute_command(cmd, process_number, num_processes, options) + number = test_env_number(process_number, options).to_s env = (options[:env] || {}).merge( - "TEST_ENV_NUMBER" => test_env_number(process_number, options).to_s, + "TEST_ENV_NUMBER" => number, "PARALLEL_TEST_GROUPS" => num_processes.to_s, "PARALLEL_PID_FILE" => ParallelTests.pid_file_path ) cmd = ["nice", *cmd] if options[:nice] + # being able to run with for example `-output foo-$TEST_ENV_NUMBER` worked originally and is convenient + cmd.map! { |c| c.gsub("$TEST_ENV_NUMBER", number).gsub("${TEST_ENV_NUMBER}", number) } + puts Shellwords.shelljoin(cmd) if report_process_command?(options) && !options[:serialize_stdout] execute_command_and_capture_output(env, cmd, options) diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index b0ebf5f2f..417367fa9 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -201,7 +201,7 @@ def call(*args) end end - describe ".report_failure_rerun_commmand" do + describe ".report_failure_rerun_command" do let(:single_failed_command) { [{ exit_status: 1, command: ['foo'], seed: nil, output: 'blah' }] } it "prints nothing if there are no failures" do diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index 5f53da0df..a3f15cc38 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -581,6 +581,14 @@ def run_with_file(content) end end + it "allows using TEST_ENV_NUMBER in arguments" do + run_with_file("puts ARGV") do |path| + result = call(["ruby", path, "$TEST_ENV_NUMBER"], 1, 4, {}) + expect(result[:stdout].chomp).to eq '2' + expect(result[:exit_status]).to eq 0 + end + end + describe "rspec seed" do it "includes seed when provided" do run_with_file("puts 'Run options: --seed 555'") do |path| From 67fc2e0a4e4d5f202b43fc229d171a7b82f2920f Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 25 Jun 2022 15:51:51 -0700 Subject: [PATCH 139/177] v3.11.1 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 3c5baf9de..ba6afb2b8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.11.0) + parallel_tests (3.11.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index df57b3f0b..f02af5c67 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.11.0' + VERSION = '3.11.1' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index f59d19160..cb29c6bc0 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.11.0) + parallel_tests (3.11.1) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index c62b9a875..e083d5ac1 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.11.0) + parallel_tests (3.11.1) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 1b6a1b2f7..afb3ce90b 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.11.0) + parallel_tests (3.11.1) parallel GEM From 19b1193a1b56ea6fa885f133b4fe5f47450a8b73 Mon Sep 17 00:00:00 2001 From: Eric Kessler Date: Tue, 30 Aug 2022 01:19:54 -0400 Subject: [PATCH 140/177] Fix scenario grouping with Rules (#877) * Fix scenario grouping with Rules Updated the scenario detection logic when grouping by scenarios so that it can handle test that are nested under Rules. * Update CHANGELOG Added the scenario grouping Rule fix to the change log. * Fix Rubocop violations Fixed Rubocop violations introduced in the recent commits. * Add development dependencies to gemspec Moving some gems that are definitely needed to develop and test the gem into their proper section of the gemspec instead of them only existing in the development gemfile. * Test against various dependency versions in CI Updated the CI matrix so that the gem is tested against several different versions of its potential runtime dependencies. * Ignore some IDE files Ignoring Jetbrains IDE files. * Fix CI gemfile isues Fixing the paths to the gemspec and the Rubocop task not even having a gemfile specified. * Fix Rubocop violations Fixed Rubocop violations introduced in the recent commits. * Exclude bad CI combinations Not testing against some incompatible dependency combinations. * Fix typo in CI config Fixed a copy/paste mistake. * Fix another typo in CI config Fixed another copy/paste mistake. * Update minimum supported CukeModeler version Removing CukeModeler 2.x from CI testing because this gem requires at least CukeModeler 3.x. * Handle Cucumber Rules better Added a condition to some Rule logic so that older versions of CukeModeler that don't use Rules will still work. * Fix Rubocop violations Fixed Rubocop violations that are showing up in the newer version of Rubocop that is being used in CI. * Fix a test Fixed a test that was using an unreliable way of determining the root directory of the repository. * Remove Cucumber 3 from CI tests Not testing against Cucumber 3 because it has lots of failures and I don't know if it is even officially supported by this gem anymore. * Fix more Rubocop violations Fixed more Rubocop violations that are showing up in the newer version of Rubocop that is being used in CI. * Make a test conditional Not running a test for versions of dependencies for which it is not applicable. * Re-lock dependencies Locking down Cucumber and CukeModeler to their previous version limits because there are lots of test failures in CI for versions that I don't know if this gem even supports. --- .github/workflows/test.yml | 20 ++++++-- .gitignore | 1 + CHANGELOG.md | 2 + Gemfile | 5 -- Gemfile.lock | 22 ++++---- Rakefile | 2 +- ci_gemfiles/cucumber_4.gemfile | 11 ++++ ci_gemfiles/cuke_modeler_3.gemfile | 11 ++++ ci_gemfiles/cuke_modeler_3_minimum.gemfile | 11 ++++ lib/parallel_tests.rb | 6 +-- lib/parallel_tests/cli.rb | 2 +- lib/parallel_tests/cucumber/scenarios.rb | 4 +- lib/parallel_tests/test/runner.rb | 2 +- parallel_tests.gemspec | 7 +++ spec/fixtures/rails70/bin/bundle | 4 +- .../parallel_tests/cucumber/scenarios_spec.rb | 50 +++++++++++++++++++ .../test/runtime_logger_spec.rb | 8 +-- 17 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 ci_gemfiles/cucumber_4.gemfile create mode 100644 ci_gemfiles/cuke_modeler_3.gemfile create mode 100644 ci_gemfiles/cuke_modeler_3_minimum.gemfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 37487669d..78498f649 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,11 +12,25 @@ jobs: matrix: ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', head, jruby-head] os: [ubuntu-latest, windows-latest] + gemfile: [cucumber_4, cuke_modeler_3_minimum, cuke_modeler_3] task: [spec] include: - - ruby: '2.5' # lowest supported version - os: ubuntu-latest - task: rubocop + - ruby: '2.5' # lowest supported version + os: ubuntu-latest + gemfile: cuke_modeler_3 # Any one of the gemfiles should be fine + task: rubocop + exclude: + # CukeModeler 3.x does not support Ruby 3 until CM 3.6 + - gemfile: cuke_modeler_3_minimum + ruby: jruby-head + - gemfile: cuke_modeler_3_minimum + ruby: head + - gemfile: cuke_modeler_3_minimum + ruby: '3.1' + - gemfile: cuke_modeler_3_minimum + ruby: '3.0' + env: # $BUNDLE_GEMFILE must be set at the job level, so that it is set for all steps + BUNDLE_GEMFILE: ci_gemfiles/${{ matrix.gemfile }}.gemfile steps: - uses: actions/checkout@master - uses: ruby/setup-ruby@v1 diff --git a/.gitignore b/.gitignore index b63e5089b..0e163352f 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ tmp .bundle **/vendor/bundle +/.idea diff --git a/CHANGELOG.md b/CHANGELOG.md index 1216a4a4f..733956057 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- Grouping by scenarios now works for tests that are nested under Rules. + ## 3.11.0 - 2022-05-27 ### Changed diff --git a/Gemfile b/Gemfile index 9f3d04f44..df643bd9c 100644 --- a/Gemfile +++ b/Gemfile @@ -5,9 +5,4 @@ gemspec gem 'bump' gem 'test-unit' gem 'minitest', '~> 5.5.0' -gem 'rspec', '~> 3.3' -gem 'cucumber', "~> 4.0" -gem 'cuke_modeler', '~> 3.0' gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 -gem 'rake' -gem 'rubocop' diff --git a/Gemfile.lock b/Gemfile.lock index ba6afb2b8..e61c4be69 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -62,14 +62,16 @@ GEM cucumber-gherkin (< 23.0) diff-lcs (1.3) ffi (1.15.5) + ffi (1.15.5-x64-mingw32) gherkin-ruby (0.3.2) i18n (1.10.0) concurrent-ruby (~> 1.0) + json (2.6.2) middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) parallel (1.22.1) - parser (3.1.1.0) + parser (3.1.2.1) ast (~> 2.4.1) power_assert (2.0.1) protobuf-cucumber (3.10.8) @@ -79,7 +81,7 @@ GEM thread_safe rainbow (3.1.1) rake (13.0.6) - regexp_parser (2.2.1) + regexp_parser (2.5.0) rexml (3.2.5) rspec (3.11.0) rspec-core (~> 3.11.0) @@ -94,16 +96,17 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.11.0) rspec-support (3.11.0) - rubocop (1.26.1) + rubocop (1.35.1) + json (~> 2.3) parallel (~> 1.10) - parser (>= 3.1.0.0) + parser (>= 3.1.2.1) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) - rexml - rubocop-ast (>= 1.16.0, < 2.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.20.1, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.16.0) + rubocop-ast (1.21.0) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) sys-uname (1.2.2) @@ -114,11 +117,12 @@ GEM thread_safe (0.3.6) tzinfo (2.0.4) concurrent-ruby (~> 1.0) - unicode-display_width (2.1.0) + unicode-display_width (2.2.0) zeitwerk (2.5.4) PLATFORMS ruby + x64-mingw32 DEPENDENCIES bump @@ -133,4 +137,4 @@ DEPENDENCIES test-unit BUNDLED WITH - 2.3.7 + 2.3.6 diff --git a/Rakefile b/Rakefile index d184aff78..1409b9f10 100644 --- a/Rakefile +++ b/Rakefile @@ -19,7 +19,7 @@ end desc "bundle all gemfiles [EXTRA=]" task :bundle_all do - extra = ENV["EXTRA"] || "install" + extra = ENV.fetch("EXTRA", nil) || "install" gemfiles = (["Gemfile"] + Dir["spec/fixtures/rails*/Gemfile"]) raise if gemfiles.size < 3 diff --git a/ci_gemfiles/cucumber_4.gemfile b/ci_gemfiles/cucumber_4.gemfile new file mode 100644 index 000000000..fe582868a --- /dev/null +++ b/ci_gemfiles/cucumber_4.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true +source 'https://rubygems.org' +gemspec path: "../" + +gem 'bump' +gem 'test-unit' +gem 'minitest', '~> 5.5.0' +gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 + +# The version of Cucumber being tested +gem 'cucumber', '~> 4.0' diff --git a/ci_gemfiles/cuke_modeler_3.gemfile b/ci_gemfiles/cuke_modeler_3.gemfile new file mode 100644 index 000000000..6b8175385 --- /dev/null +++ b/ci_gemfiles/cuke_modeler_3.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true +source 'https://rubygems.org' +gemspec path: "../" + +gem 'bump' +gem 'test-unit' +gem 'minitest', '~> 5.5.0' +gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 + +# The version of CukeModeler being tested +gem 'cuke_modeler', '~> 3.0' diff --git a/ci_gemfiles/cuke_modeler_3_minimum.gemfile b/ci_gemfiles/cuke_modeler_3_minimum.gemfile new file mode 100644 index 000000000..294409767 --- /dev/null +++ b/ci_gemfiles/cuke_modeler_3_minimum.gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true +source 'https://rubygems.org' +gemspec path: "../" + +gem 'bump' +gem 'test-unit' +gem 'minitest', '~> 5.5.0' +gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 + +# The version of CukeModeler being tested +gem 'cuke_modeler', '3.0.0' diff --git a/lib/parallel_tests.rb b/lib/parallel_tests.rb index 356ba7eff..b96162be3 100644 --- a/lib/parallel_tests.rb +++ b/lib/parallel_tests.rb @@ -16,7 +16,7 @@ class << self def determine_number_of_processes(count) [ count, - ENV["PARALLEL_TEST_PROCESSORS"], + ENV.fetch("PARALLEL_TEST_PROCESSORS", nil), Parallel.processor_count ].detect { |c| !c.to_s.strip.empty? }.to_i end @@ -68,8 +68,8 @@ def first_process? end def last_process? - current_process_number = ENV['TEST_ENV_NUMBER'] - total_processes = ENV['PARALLEL_TEST_GROUPS'] + current_process_number = ENV.fetch('TEST_ENV_NUMBER', nil) + total_processes = ENV.fetch('PARALLEL_TEST_GROUPS', nil) return true if current_process_number.nil? && total_processes.nil? current_process_number = '1' if current_process_number.nil? current_process_number == total_processes diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 6c0e6928b..96daa3236 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -383,7 +383,7 @@ def use_colors? end def first_is_1? - val = ENV["PARALLEL_TEST_FIRST_IS_1"] + val = ENV.fetch("PARALLEL_TEST_FIRST_IS_1", nil) ['1', 'true'].include?(val) end diff --git a/lib/parallel_tests/cucumber/scenarios.rb b/lib/parallel_tests/cucumber/scenarios.rb index 15852cdcd..6c95998fe 100644 --- a/lib/parallel_tests/cucumber/scenarios.rb +++ b/lib/parallel_tests/cucumber/scenarios.rb @@ -52,7 +52,9 @@ def split_into_scenarios(files, tags = '') feature_tags = feature.tags.map(&:name) # We loop on each children of the feature - feature.tests.each do |test| + test_models = feature.tests + test_models += feature.rules.map(&:tests).flatten if feature.respond_to?(:rules) + test_models.each do |test| # It's a scenario, we add it to the scenario_line_logger scenario_line_logger.visit_feature_element(document.path, test, feature_tags, line_numbers: test_lines) end diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 836630af1..46e8b62da 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -154,7 +154,7 @@ def command_with_seed(cmd, seed) def executable if ENV.include?('PARALLEL_TESTS_EXECUTABLE') - [ENV['PARALLEL_TESTS_EXECUTABLE']] + [ENV.fetch('PARALLEL_TESTS_EXECUTABLE')] else determine_executable end diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index b6d5f3f9d..45093e0b6 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,5 +17,12 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" + + s.add_development_dependency 'cucumber', '~> 4.0' + s.add_development_dependency 'cuke_modeler', '~> 3.0' + s.add_development_dependency "rake" + s.add_development_dependency 'rspec', '~> 3.3' + s.add_development_dependency "rubocop" + s.required_ruby_version = '>= 2.5.0' end diff --git a/spec/fixtures/rails70/bin/bundle b/spec/fixtures/rails70/bin/bundle index 25dfd64d8..650643e31 100755 --- a/spec/fixtures/rails70/bin/bundle +++ b/spec/fixtures/rails70/bin/bundle @@ -18,7 +18,7 @@ m = Module.new do end def env_var_version - ENV["BUNDLER_VERSION"] + ENV.fetch("BUNDLER_VERSION", nil) end def cli_arg_version @@ -38,7 +38,7 @@ m = Module.new do end def gemfile - gemfile = ENV["BUNDLE_GEMFILE"] + gemfile = ENV.fetch("BUNDLE_GEMFILE", nil) return gemfile if gemfile && !gemfile.empty? File.expand_path('../Gemfile', __dir__) diff --git a/spec/parallel_tests/cucumber/scenarios_spec.rb b/spec/parallel_tests/cucumber/scenarios_spec.rb index 4799b31c3..88bd42a4a 100644 --- a/spec/parallel_tests/cucumber/scenarios_spec.rb +++ b/spec/parallel_tests/cucumber/scenarios_spec.rb @@ -232,4 +232,54 @@ expect(scenarios.length).to eq 1 end end + + cuke_modeler_version = Gem.loaded_specs['cuke_modeler'].version.version + major = cuke_modeler_version.match(/^(\d+)\./)[1].to_i + minor = cuke_modeler_version.match(/^\d+\.(\d+)\./)[1].to_i + + # CukeModeler doesn't support Rule models until 3.2.0 + context 'with Rules', if: (major > 3) || (minor >= 2) do + let(:feature_file) do + Tempfile.new('grouper.feature').tap do |feature| + feature.write <<-EOS + Feature: Grouping by scenario + + Scenario: First + Given I do nothing + + Scenario Outline: Second + Given I don't do anything + Examples: + | param | + | value 1 | + | value 2 | + + Rule: + Scenario: Third + Given I don't do anything + + Rule: + Scenario Outline: Fourth + Given I don't do anything + Examples: + | param | + | value 1 | + | value 2 | + EOS + feature.rewind + end + end + + it 'returns all the scenarios' do + scenarios = ParallelTests::Cucumber::Scenarios.all([feature_file.path]) + expect(scenarios).to match_array [ + "#{feature_file.path}:3", + "#{feature_file.path}:10", + "#{feature_file.path}:11", + "#{feature_file.path}:14", + "#{feature_file.path}:22", + "#{feature_file.path}:23" + ] + end + end end diff --git a/spec/parallel_tests/test/runtime_logger_spec.rb b/spec/parallel_tests/test/runtime_logger_spec.rb index f609fdd53..0e038c0c6 100644 --- a/spec/parallel_tests/test/runtime_logger_spec.rb +++ b/spec/parallel_tests/test/runtime_logger_spec.rb @@ -7,12 +7,14 @@ def run(command) raise "FAILED: #{result}" unless $?.success? end - def run_tests - run ["ruby", "#{Bundler.root}/bin/parallel_test", "test", "-n", "2"] + def run_tests(repo_root_dir) + run ["ruby", "#{repo_root_dir}/bin/parallel_test", "test", "-n", "2"] end it "writes a correct log on minitest-5" do skip if RUBY_PLATFORM == "java" # just too slow ... + repo_root = Dir.pwd + use_temporary_directory do # setup simple structure FileUtils.mkdir "test" @@ -37,7 +39,7 @@ def test_foo RUBY end - run_tests + run_tests(repo_root) # log looking good ? lines = File.read("tmp/parallel_runtime_test.log").split("\n").sort.map { |x| x.sub(/\d$/, "") } From 03c4d5ff231da9b865b8d58077b4771631b9d5a7 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 29 Aug 2022 22:47:36 -0700 Subject: [PATCH 141/177] thx for the fix --- Readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Readme.md b/Readme.md index 01c90089d..555e43d3f 100644 --- a/Readme.md +++ b/Readme.md @@ -403,6 +403,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Joshua Pinter](https://github.com/joshuapinter) - [Zach Dennis](https://github.com/zdennis) - [Jon Dufresne](https://github.com/jdufresne) + - [Eric Kessler](https://github.com/enkessler) [Michael Grosser](http://grosser.it)
michael@grosser.it
From d51c6d1fbf1aa83e6be1c812ad177e5370f60d1a Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 30 Aug 2022 16:38:24 +0200 Subject: [PATCH 142/177] remove extra cuke modeler complexity (#878) --- .github/workflows/test.yml | 14 -------------- .rubocop.yml | 4 ++++ Gemfile | 6 ++++++ Gemfile.lock | 19 +++++++++---------- Rakefile | 2 +- ci_gemfiles/cucumber_4.gemfile | 11 ----------- ci_gemfiles/cuke_modeler_3.gemfile | 11 ----------- ci_gemfiles/cuke_modeler_3_minimum.gemfile | 11 ----------- lib/parallel_tests.rb | 6 +++--- lib/parallel_tests/cli.rb | 4 ++-- lib/parallel_tests/cucumber/scenarios.rb | 2 +- lib/parallel_tests/test/runner.rb | 4 ++-- parallel_tests.gemspec | 7 ------- spec/fixtures/rails70/bin/bundle | 4 ++-- .../parallel_tests/cucumber/scenarios_spec.rb | 7 +------ 15 files changed, 31 insertions(+), 81 deletions(-) delete mode 100644 ci_gemfiles/cucumber_4.gemfile delete mode 100644 ci_gemfiles/cuke_modeler_3.gemfile delete mode 100644 ci_gemfiles/cuke_modeler_3_minimum.gemfile diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 78498f649..9ebb95ede 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -12,25 +12,11 @@ jobs: matrix: ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', head, jruby-head] os: [ubuntu-latest, windows-latest] - gemfile: [cucumber_4, cuke_modeler_3_minimum, cuke_modeler_3] task: [spec] include: - ruby: '2.5' # lowest supported version os: ubuntu-latest - gemfile: cuke_modeler_3 # Any one of the gemfiles should be fine task: rubocop - exclude: - # CukeModeler 3.x does not support Ruby 3 until CM 3.6 - - gemfile: cuke_modeler_3_minimum - ruby: jruby-head - - gemfile: cuke_modeler_3_minimum - ruby: head - - gemfile: cuke_modeler_3_minimum - ruby: '3.1' - - gemfile: cuke_modeler_3_minimum - ruby: '3.0' - env: # $BUNDLE_GEMFILE must be set at the job level, so that it is set for all steps - BUNDLE_GEMFILE: ci_gemfiles/${{ matrix.gemfile }}.gemfile steps: - uses: actions/checkout@master - uses: ruby/setup-ruby@v1 diff --git a/.rubocop.yml b/.rubocop.yml index 67bb29d84..7c49c081f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -128,3 +128,7 @@ Style/CaseEquality: Lint/EmptyClass: Enabled: false + +# ENV.fetch('FOO', nil) is the same as ENV['FOO'] +Style/FetchEnvVar: + Enabled: false diff --git a/Gemfile b/Gemfile index df643bd9c..5392e329c 100644 --- a/Gemfile +++ b/Gemfile @@ -5,4 +5,10 @@ gemspec gem 'bump' gem 'test-unit' gem 'minitest', '~> 5.5.0' +gem 'rspec', '~> 3.3' +gem 'cucumber', "~> 4.0" +gem 'cuke_modeler', '~> 3.6' gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 +gem 'rake' +gem 'rubocop', '~> 1.28.0' # lock minor so we do not get accidental violations, also need to drop ruby 2.5 support to upgrade further +gem 'rubocop-ast', '~> 1.17.0' # also need to drop ruby 2.5 support to remove this line diff --git a/Gemfile.lock b/Gemfile.lock index e61c4be69..cf6b17a03 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -66,7 +66,6 @@ GEM gherkin-ruby (0.3.2) i18n (1.10.0) concurrent-ruby (~> 1.0) - json (2.6.2) middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) @@ -96,17 +95,16 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.11.0) rspec-support (3.11.0) - rubocop (1.35.1) - json (~> 2.3) + rubocop (1.28.2) parallel (~> 1.10) - parser (>= 3.1.2.1) + parser (>= 3.1.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.20.1, < 2.0) + rexml + rubocop-ast (>= 1.17.0, < 2.0) ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.21.0) + rubocop-ast (1.17.0) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) sys-uname (1.2.2) @@ -127,14 +125,15 @@ PLATFORMS DEPENDENCIES bump cucumber (~> 4.0) - cuke_modeler (~> 3.0) + cuke_modeler (~> 3.6) minitest (~> 5.5.0) parallel_tests! rake rspec (~> 3.3) - rubocop + rubocop (~> 1.28.0) + rubocop-ast (~> 1.17.0) spinach! test-unit BUNDLED WITH - 2.3.6 + 2.3.7 diff --git a/Rakefile b/Rakefile index 1409b9f10..d184aff78 100644 --- a/Rakefile +++ b/Rakefile @@ -19,7 +19,7 @@ end desc "bundle all gemfiles [EXTRA=]" task :bundle_all do - extra = ENV.fetch("EXTRA", nil) || "install" + extra = ENV["EXTRA"] || "install" gemfiles = (["Gemfile"] + Dir["spec/fixtures/rails*/Gemfile"]) raise if gemfiles.size < 3 diff --git a/ci_gemfiles/cucumber_4.gemfile b/ci_gemfiles/cucumber_4.gemfile deleted file mode 100644 index fe582868a..000000000 --- a/ci_gemfiles/cucumber_4.gemfile +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true -source 'https://rubygems.org' -gemspec path: "../" - -gem 'bump' -gem 'test-unit' -gem 'minitest', '~> 5.5.0' -gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 - -# The version of Cucumber being tested -gem 'cucumber', '~> 4.0' diff --git a/ci_gemfiles/cuke_modeler_3.gemfile b/ci_gemfiles/cuke_modeler_3.gemfile deleted file mode 100644 index 6b8175385..000000000 --- a/ci_gemfiles/cuke_modeler_3.gemfile +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true -source 'https://rubygems.org' -gemspec path: "../" - -gem 'bump' -gem 'test-unit' -gem 'minitest', '~> 5.5.0' -gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 - -# The version of CukeModeler being tested -gem 'cuke_modeler', '~> 3.0' diff --git a/ci_gemfiles/cuke_modeler_3_minimum.gemfile b/ci_gemfiles/cuke_modeler_3_minimum.gemfile deleted file mode 100644 index 294409767..000000000 --- a/ci_gemfiles/cuke_modeler_3_minimum.gemfile +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true -source 'https://rubygems.org' -gemspec path: "../" - -gem 'bump' -gem 'test-unit' -gem 'minitest', '~> 5.5.0' -gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 - -# The version of CukeModeler being tested -gem 'cuke_modeler', '3.0.0' diff --git a/lib/parallel_tests.rb b/lib/parallel_tests.rb index b96162be3..356ba7eff 100644 --- a/lib/parallel_tests.rb +++ b/lib/parallel_tests.rb @@ -16,7 +16,7 @@ class << self def determine_number_of_processes(count) [ count, - ENV.fetch("PARALLEL_TEST_PROCESSORS", nil), + ENV["PARALLEL_TEST_PROCESSORS"], Parallel.processor_count ].detect { |c| !c.to_s.strip.empty? }.to_i end @@ -68,8 +68,8 @@ def first_process? end def last_process? - current_process_number = ENV.fetch('TEST_ENV_NUMBER', nil) - total_processes = ENV.fetch('PARALLEL_TEST_GROUPS', nil) + current_process_number = ENV['TEST_ENV_NUMBER'] + total_processes = ENV['PARALLEL_TEST_GROUPS'] return true if current_process_number.nil? && total_processes.nil? current_process_number = '1' if current_process_number.nil? current_process_number == total_processes diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 96daa3236..5c3e18645 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -383,7 +383,7 @@ def use_colors? end def first_is_1? - val = ENV.fetch("PARALLEL_TEST_FIRST_IS_1", nil) + val = ENV["PARALLEL_TEST_FIRST_IS_1"] ['1', 'true'].include?(val) end @@ -391,7 +391,7 @@ def first_is_1? def simulate_output_for_ci(simulate) if simulate progress_indicator = Thread.new do - interval = Float(ENV.fetch('PARALLEL_TEST_HEARTBEAT_INTERVAL', 60)) + interval = Float(ENV['PARALLEL_TEST_HEARTBEAT_INTERVAL'] || 60) loop do sleep interval print '.' diff --git a/lib/parallel_tests/cucumber/scenarios.rb b/lib/parallel_tests/cucumber/scenarios.rb index 6c95998fe..7f9b374e3 100644 --- a/lib/parallel_tests/cucumber/scenarios.rb +++ b/lib/parallel_tests/cucumber/scenarios.rb @@ -53,7 +53,7 @@ def split_into_scenarios(files, tags = '') # We loop on each children of the feature test_models = feature.tests - test_models += feature.rules.map(&:tests).flatten if feature.respond_to?(:rules) + test_models += feature.rules.flat_map(&:tests) if feature.respond_to?(:rules) # cuke_modeler >= 3.2 supports rules test_models.each do |test| # It's a scenario, we add it to the scenario_line_logger scenario_line_logger.visit_feature_element(document.path, test, feature_tags, line_numbers: test_lines) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 46e8b62da..317dcac2b 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -153,8 +153,8 @@ def command_with_seed(cmd, seed) protected def executable - if ENV.include?('PARALLEL_TESTS_EXECUTABLE') - [ENV.fetch('PARALLEL_TESTS_EXECUTABLE')] + if (executable = ENV['PARALLEL_TESTS_EXECUTABLE']) + [executable] else determine_executable end diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 45093e0b6..b6d5f3f9d 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,12 +17,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - - s.add_development_dependency 'cucumber', '~> 4.0' - s.add_development_dependency 'cuke_modeler', '~> 3.0' - s.add_development_dependency "rake" - s.add_development_dependency 'rspec', '~> 3.3' - s.add_development_dependency "rubocop" - s.required_ruby_version = '>= 2.5.0' end diff --git a/spec/fixtures/rails70/bin/bundle b/spec/fixtures/rails70/bin/bundle index 650643e31..25dfd64d8 100755 --- a/spec/fixtures/rails70/bin/bundle +++ b/spec/fixtures/rails70/bin/bundle @@ -18,7 +18,7 @@ m = Module.new do end def env_var_version - ENV.fetch("BUNDLER_VERSION", nil) + ENV["BUNDLER_VERSION"] end def cli_arg_version @@ -38,7 +38,7 @@ m = Module.new do end def gemfile - gemfile = ENV.fetch("BUNDLE_GEMFILE", nil) + gemfile = ENV["BUNDLE_GEMFILE"] return gemfile if gemfile && !gemfile.empty? File.expand_path('../Gemfile', __dir__) diff --git a/spec/parallel_tests/cucumber/scenarios_spec.rb b/spec/parallel_tests/cucumber/scenarios_spec.rb index 88bd42a4a..b48b20595 100644 --- a/spec/parallel_tests/cucumber/scenarios_spec.rb +++ b/spec/parallel_tests/cucumber/scenarios_spec.rb @@ -233,12 +233,7 @@ end end - cuke_modeler_version = Gem.loaded_specs['cuke_modeler'].version.version - major = cuke_modeler_version.match(/^(\d+)\./)[1].to_i - minor = cuke_modeler_version.match(/^\d+\.(\d+)\./)[1].to_i - - # CukeModeler doesn't support Rule models until 3.2.0 - context 'with Rules', if: (major > 3) || (minor >= 2) do + context 'with Rules' do # cuke_modeler >=3.2 let(:feature_file) do Tempfile.new('grouper.feature').tap do |feature| feature.write <<-EOS From 4ed308a84f9e8628537c263d7d972991258af263 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 30 Aug 2022 07:38:39 -0700 Subject: [PATCH 143/177] v3.12.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index cf6b17a03..e2920ab60 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.11.1) + parallel_tests (3.12.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index f02af5c67..2a0c6de2e 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.11.1' + VERSION = '3.12.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index cb29c6bc0..4f60b3c60 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.11.1) + parallel_tests (3.12.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index e083d5ac1..6f4a6854c 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.11.1) + parallel_tests (3.12.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index afb3ce90b..be66e2814 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.11.1) + parallel_tests (3.12.0) parallel GEM From c27f4c187228a0f5aa0d9466ff17aa931a43e6a3 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 30 Aug 2022 07:41:44 -0700 Subject: [PATCH 144/177] changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 733956057..461de3c28 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ ### Fixed +## v3.12.0 - 2022-08-30 + +### Fixed + - Grouping by scenarios now works for tests that are nested under Rules. ## 3.11.0 - 2022-05-27 From e956ebff8d157ced9bc775a27cca36d8ec2f4ef5 Mon Sep 17 00:00:00 2001 From: Jason Ormand Date: Mon, 12 Sep 2022 17:13:20 -0600 Subject: [PATCH 145/177] Silence undesirable output (#880) --- lib/parallel_tests/test/runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 317dcac2b..d61bec444 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -73,7 +73,7 @@ def tests_with_size(tests, options) [] end if runtimes.size * 1.5 > tests.size - puts "Using recorded test runtime" + puts "Using recorded test runtime" unless options[:quiet] sort_by_runtime(tests, runtimes) else sort_by_filesize(tests) From 6059df4c320e5bea9f3c640c1d884d319947b2c8 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 12 Sep 2022 16:13:43 -0700 Subject: [PATCH 146/177] v3.12.1 --- CHANGELOG.md | 6 ++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 461de3c28..fb047fd95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ ### Fixed +## v3.12.1 - 2022-09-12 + +### Fixed + +- `--quiet` no longer prints 'Using recorded test runtime' + ## v3.12.0 - 2022-08-30 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index e2920ab60..504c7efad 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.12.0) + parallel_tests (3.12.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 2a0c6de2e..b999245cd 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.12.0' + VERSION = '3.12.1' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 4f60b3c60..7609579d5 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.12.0) + parallel_tests (3.12.1) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 6f4a6854c..7bafc6bc1 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.12.0) + parallel_tests (3.12.1) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index be66e2814..df64aa316 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.12.0) + parallel_tests (3.12.1) parallel GEM From 6926aa0503947697435cac65a995891a4cf0d111 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 24 Sep 2022 07:12:42 +0200 Subject: [PATCH 147/177] drop ruby 2.5 (#881) --- .github/workflows/test.yml | 4 ++-- .rubocop.yml | 2 +- lib/parallel_tests/cli.rb | 4 ++-- lib/parallel_tests/cucumber/scenario_line_logger.rb | 2 +- lib/parallel_tests/gherkin/runner.rb | 2 +- lib/parallel_tests/grouper.rb | 2 +- parallel_tests.gemspec | 2 +- spec/parallel_tests/rspec/runner_spec.rb | 2 +- spec/parallel_tests/test/runner_spec.rb | 2 +- spec/spec_helper.rb | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 9ebb95ede..acf5ba58c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,11 +10,11 @@ jobs: strategy: fail-fast: false # run all tests so we see which gem/ruby combinations break matrix: - ruby: ['2.5', '2.6', '2.7', '3.0', '3.1', head, jruby-head] + ruby: ['2.6', '2.7', '3.0', '3.1', head, jruby-head] os: [ubuntu-latest, windows-latest] task: [spec] include: - - ruby: '2.5' # lowest supported version + - ruby: '2.6' # lowest supported version, same as gemspec and .rubocop.yml os: ubuntu-latest task: rubocop steps: diff --git a/.rubocop.yml b/.rubocop.yml index 7c49c081f..d69035e3f 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,6 @@ AllCops: NewCops: enable - TargetRubyVersion: 2.5 + TargetRubyVersion: 2.6 SuggestExtensions: false Exclude: - '**/vendor/bundle/**/*' diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 5c3e18645..8c3872c44 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -316,12 +316,12 @@ def parse_options!(argv) def extract_file_paths(argv) dash_index = argv.rindex("--") file_args_at = (dash_index || -1) + 1 - [argv[file_args_at..-1], argv[0...(dash_index || 0)]] + [argv[file_args_at..], argv[0...(dash_index || 0)]] end def extract_test_options(argv) dash_index = argv.index("--") || -1 - argv[dash_index + 1..-1] + argv[dash_index + 1..] end def append_test_options(options, argv) diff --git a/lib/parallel_tests/cucumber/scenario_line_logger.rb b/lib/parallel_tests/cucumber/scenario_line_logger.rb index 74a99b52a..bd47b7ada 100644 --- a/lib/parallel_tests/cucumber/scenario_line_logger.rb +++ b/lib/parallel_tests/cucumber/scenario_line_logger.rb @@ -27,7 +27,7 @@ def visit_feature_element(uri, feature_element, feature_tags, line_numbers: []) example_tags = example.tags.map(&:name) example_tags = scenario_tags + example_tags next unless matches_tags?(example_tags) - example.rows[1..-1].each do |row| + example.rows[1..].each do |row| test_line = row.source_line next if line_numbers.any? && !line_numbers.include?(test_line) diff --git a/lib/parallel_tests/gherkin/runner.rb b/lib/parallel_tests/gherkin/runner.rb index b41463a36..a3508fba1 100644 --- a/lib/parallel_tests/gherkin/runner.rb +++ b/lib/parallel_tests/gherkin/runner.rb @@ -57,7 +57,7 @@ def summarize_results(results) plural = "s" if (word == group) && (number != 1) "#{number} #{word}#{plural}" end - "#{sums[0]} (#{sums[1..-1].join(", ")})" + "#{sums[0]} (#{sums[1..].join(", ")})" end.compact.join("\n") end diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index 959339f16..fd2229d97 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -38,7 +38,7 @@ def in_even_groups_by_size(items, num_groups, options = {}) # add all files that should run in a multiple isolated processes to their own groups group_features_by_size(items_to_group(single_items), groups[0..(isolate_count - 1)]) # group the non-isolated by size - group_features_by_size(items_to_group(items), groups[isolate_count..-1]) + group_features_by_size(items_to_group(items), groups[isolate_count..]) else # add all files that should run in a single non-isolated process to first group single_items.each { |item, size| add_to_group(groups.first, item, size) } diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index b6d5f3f9d..17ac64264 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,5 +17,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.5.0' + s.required_ruby_version = '>= 2.6.0' end diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index 23c209725..bec9f6957 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -180,7 +180,7 @@ def call(*args) def call(*args) base = ["ruby", "-Ilib:test", "test/minitest/test_minitest_unit.rb"] result = ParallelTests::RSpec::Runner.command_with_seed([*base, *args], "555") - result[base.length..-1] + result[base.length..] end it "adds the randomized seed" do diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index a3f15cc38..d3b078317 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -610,7 +610,7 @@ def run_with_file(content) def call(*args) base = ["ruby", "-Ilib:test", "test/minitest/test_minitest_unit.rb"] result = ParallelTests::Test::Runner.command_with_seed([*base, *args], "555") - result[base.length..-1] + result[base.length..] end it "adds the randomized seed" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 405d93d01..b327c6f45 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -84,7 +84,7 @@ def test_tests_in_groups(klass, suffix) def setup_runtime_log # rubocop:disable Lint/NestedMethodDefinition File.open(log, 'w') do |f| - @files[1..-1].each { |file| f.puts "#{file}:#{@files.index(file)}" } + @files[1..].each { |file| f.puts "#{file}:#{@files.index(file)}" } f.puts "#{@files[0]}:10" end end From bd8ed08386695cb8b6f9af720b1544e853fa484d Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 23 Sep 2022 22:14:28 -0700 Subject: [PATCH 148/177] v3.13.0 --- CHANGELOG.md | 6 ++++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 11 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb047fd95..f79ef208a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,12 @@ ### Fixed +## 3.13.0 - 2022-09-23 + +### Changed + +- Drop support for ruby 2.5 + ## v3.12.1 - 2022-09-12 ### Fixed diff --git a/Gemfile.lock b/Gemfile.lock index 504c7efad..bdced955f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.12.1) + parallel_tests (3.13.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index b999245cd..1cd9e2168 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.12.1' + VERSION = '3.13.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 7609579d5..2d3644d11 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.12.1) + parallel_tests (3.13.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 7bafc6bc1..cd370bf04 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.12.1) + parallel_tests (3.13.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index df64aa316..0e7fb1e04 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.12.1) + parallel_tests (3.13.0) parallel GEM From fc090514799e8b46fa92752cc751b14fdac5f9a7 Mon Sep 17 00:00:00 2001 From: Adis Osmonov Date: Sat, 5 Nov 2022 19:53:24 +0000 Subject: [PATCH 149/177] Add TEST_ENV_NUMBER and PARALLEL_TEST_GROUPS environment variables to command output in --verbose (#884) --- CHANGELOG.md | 1 + lib/parallel_tests/cli.rb | 7 +++---- lib/parallel_tests/test/runner.rb | 11 ++++++++--- spec/integration_spec.rb | 24 +++++------------------- spec/parallel_tests/cli_spec.rb | 29 +++++++++++++---------------- 5 files changed, 30 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f79ef208a..2e8ea26b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased ### Breaking Changes +- The `--verbose-process-command` and `--verbose-rerun-command` are combined into `--verbose-command`. See [#884](https://github.com/grosser/parallel_tests/pull/884). ### Added diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 8c3872c44..33ad63e04 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -131,12 +131,12 @@ def report_failure_rerun_commmand(test_results, options) failing_sets = test_results.reject { |r| r[:exit_status] == 0 } return if failing_sets.none? - if options[:verbose] || options[:verbose_rerun_command] + if options[:verbose] || options[:verbose_command] puts "\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\n" failing_sets.each do |failing_set| command = failing_set[:command] command = @runner.command_with_seed(command, failing_set[:seed]) if failing_set[:seed] - puts Shellwords.shelljoin(command) + @runner.print_command(command, failing_set[:env] || {}) end end end @@ -261,8 +261,7 @@ def parse_options!(argv) opts.on("--first-is-1", "Use \"1\" as TEST_ENV_NUMBER to not reuse the default test environment") { options[:first_is_1] = true } opts.on("--fail-fast", "Stop all groups when one group fails (best used with --test-options '--fail-fast' if supported") { options[:fail_fast] = true } opts.on("--verbose", "Print debug output") { options[:verbose] = true } - opts.on("--verbose-process-command", "Displays only the command that will be executed by each process") { options[:verbose_process_command] = true } - opts.on("--verbose-rerun-command", "When there are failures, displays the command executed by each process that failed") { options[:verbose_rerun_command] = true } + opts.on("--verbose-command", "Displays the command that will be executed by each process and when there are failures displays the command executed by each process that failed") { options[:verbose_command] = true } opts.on("--quiet", "Print only tests output") { options[:quiet] = true } opts.on("-v", "--version", "Show Version") do puts ParallelTests::VERSION diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index d61bec444..90007bfed 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -97,11 +97,16 @@ def execute_command(cmd, process_number, num_processes, options) # being able to run with for example `-output foo-$TEST_ENV_NUMBER` worked originally and is convenient cmd.map! { |c| c.gsub("$TEST_ENV_NUMBER", number).gsub("${TEST_ENV_NUMBER}", number) } - puts Shellwords.shelljoin(cmd) if report_process_command?(options) && !options[:serialize_stdout] + print_command(cmd, env) if report_process_command?(options) && !options[:serialize_stdout] execute_command_and_capture_output(env, cmd, options) end + def print_command(command, env) + env_str = ['TEST_ENV_NUMBER', 'PARALLEL_TEST_GROUPS'].map { |e| "#{e}=#{env[e]}" }.join(' ') + puts [env_str, Shellwords.shelljoin(command)].compact.join(' ') + end + def execute_command_and_capture_output(env, cmd, options) pid = nil @@ -119,7 +124,7 @@ def execute_command_and_capture_output(env, cmd, options) output = "#{Shellwords.shelljoin(cmd)}\n#{output}" if report_process_command?(options) && options[:serialize_stdout] - { stdout: output, exit_status: exitstatus, command: cmd, seed: seed } + { env: env, stdout: output, exit_status: exitstatus, command: cmd, seed: seed } end def find_results(test_output) @@ -286,7 +291,7 @@ def set_unknown_runtime(tests, options) end def report_process_command?(options) - options[:verbose] || options[:verbose_process_command] + options[:verbose] || options[:verbose_command] end end end diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 3e364281f..f3e544393 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -66,8 +66,8 @@ def self.it_runs_the_default_folder_if_it_exists(type, test_folder) end end - let(:printed_commands) { /specs? per process\nbundle exec rspec/ } - let(:printed_rerun) { "run the group again:\n\nbundle exec rspec" } + let(:printed_commands) { /specs? per process\nTEST_ENV_NUMBER=(\d+)? PARALLEL_TEST_GROUPS=\d+ bundle exec rspec/ } + let(:printed_rerun) { /run the group again:\n\nTEST_ENV_NUMBER=(\d+)? PARALLEL_TEST_GROUPS=\d+ bundle exec rspec/ } context "running tests sequentially" do it "exits with 0 when each run is successful" do @@ -231,30 +231,16 @@ def test_unicode expect(result).to include('Took') end - it "shows command and rerun with --verbose" do + it "shows command and rerun with --verbose-command" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests ["spec", "--verbose"], type: 'rspec', fail: true + result = run_tests ["spec", "--verbose-command"], type: 'rspec', fail: true expect(result).to match printed_commands - expect(result).to include printed_rerun + expect(result).to match printed_rerun expect(result).to include "bundle exec rspec spec/xxx_spec.rb" expect(result).to include "bundle exec rspec spec/xxx2_spec.rb" end - it "shows only rerun with --verbose-rerun-command" do - write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests ["spec", "--verbose-rerun-command"], type: 'rspec', fail: true - expect(result).to include printed_rerun - expect(result).to_not match printed_commands - end - - it "shows only process with --verbose-process-command" do - write 'spec/xxx_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' - result = run_tests ["spec", "--verbose-process-command"], type: 'rspec', fail: true - expect(result).to_not include printed_rerun - expect(result).to match printed_commands - end - it "fails when tests fail" do write 'spec/xxx_spec.rb', 'describe("it"){it("should"){puts "TEST1"}}' write 'spec/xxx2_spec.rb', 'describe("it"){it("should"){expect(1).to eq(2)}}' diff --git a/spec/parallel_tests/cli_spec.rb b/spec/parallel_tests/cli_spec.rb index 417367fa9..b41ed8b6e 100644 --- a/spec/parallel_tests/cli_spec.rb +++ b/spec/parallel_tests/cli_spec.rb @@ -55,15 +55,9 @@ def call(*args) expect(call(["test", "--verbose"])).to eq(defaults.merge(verbose: true)) end - it "parses --verbose-process-command" do - expect(call(['test', '--verbose-process-command'])).to eq( - defaults.merge(verbose_process_command: true) - ) - end - - it "parses --verbose-rerun-command" do - expect(call(['test', '--verbose-rerun-command'])).to eq( - defaults.merge(verbose_rerun_command: true) + it "parses --verbose-command" do + expect(call(['test', '--verbose-command'])).to eq( + defaults.merge(verbose_command: true) ) end @@ -225,6 +219,10 @@ def self.it_prints_nothing_about_rerun_commands(options) end describe "failure" do + before do + subject.instance_variable_set(:@runner, ParallelTests::Test::Runner) + end + context 'without options' do it_prints_nothing_about_rerun_commands({}) end @@ -233,11 +231,11 @@ def self.it_prints_nothing_about_rerun_commands(options) it_prints_nothing_about_rerun_commands(verbose: false) end - context "with verbose rerun" do + context "with verbose command" do it "prints command if there is a failure" do expect do - subject.send(:report_failure_rerun_commmand, single_failed_command, verbose_rerun_command: true) - end.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout + subject.send(:report_failure_rerun_commmand, single_failed_command, verbose_command: true) + end.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nTEST_ENV_NUMBER= PARALLEL_TEST_GROUPS= foo\n").to_stdout end end @@ -245,7 +243,7 @@ def self.it_prints_nothing_about_rerun_commands(options) it "prints a message and the command if there is a failure" do expect do subject.send(:report_failure_rerun_commmand, single_failed_command, verbose: true) - end.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nfoo\n").to_stdout + end.to output("\n\nTests have failed for a parallel_test group. Use the following command to run the group again:\n\nTEST_ENV_NUMBER= PARALLEL_TEST_GROUPS= foo\n").to_stdout end it "prints multiple commands if there are multiple failures" do @@ -259,7 +257,7 @@ def self.it_prints_nothing_about_rerun_commands(options) ], { verbose: true } ) - end.to output(/foo\nbar\nbaz/).to_stdout + end.to output(/\sfoo\n.+?\sbar\n.+?\sbaz/).to_stdout end it "only includes failures" do @@ -273,14 +271,13 @@ def self.it_prints_nothing_about_rerun_commands(options) ], { verbose: true } ) - end.to output(/foo --color\nbaz/).to_stdout + end.to output(/\sfoo --color\n.+?\sbaz/).to_stdout end it "prints the command with the seed added by the runner" do command = ['rspec', '--color', 'spec/foo_spec.rb'] seed = 555 - subject.instance_variable_set(:@runner, ParallelTests::Test::Runner) expect(ParallelTests::Test::Runner).to receive(:command_with_seed).with(command, seed) .and_return(['my', 'seeded', 'command', 'result', '--seed', seed]) single_failed_command[0].merge!(seed: seed, command: command) From 9100734b38eb0a21bfbf3cfd855cd8c24979c110 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 5 Nov 2022 21:18:19 +0100 Subject: [PATCH 150/177] drop 2.6 (#886) --- .github/workflows/test.yml | 4 ++-- .rubocop.yml | 2 +- parallel_tests.gemspec | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index acf5ba58c..d2d9368cc 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,11 +10,11 @@ jobs: strategy: fail-fast: false # run all tests so we see which gem/ruby combinations break matrix: - ruby: ['2.6', '2.7', '3.0', '3.1', head, jruby-head] + ruby: ['2.7', '3.0', '3.1', head, jruby-head] os: [ubuntu-latest, windows-latest] task: [spec] include: - - ruby: '2.6' # lowest supported version, same as gemspec and .rubocop.yml + - ruby: '2.7' # lowest supported version, same as gemspec and .rubocop.yml os: ubuntu-latest task: rubocop steps: diff --git a/.rubocop.yml b/.rubocop.yml index d69035e3f..a3d012c16 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,6 +1,6 @@ AllCops: NewCops: enable - TargetRubyVersion: 2.6 + TargetRubyVersion: 2.7 SuggestExtensions: false Exclude: - '**/vendor/bundle/**/*' diff --git a/parallel_tests.gemspec b/parallel_tests.gemspec index 17ac64264..3eb00e26c 100644 --- a/parallel_tests.gemspec +++ b/parallel_tests.gemspec @@ -17,5 +17,5 @@ Gem::Specification.new name, ParallelTests::VERSION do |s| s.license = "MIT" s.executables = ["parallel_spinach", "parallel_cucumber", "parallel_rspec", "parallel_test"] s.add_runtime_dependency "parallel" - s.required_ruby_version = '>= 2.6.0' + s.required_ruby_version = '>= 2.7.0' end From f8ff80077f0775ff75d5c8e0a793fe228ff99cf7 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 5 Nov 2022 13:18:34 -0700 Subject: [PATCH 151/177] v4.0.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index bdced955f..c46ed9863 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (3.13.0) + parallel_tests (4.0.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 1cd9e2168..b4e5b6c56 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '3.13.0' + VERSION = '4.0.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 2d3644d11..7645ddeb2 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.13.0) + parallel_tests (4.0.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index cd370bf04..09cddf2b2 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.13.0) + parallel_tests (4.0.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 0e7fb1e04..2a9d172a7 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (3.13.0) + parallel_tests (4.0.0) parallel GEM From 7871e836dc5ef56e64ee01abeb85fe66ef5beca3 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 5 Nov 2022 13:19:53 -0700 Subject: [PATCH 152/177] thx for the pr --- CHANGELOG.md | 9 +++++++++ Readme.md | 1 + 2 files changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e8ea26b5..1c12afbc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,17 @@ ## Unreleased +### Breaking Changes + +### Added + +### Fixed + +## 4.0.0 - 2022-11-05 + ### Breaking Changes - The `--verbose-process-command` and `--verbose-rerun-command` are combined into `--verbose-command`. See [#884](https://github.com/grosser/parallel_tests/pull/884). +- Drop ruby 2.6 support ### Added diff --git a/Readme.md b/Readme.md index 555e43d3f..d39c8a3f7 100644 --- a/Readme.md +++ b/Readme.md @@ -404,6 +404,7 @@ inspired by [pivotal labs](https://blog.pivotal.io/labs/labs/parallelize-your-rs - [Zach Dennis](https://github.com/zdennis) - [Jon Dufresne](https://github.com/jdufresne) - [Eric Kessler](https://github.com/enkessler) + - [Adis Osmonov](https://github.com/adis-io) [Michael Grosser](http://grosser.it)
michael@grosser.it
From 35461d7f6d5869685a788e0d3399a88962dd8b8b Mon Sep 17 00:00:00 2001 From: Matthew Peveler Date: Wed, 30 Nov 2022 01:13:27 -0500 Subject: [PATCH 153/177] Update build status badges in README (#887) --- Readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index d39c8a3f7..09c7f02d1 100644 --- a/Readme.md +++ b/Readme.md @@ -1,8 +1,7 @@ # parallel_tests [![Gem Version](https://badge.fury.io/rb/parallel_tests.svg)](https://rubygems.org/gems/parallel_tests) -[![Build Status](https://travis-ci.org/grosser/parallel_tests.svg)](https://travis-ci.org/grosser/parallel_tests/builds) -[![Build status](https://github.com/grosser/parallel_tests/workflows/windows/badge.svg)](https://github.com/grosser/parallel_tests/actions?query=workflow%3Awindows) +[![Build status](https://github.com/grosser/parallel_tests/workflows/test/badge.svg)](https://github.com/grosser/parallel_tests/actions?query=workflow%3Atest) Speedup Test::Unit + RSpec + Cucumber + Spinach by running parallel on multiple CPU cores.
ParallelTests splits tests into even groups (by number of lines or runtime) and runs each group in a single process with its own database. From 445ec9e8de405a30d866b87c3dc4e1586c6ffa85 Mon Sep 17 00:00:00 2001 From: Rangel Dokov Date: Sat, 14 Jan 2023 23:38:01 +0000 Subject: [PATCH 154/177] Avoid double sending of SIGINT to subprocesses (#889) Standard bash behavior when pressing Ctrl+C is to send SIGINT to the foreground process group. This combines well with standard fork behavior because subprocesses are started in the same group, so a multi-process program is correctly terminated without any explicit signal handling. It however does not work well in cases where signals are handled explicitly like here, because on Ctrl+C the subprocesses receive two SIGINTs - one directly from the shell and one from the interrupt handler in the `CLI` class. This in turn can prevent graceful shutdown in the subprocesses. The specific example that prompted this fix was interrupting feature specs using selenium. In case of a double interrupt the browser process will sometimes remain running after rspec is terminated. --- lib/parallel_tests/test/runner.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 90007bfed..38990d393 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -110,7 +110,7 @@ def print_command(command, env) def execute_command_and_capture_output(env, cmd, options) pid = nil - popen_options = {} + popen_options = { pgroup: true } popen_options[:err] = [:child, :out] if options[:combine_stderr] output = IO.popen(env, cmd, popen_options) do |io| From ee114fcd93b2f4dee7b685f4e2fb1380fcff9efc Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 14 Jan 2023 16:54:46 -0800 Subject: [PATCH 155/177] v4.1.0 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c46ed9863..e728a79d6 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (4.0.0) + parallel_tests (4.1.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index b4e5b6c56..446cb7ff1 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '4.0.0' + VERSION = '4.1.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 7645ddeb2..7cba982c4 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.0.0) + parallel_tests (4.1.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 09cddf2b2..08330b767 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.0.0) + parallel_tests (4.1.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 2a9d172a7..18de96781 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.0.0) + parallel_tests (4.1.0) parallel GEM From b0d2e56153fdef61a3655265b4e6a2f0865c74b4 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sat, 14 Jan 2023 17:05:59 -0800 Subject: [PATCH 156/177] changelog --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c12afbc2..76b740f07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,16 +8,18 @@ ### Fixed +## 4.1.0 - 2023-01-14 + +### Fixed + +- Avoid double sending of SIGINT to subprocesses [#889](https://github.com/grosser/parallel_tests/pull/889) + ## 4.0.0 - 2022-11-05 ### Breaking Changes - The `--verbose-process-command` and `--verbose-rerun-command` are combined into `--verbose-command`. See [#884](https://github.com/grosser/parallel_tests/pull/884). - Drop ruby 2.6 support -### Added - -### Fixed - ## 3.13.0 - 2022-09-23 ### Changed From 516fe3319580747a216c689f1abb9597c4ee7ece Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 6 Feb 2023 23:59:35 +0100 Subject: [PATCH 157/177] fix double int without breaking stdin (#891) --- CHANGELOG.md | 2 ++ lib/parallel_tests/cli.rb | 20 +++++++++++++++++--- lib/parallel_tests/test/runner.rb | 5 ++--- spec/integration_spec.rb | 5 ++++- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76b740f07..c40322b73 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed +- Avoid double sending int while also not breaking debugging [#891](https://github.com/grosser/parallel_tests/pull/891) + ## 4.1.0 - 2023-01-14 ### Fixed diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 33ad63e04..efd5fe3dd 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -32,9 +32,23 @@ def handle_interrupt @graceful_shutdown_attempted ||= false Kernel.exit if @graceful_shutdown_attempted - # The Pid class's synchronize method can't be called directly from a trap - # Using Thread workaround https://github.com/ddollar/foreman/issues/332 - Thread.new { ParallelTests.stop_all_processes } + # In a shell, all sub-processes also get an interrupt, so they shut themselves down. + # In a background process this does not happen and we need to do it ourselves. + # We cannot always send the interrupt since then the sub-processes would get interrupted twice when in foreground + # and that messes with interrupt handling. + # + # (can simulate detached with `(bundle exec parallel_rspec test/a_spec.rb -n 2 &)`) + # also the integration test "passes on int signal to child processes" is detached. + # + # On windows getpgid does not work so we resort to always killing which is the smaller bug. + # + # The ParallelTests::Pids `synchronize` method can't be called directly from a trap, + # using Thread workaround https://github.com/ddollar/foreman/issues/332 + Thread.new do + if Gem.win_platform? || ((child_pid = ParallelTests.pids.all.first) && Process.getpgid(child_pid) != Process.pid) + ParallelTests.stop_all_processes + end + end @graceful_shutdown_attempted = true end diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 38990d393..476510128 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -108,11 +108,10 @@ def print_command(command, env) end def execute_command_and_capture_output(env, cmd, options) - pid = nil - - popen_options = { pgroup: true } + popen_options = {} # do not add `pgroup: true`, it will break `binding.irb` inside the test popen_options[:err] = [:child, :out] if options[:combine_stderr] + pid = nil output = IO.popen(env, cmd, popen_options) do |io| pid = io.pid ParallelTests.pids.add(pid) diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index f3e544393..19ea69d25 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -667,7 +667,10 @@ class A < Spinach::FeatureSteps # Process.kill on Windows doesn't work as expected. It kills all process group instead of just one process. it "passes on int signal to child processes", unless: Gem.win_platform? do timeout = 2 - write "spec/test_spec.rb", "sleep #{timeout}; describe { specify { 'Should not get here' }; specify { p 'Should not get here either'} }" + write( + "spec/test_spec.rb", + "sleep #{timeout}; describe { specify { p 'Should not get here' }; specify { p 'Should not get here either'} }" + ) pid = nil Thread.new { sleep timeout - 0.5; Process.kill("INT", pid) } result = run_tests(["spec"], processes: 2, type: 'rspec', fail: true) { |io| pid = io.pid } From bcc4b8e9925335fcaec8b5dcac6707565e7cc733 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 6 Feb 2023 14:59:59 -0800 Subject: [PATCH 158/177] v4.2.0 --- CHANGELOG.md | 4 ++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c40322b73..e74fbd3ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ ### Fixed +## 4.2.0 - 2023-02-06 + +### Fixed + - Avoid double sending int while also not breaking debugging [#891](https://github.com/grosser/parallel_tests/pull/891) ## 4.1.0 - 2023-01-14 diff --git a/Gemfile.lock b/Gemfile.lock index e728a79d6..a2c5ee2a7 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -10,7 +10,7 @@ GIT PATH remote: . specs: - parallel_tests (4.1.0) + parallel_tests (4.2.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 446cb7ff1..9db8f33fd 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '4.1.0' + VERSION = '4.2.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 7cba982c4..3e708d939 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.1.0) + parallel_tests (4.2.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 08330b767..72fb07c42 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.1.0) + parallel_tests (4.2.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index 18de96781..d7a946b65 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.1.0) + parallel_tests (4.2.0) parallel GEM From faa9a56f46782798da79edc8f2089eadcd5bb5f8 Mon Sep 17 00:00:00 2001 From: Orien Madgwick <497874+orien@users.noreply.github.com> Date: Fri, 10 Feb 2023 09:00:11 +1100 Subject: [PATCH 159/177] CI: add Ruby 3.2 to the test matrix (#892) * CI: add Ruby 3.2 to the test matrix * Bump spinach to version 0.12 * Bump nokogiri to version 1.14.1 --- .github/workflows/test.yml | 2 +- Gemfile | 2 +- Gemfile.lock | 14 ++++---------- spec/fixtures/rails70/Gemfile.lock | 8 ++++---- 4 files changed, 10 insertions(+), 16 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d2d9368cc..fdf3e6482 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false # run all tests so we see which gem/ruby combinations break matrix: - ruby: ['2.7', '3.0', '3.1', head, jruby-head] + ruby: ['2.7', '3.0', '3.1', '3.2', head, jruby-head] os: [ubuntu-latest, windows-latest] task: [spec] include: diff --git a/Gemfile b/Gemfile index 5392e329c..dfa24b03e 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ gem 'minitest', '~> 5.5.0' gem 'rspec', '~> 3.3' gem 'cucumber', "~> 4.0" gem 'cuke_modeler', '~> 3.6' -gem 'spinach', git: "https://github.com/grosser/spinach.git", branch: "grosser/json" # https://github.com/codegram/spinach/pull/229 +gem 'spinach', '~> 0.12' gem 'rake' gem 'rubocop', '~> 1.28.0' # lock minor so we do not get accidental violations, also need to drop ruby 2.5 support to upgrade further gem 'rubocop-ast', '~> 1.17.0' # also need to drop ruby 2.5 support to remove this line diff --git a/Gemfile.lock b/Gemfile.lock index a2c5ee2a7..0c973748d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,12 +1,3 @@ -GIT - remote: https://github.com/grosser/spinach.git - revision: e4e08ffd6d0877d139d602f3f5ccba3c97d69a36 - branch: grosser/json - specs: - spinach (0.11.0) - colorize - gherkin-ruby (>= 0.3.2) - PATH remote: . specs: @@ -107,6 +98,9 @@ GEM rubocop-ast (1.17.0) parser (>= 3.1.1.0) ruby-progressbar (1.11.0) + spinach (0.12.0) + colorize + gherkin-ruby (>= 0.3.2) sys-uname (1.2.2) ffi (~> 1.1) test-unit (3.5.3) @@ -132,7 +126,7 @@ DEPENDENCIES rspec (~> 3.3) rubocop (~> 1.28.0) rubocop-ast (~> 1.17.0) - spinach! + spinach (~> 0.12) test-unit BUNDLED WITH diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index d7a946b65..cd6af4474 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -83,14 +83,14 @@ GEM net-protocol timeout nio4r (2.5.8) - nokogiri (1.13.3) + nokogiri (1.14.1) mini_portile2 (~> 2.8.0) racc (~> 1.4) - nokogiri (1.13.3-x64-mingw32) + nokogiri (1.14.1-x64-mingw32) racc (~> 1.4) - nokogiri (1.13.3-x86_64-darwin) + nokogiri (1.14.1-x86_64-darwin) racc (~> 1.4) - nokogiri (1.13.3-x86_64-linux) + nokogiri (1.14.1-x86_64-linux) racc (~> 1.4) parallel (1.22.1) racc (1.6.0) From 7bebc55b7143afe09c4ad3d69c11fb0e15d44d77 Mon Sep 17 00:00:00 2001 From: "M.Yamashita" <4653960+M-Yamashita01@users.noreply.github.com> Date: Sat, 18 Mar 2023 12:01:12 +0900 Subject: [PATCH 160/177] Remove duplicate raise codes. (#897) --- lib/parallel_tests/grouper.rb | 4 ---- spec/parallel_tests/grouper_spec.rb | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index fd2229d97..444027649 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -26,10 +26,6 @@ def in_even_groups_by_size(items, num_groups, options = {}) isolate_count = isolate_count(options) - if isolate_count >= num_groups - raise 'Number of isolated processes must be less than total the number of processes' - end - if isolate_count >= num_groups raise 'Number of isolated processes must be >= total number of processes' end diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index cba9de287..57f0764cb 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -72,7 +72,7 @@ def call(num_groups, options = {}) expect do call(3, single_process: [/1/], isolate_count: 3) end.to raise_error( - "Number of isolated processes must be less than total the number of processes" + "Number of isolated processes must be >= total number of processes" ) end From f70f2ee0624a318296732cbe149468174cfdd97e Mon Sep 17 00:00:00 2001 From: Marlon Moyer Date: Thu, 23 Mar 2023 12:15:57 -0500 Subject: [PATCH 161/177] update Readme for PR 884 (#899) PR [#884](https://github.com/grosser/parallel_tests/pull/884) combined both `verbose-process-command` and `verbose-rerun-command` into `verbose-command` This PR updates the Readme to reflect that change --- Readme.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 09c7f02d1..1b5c70045 100644 --- a/Readme.md +++ b/Readme.md @@ -249,8 +249,7 @@ Options are: --first-is-1 Use "1" as TEST_ENV_NUMBER to not reuse the default test environment --fail-fast Stop all groups when one group fails (best used with --test-options '--fail-fast' if supported --verbose Print debug output - --verbose-process-command Displays only the command that will be executed by each process - --verbose-rerun-command When there are failures, displays the command executed by each process that failed + --verbose-command Displays the command that will be executed by each process and when there are failures displays the command executed by each process that failed --quiet Print only tests output -v, --version Show Version -h, --help Show this. From 6363819a22f4944174acd688eb3fedcf4b6ad52c Mon Sep 17 00:00:00 2001 From: Zsolt Kozaroczy Date: Sat, 13 May 2023 00:28:32 +0200 Subject: [PATCH 162/177] Fix $TEST_ENV_NUMBER replacing code to not affect all processes (#905) --- lib/parallel_tests/test/runner.rb | 2 +- spec/integration_spec.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/parallel_tests/test/runner.rb b/lib/parallel_tests/test/runner.rb index 476510128..173767829 100644 --- a/lib/parallel_tests/test/runner.rb +++ b/lib/parallel_tests/test/runner.rb @@ -95,7 +95,7 @@ def execute_command(cmd, process_number, num_processes, options) cmd = ["nice", *cmd] if options[:nice] # being able to run with for example `-output foo-$TEST_ENV_NUMBER` worked originally and is convenient - cmd.map! { |c| c.gsub("$TEST_ENV_NUMBER", number).gsub("${TEST_ENV_NUMBER}", number) } + cmd = cmd.map { |c| c.gsub("$TEST_ENV_NUMBER", number).gsub("${TEST_ENV_NUMBER}", number) } print_command(cmd, env) if report_process_command?(options) && !options[:serialize_stdout] diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index 19ea69d25..88c6c5bc9 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -288,6 +288,11 @@ def test_unicode expect(result.gsub('"', '').chars.sort).to eq(['0', '2', '3', '4']) end + it "can exec given commands with $TEST_ENV_NUMBER" do + result = run_tests ['-e', 'echo foo-$TEST_ENV_NUMBER'], processes: 4 + expect(result.split(/\n+/).sort).to eq(['foo-', 'foo-2', 'foo-3', 'foo-4']) + end + it "can exec given command non-parallel" do result = run_tests( ['-e', 'ruby -e "sleep(rand(10)/100.0); puts ENV[:TEST_ENV_NUMBER.to_s].inspect"'], From 163f53c67689e8362dc8eae635a839416e680fe0 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Fri, 12 May 2023 15:32:19 -0700 Subject: [PATCH 163/177] v4.2.1 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 0c973748d..65112fdbc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (4.2.0) + parallel_tests (4.2.1) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index 9db8f33fd..afe816f7b 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '4.2.0' + VERSION = '4.2.1' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 3e708d939..24bd68f18 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.0) + parallel_tests (4.2.1) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 72fb07c42..1205d1314 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.0) + parallel_tests (4.2.1) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index cd6af4474..f970b5613 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.0) + parallel_tests (4.2.1) parallel GEM From fed72e4717fe513f13c4240261a5beb2a4e161ad Mon Sep 17 00:00:00 2001 From: Benjamin Quorning <22333+bquorning@users.noreply.github.com> Date: Thu, 25 May 2023 22:31:55 +0200 Subject: [PATCH 164/177] Remove compatibility with RSpec 2 (#908) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RSpec 3 was released 9 years ago. Most people will have upgraded by now 😅 --- CHANGELOG.md | 2 ++ lib/parallel_tests/rspec/failures_logger.rb | 18 +++++------------- lib/parallel_tests/rspec/logger_base.rb | 2 -- lib/parallel_tests/rspec/runtime_logger.rb | 5 ++--- lib/parallel_tests/rspec/summary_logger.rb | 2 +- .../rspec/runtime_logger_spec.rb | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e74fbd3ec..6832c309a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### Breaking Changes +- Drop support for RSpec 2. + ### Added ### Fixed diff --git a/lib/parallel_tests/rspec/failures_logger.rb b/lib/parallel_tests/rspec/failures_logger.rb index 7047d43db..3c979f697 100644 --- a/lib/parallel_tests/rspec/failures_logger.rb +++ b/lib/parallel_tests/rspec/failures_logger.rb @@ -3,22 +3,14 @@ require 'parallel_tests/rspec/runner' class ParallelTests::RSpec::FailuresLogger < ParallelTests::RSpec::LoggerBase - if RSPEC_2 - def dump_failures(*args); end - else - RSpec::Core::Formatters.register self, :dump_summary - end + RSpec::Core::Formatters.register(self, :dump_summary) def dump_summary(*args) lock_output do - if RSPEC_2 - dump_commands_to_rerun_failed_examples - else - notification = args.first - unless notification.failed_examples.empty? - colorizer = ::RSpec::Core::Formatters::ConsoleCodes - output.puts notification.colorized_rerun_commands(colorizer) - end + notification = args.first + unless notification.failed_examples.empty? + colorizer = ::RSpec::Core::Formatters::ConsoleCodes + output.puts notification.colorized_rerun_commands(colorizer) end end @output.flush diff --git a/lib/parallel_tests/rspec/logger_base.rb b/lib/parallel_tests/rspec/logger_base.rb index ab1356bb8..4b3b1bff1 100644 --- a/lib/parallel_tests/rspec/logger_base.rb +++ b/lib/parallel_tests/rspec/logger_base.rb @@ -7,8 +7,6 @@ module RSpec require 'rspec/core/formatters/base_text_formatter' class ParallelTests::RSpec::LoggerBase < RSpec::Core::Formatters::BaseTextFormatter - RSPEC_2 = RSpec::Core::Version::STRING.start_with?('2') - def initialize(*args) super diff --git a/lib/parallel_tests/rspec/runtime_logger.rb b/lib/parallel_tests/rspec/runtime_logger.rb index 14f9b883b..bfcccfa1a 100644 --- a/lib/parallel_tests/rspec/runtime_logger.rb +++ b/lib/parallel_tests/rspec/runtime_logger.rb @@ -9,7 +9,7 @@ def initialize(*args) @group_nesting = 0 end - RSpec::Core::Formatters.register self, :example_group_started, :example_group_finished, :start_dump unless RSPEC_2 + RSpec::Core::Formatters.register(self, :example_group_started, :example_group_finished, :start_dump) def example_group_started(example_group) @time = ParallelTests.now if @group_nesting == 0 @@ -20,8 +20,7 @@ def example_group_started(example_group) def example_group_finished(notification) @group_nesting -= 1 if @group_nesting == 0 - path = (RSPEC_2 ? notification.file_path : notification.group.file_path) - @example_times[path] += ParallelTests.now - @time + @example_times[notification.group.file_path] += ParallelTests.now - @time end super if defined?(super) end diff --git a/lib/parallel_tests/rspec/summary_logger.rb b/lib/parallel_tests/rspec/summary_logger.rb index 339a60134..8b30cd6ca 100644 --- a/lib/parallel_tests/rspec/summary_logger.rb +++ b/lib/parallel_tests/rspec/summary_logger.rb @@ -2,7 +2,7 @@ require 'parallel_tests/rspec/failures_logger' class ParallelTests::RSpec::SummaryLogger < ParallelTests::RSpec::LoggerBase - RSpec::Core::Formatters.register self, :dump_failures unless RSPEC_2 + RSpec::Core::Formatters.register(self, :dump_failures) def dump_failures(*args) lock_output { super } diff --git a/spec/parallel_tests/rspec/runtime_logger_spec.rb b/spec/parallel_tests/rspec/runtime_logger_spec.rb index 23f62e5c6..ec1000800 100644 --- a/spec/parallel_tests/rspec/runtime_logger_spec.rb +++ b/spec/parallel_tests/rspec/runtime_logger_spec.rb @@ -19,7 +19,7 @@ def log_for_a_file(_options = {}) end example = double(file_path: "#{Dir.pwd}/spec/foo.rb") - example = double(group: example) unless ParallelTests::RSpec::RuntimeLogger::RSPEC_2 + example = double(group: example) logger.example_group_started example logger.example_group_finished example From 3247815a8e17136e55f0878c0e1397274b9c5d7d Mon Sep 17 00:00:00 2001 From: Benjamin Quorning <22333+bquorning@users.noreply.github.com> Date: Fri, 26 May 2023 16:55:31 +0200 Subject: [PATCH 165/177] Upgrade RuboCop and fix some offenses (#909) Ruby 2.5 compatibility is no longer a concern, so we can now upgrade to the very latest version. --- .rubocop.yml | 3 ++ Gemfile | 3 +- Gemfile.lock | 33 +++++++++++++--------- lib/parallel_tests/cli.rb | 2 +- lib/parallel_tests/rspec/runtime_logger.rb | 2 +- spec/parallel_tests/test/runner_spec.rb | 18 ++++++------ 6 files changed, 34 insertions(+), 27 deletions(-) diff --git a/.rubocop.yml b/.rubocop.yml index a3d012c16..d843d1687 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -78,6 +78,9 @@ Layout/LineLength: Enabled: false Max: 120 +Style/RedundantConstantBase: + Enabled: false + Style/RegexpLiteral: Enabled: false diff --git a/Gemfile b/Gemfile index dfa24b03e..88af8f0e2 100644 --- a/Gemfile +++ b/Gemfile @@ -10,5 +10,4 @@ gem 'cucumber', "~> 4.0" gem 'cuke_modeler', '~> 3.6' gem 'spinach', '~> 0.12' gem 'rake' -gem 'rubocop', '~> 1.28.0' # lock minor so we do not get accidental violations, also need to drop ruby 2.5 support to upgrade further -gem 'rubocop-ast', '~> 1.17.0' # also need to drop ruby 2.5 support to remove this line +gem 'rubocop', '~> 1.51.0' # lock minor so we do not get accidental violations diff --git a/Gemfile.lock b/Gemfile.lock index 65112fdbc..dd14302f0 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -53,15 +53,18 @@ GEM cucumber-gherkin (< 23.0) diff-lcs (1.3) ffi (1.15.5) + ffi (1.15.5-java) ffi (1.15.5-x64-mingw32) gherkin-ruby (0.3.2) i18n (1.10.0) concurrent-ruby (~> 1.0) + json (2.6.3) + json (2.6.3-java) middleware (0.1.0) minitest (5.5.1) multi_test (0.1.2) - parallel (1.22.1) - parser (3.1.2.1) + parallel (1.23.0) + parser (3.2.2.1) ast (~> 2.4.1) power_assert (2.0.1) protobuf-cucumber (3.10.8) @@ -71,7 +74,7 @@ GEM thread_safe rainbow (3.1.1) rake (13.0.6) - regexp_parser (2.5.0) + regexp_parser (2.8.0) rexml (3.2.5) rspec (3.11.0) rspec-core (~> 3.11.0) @@ -86,18 +89,19 @@ GEM diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.11.0) rspec-support (3.11.0) - rubocop (1.28.2) + rubocop (1.51.0) + json (~> 2.3) parallel (~> 1.10) - parser (>= 3.1.0.0) + parser (>= 3.2.0.0) rainbow (>= 2.2.2, < 4.0) regexp_parser (>= 1.8, < 3.0) - rexml - rubocop-ast (>= 1.17.0, < 2.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.28.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 1.4.0, < 3.0) - rubocop-ast (1.17.0) - parser (>= 3.1.1.0) - ruby-progressbar (1.11.0) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.28.1) + parser (>= 3.2.1.0) + ruby-progressbar (1.13.0) spinach (0.12.0) colorize gherkin-ruby (>= 0.3.2) @@ -107,12 +111,14 @@ GEM power_assert thor (1.2.1) thread_safe (0.3.6) + thread_safe (0.3.6-java) tzinfo (2.0.4) concurrent-ruby (~> 1.0) - unicode-display_width (2.2.0) + unicode-display_width (2.4.2) zeitwerk (2.5.4) PLATFORMS + java ruby x64-mingw32 @@ -124,8 +130,7 @@ DEPENDENCIES parallel_tests! rake rspec (~> 3.3) - rubocop (~> 1.28.0) - rubocop-ast (~> 1.17.0) + rubocop (~> 1.51.0) spinach (~> 0.12) test-unit diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index efd5fe3dd..c527e823c 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -258,7 +258,7 @@ def parse_options!(argv) "--suffix [PATTERN]", <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") override built in test file pattern (should match suffix): - '_spec\.rb$' - matches rspec files + '_spec.rb$' - matches rspec files '_(test|spec).rb$' - matches test or spec files TEXT ) { |pattern| options[:suffix] = /#{pattern}/ } diff --git a/lib/parallel_tests/rspec/runtime_logger.rb b/lib/parallel_tests/rspec/runtime_logger.rb index bfcccfa1a..ba4637aaa 100644 --- a/lib/parallel_tests/rspec/runtime_logger.rb +++ b/lib/parallel_tests/rspec/runtime_logger.rb @@ -38,7 +38,7 @@ def start_dump(*) lock_output do @example_times.each do |file, time| relative_path = file.sub(%r{^#{Regexp.escape Dir.pwd}/}, '').sub(%r{^\./}, "") - @output.puts "#{relative_path}:#{time > 0 ? time : 0}" + @output.puts "#{relative_path}:#{[time, 0].max}" end end @output.flush diff --git a/spec/parallel_tests/test/runner_spec.rb b/spec/parallel_tests/test/runner_spec.rb index d3b078317..2e2055e38 100644 --- a/spec/parallel_tests/test/runner_spec.rb +++ b/spec/parallel_tests/test/runner_spec.rb @@ -147,12 +147,12 @@ def call(*args) isolated, *groups = result expect(isolated).to eq(["aaa"]) - actual = groups.map(&:to_set).to_set + actual = groups.to_set(&:to_set) # both eee and ccs are the same size, so either can be in either group valid_combinations = [ - [["bbb", "eee"], ["ccc", "ddd"]].map(&:to_set).to_set, - [["bbb", "ccc"], ["eee", "ddd"]].map(&:to_set).to_set + [["bbb", "eee"], ["ccc", "ddd"]].to_set(&:to_set), + [["bbb", "ccc"], ["eee", "ddd"]].to_set(&:to_set) ] expect(valid_combinations).to include(actual) @@ -169,12 +169,12 @@ def call(*args) isolated_1, isolated_2, *groups = result expect(isolated_1).to eq(["aaa2"]) expect(isolated_2).to eq(["aaa1", "aaa3"]) - actual = groups.map(&:to_set).to_set + actual = groups.to_set(&:to_set) # both eee and ccs are the same size, so either can be in either group valid_combinations = [ - [["bbb", "eee"], ["ccc", "ddd"]].map(&:to_set).to_set, - [["bbb", "ccc"], ["eee", "ddd"]].map(&:to_set).to_set + [["bbb", "eee"], ["ccc", "ddd"]].to_set(&:to_set), + [["bbb", "ccc"], ["eee", "ddd"]].to_set(&:to_set) ] expect(valid_combinations).to include(actual) @@ -191,12 +191,12 @@ def call(*args) specify_groups_1, specify_groups_2, *groups = result expect(specify_groups_1).to eq(["aaa2", "aaa1"]) expect(specify_groups_2).to eq(["bbb"]) - actual = groups.map(&:to_set).to_set + actual = groups.to_set(&:to_set) # both eee and ccs are the same size, so either can be in either group valid_combinations = [ - [["aaa3", "ccc"], ["ddd", "eee"]].map(&:to_set).to_set, - [["aaa3", "eee"], ["ddd", "ccc"]].map(&:to_set).to_set + [["aaa3", "ccc"], ["ddd", "eee"]].to_set(&:to_set), + [["aaa3", "eee"], ["ddd", "ccc"]].to_set(&:to_set) ] expect(valid_combinations).to include(actual) From 432b80ab684423af7a8fc38c63aee01fa1e59297 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=ABl=20Quenneville?= Date: Tue, 5 Sep 2023 23:06:17 -0400 Subject: [PATCH 166/177] Document `--only-group` grouping strategy choice (#870) The documentation says that parallel_test will attempt to use a runtime grouping strategy if a runtime file is present and otherwise fall back to the filesize strategy. This behavior can be overridden with an explicit `--group-by` flag. The `--only-group` flag changes this by always running with the filesize strategy when no explicit strategy is given, even if a runtime file is present. This behavior happens in `lib/parallel_tests/cli.rb:312`. I was attempting to rely on the default behavior and also use the `--only-group` flag and couldn't figure out why my runtime log wasn't getting used. Only by reading the source did I figure out this undocumented edge-case in the `--only-group` flag. This commit adds explicit documentation about this. If you want to use the `--only-group` flag and a runtime log, you _must_ explicitly set the `--group-by` flag instead of relying on the default behavior. --- CHANGELOG.md | 3 +++ Readme.md | 4 +++- lib/parallel_tests/cli.rb | 10 +++++++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6832c309a..82a7bab41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ ### Added +- Document unexpected behavior where the `--only-group` flag will also set a + grouping strategy. + ### Fixed ## 4.2.0 - 2023-02-06 diff --git a/Readme.md b/Readme.md index 1b5c70045..0477ce6b5 100644 --- a/Readme.md +++ b/Readme.md @@ -228,7 +228,9 @@ Options are: Process 1 will contain 1_spec.rb and 2_spec.rb Process 2 will contain 3_spec.rb Process 3 will contain all other specs - --only-group INT[,INT] + --only-group INT[,INT] Only run the given group numbers. Note that this will force the 'filesize' + grouping strategy (even when the runtime log is present) unless you explicitly + set it otherwise via the '-group-by' flag. -e, --exec [COMMAND] execute this code parallel and with ENV['TEST_ENV_NUMBER'] -o, --test-options '[OPTIONS]' execute test commands with those options -t, --type [TYPE] test(default) / rspec / cucumber / spinach diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index c527e823c..15d910c73 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -244,7 +244,15 @@ def parse_options!(argv) TEXT ) { |groups| options[:specify_groups] = groups } - opts.on("--only-group INT[,INT]", Array) { |groups| options[:only_group] = groups.map(&:to_i) } + opts.on( + "--only-group INT[,INT]", + Array, + <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") + Only run the given group numbers. Note that this will force the 'filesize' + grouping strategy (even when the runtime log is present) unless you explicitly + set it otherwise via the '-group-by' flag. + TEXT + ) { |groups| options[:only_group] = groups.map(&:to_i) } opts.on("-e", "--exec [COMMAND]", "execute this code parallel and with ENV['TEST_ENV_NUMBER']") { |arg| options[:execute] = Shellwords.shellsplit(arg) } opts.on("-o", "--test-options '[OPTIONS]'", "execute test commands with those options") { |arg| options[:test_options] = Shellwords.shellsplit(arg) } From 063362a303be062d7fb1f2b602c3f2e14d93c65f Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 5 Sep 2023 20:11:01 -0700 Subject: [PATCH 167/177] simplify docs --- lib/parallel_tests/cli.rb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 15d910c73..ce71266b4 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -248,9 +248,8 @@ def parse_options!(argv) "--only-group INT[,INT]", Array, <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") - Only run the given group numbers. Note that this will force the 'filesize' - grouping strategy (even when the runtime log is present) unless you explicitly - set it otherwise via the '-group-by' flag. + Only run the given group numbers. + Changes `--group-by` default to 'filesize'. TEXT ) { |groups| options[:only_group] = groups.map(&:to_i) } From 7ae09fba13aa0abbf3d667bd2b251165c3053f84 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 5 Sep 2023 20:11:30 -0700 Subject: [PATCH 168/177] v4.2.2 --- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index dd14302f0..3c7868ed4 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (4.2.1) + parallel_tests (4.2.2) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index afe816f7b..f9a707628 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '4.2.1' + VERSION = '4.2.2' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index 24bd68f18..a2137e710 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.1) + parallel_tests (4.2.2) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 1205d1314..54f3b8fa3 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.1) + parallel_tests (4.2.2) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index f970b5613..a319dd0f0 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.1) + parallel_tests (4.2.2) parallel GEM From 273a1cc8fe50c5cb2c8c73af31bba51675c2e5f8 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Tue, 5 Sep 2023 20:15:30 -0700 Subject: [PATCH 169/177] changelog --- CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82a7bab41..0594cbbcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ ### Breaking Changes +### Added + +## 4.2.2 - 2023-09-05 + +### Breaking Changes + - Drop support for RSpec 2. ### Added @@ -11,8 +17,13 @@ - Document unexpected behavior where the `--only-group` flag will also set a grouping strategy. +## 4.2.1 - 2023-05-05 + ### Fixed +- Fix $TEST_ENV_NUMBER replacing code to not affect all processes (#905) +- Remove duplicate raise codes. (#897) + ## 4.2.0 - 2023-02-06 ### Fixed From 439a9cab1701651b881bd052d6fb7c37b7d3061a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20=C5=A0im=C3=A1nek?= Date: Mon, 9 Oct 2023 03:23:06 +0200 Subject: [PATCH 170/177] Support also feature files used by RSpec turnip gem. (#919) --- CHANGELOG.md | 2 ++ lib/parallel_tests/rspec/runner.rb | 4 +++- spec/parallel_tests/rspec/runner_spec.rb | 6 ++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0594cbbcf..5ba412c17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ ### Added +- Support for RSpec turnip feature files. + ## 4.2.2 - 2023-09-05 ### Breaking Changes diff --git a/lib/parallel_tests/rspec/runner.rb b/lib/parallel_tests/rspec/runner.rb index 617d5f42f..016751f2d 100644 --- a/lib/parallel_tests/rspec/runner.rb +++ b/lib/parallel_tests/rspec/runner.rb @@ -33,8 +33,10 @@ def test_file_name "spec" end + # used to find all _spec.rb files + # supports also feature files used by rspec turnip extension def test_suffix - /_spec\.rb$/ + /(_spec\.rb|\.feature)$/ end def line_is_result?(line) diff --git a/spec/parallel_tests/rspec/runner_spec.rb b/spec/parallel_tests/rspec/runner_spec.rb index bec9f6957..540a4e434 100644 --- a/spec/parallel_tests/rspec/runner_spec.rb +++ b/spec/parallel_tests/rspec/runner_spec.rb @@ -119,6 +119,12 @@ def call(*args) ParallelTests::RSpec::Runner.send(:find_tests, *args) end + it "finds turnip feature files" do + with_files(['a/test.feature']) do |root| + expect(call(["#{root}/"])).to eq(["#{root}/a/test.feature"]) + end + end + it "doesn't find backup files with the same name as test files" do with_files(['a/x_spec.rb', 'a/x_spec.rb.bak']) do |root| expect(call(["#{root}/"])).to eq(["#{root}/a/x_spec.rb"]) From 96d5a8c259b0a15ca63a1b5e17f857526c65e349 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 8 Oct 2023 18:25:35 -0700 Subject: [PATCH 171/177] turnip docs --- Readme.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Readme.md b/Readme.md index 0477ce6b5..b0ea3f53c 100644 --- a/Readme.md +++ b/Readme.md @@ -3,8 +3,8 @@ [![Gem Version](https://badge.fury.io/rb/parallel_tests.svg)](https://rubygems.org/gems/parallel_tests) [![Build status](https://github.com/grosser/parallel_tests/workflows/test/badge.svg)](https://github.com/grosser/parallel_tests/actions?query=workflow%3Atest) -Speedup Test::Unit + RSpec + Cucumber + Spinach by running parallel on multiple CPU cores.
-ParallelTests splits tests into even groups (by number of lines or runtime) and runs each group in a single process with its own database. +Speedup Minitest + RSpec + Turnip + Cucumber + Spinach by running parallel on multiple CPU cores.
+ParallelTests splits tests into balanced groups (by number of lines or runtime) and runs each group in a process with its own database. Setup for Rails =============== @@ -46,7 +46,7 @@ test: rake parallel:drop ### Run! - rake parallel:test # Test::Unit + rake parallel:test # Minitest rake parallel:spec # RSpec rake parallel:features # Cucumber rake parallel:features-spinach # Spinach From 370add940419e3bc6deacc210b137c184ca15be6 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 8 Oct 2023 18:26:14 -0700 Subject: [PATCH 172/177] v4.3.0 --- CHANGELOG.md | 4 ++++ Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 9 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ba412c17..87a058566 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,10 @@ ### Added +## 4.3.0 - 2023-10-08 + +### Added + - Support for RSpec turnip feature files. ## 4.2.2 - 2023-09-05 diff --git a/Gemfile.lock b/Gemfile.lock index 3c7868ed4..214675c7e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (4.2.2) + parallel_tests (4.3.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index f9a707628..e978055ad 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '4.2.2' + VERSION = '4.3.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index a2137e710..e00dd26eb 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.2) + parallel_tests (4.3.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 54f3b8fa3..8055a9d99 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.2) + parallel_tests (4.3.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index a319dd0f0..d8ab9fa78 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.2.2) + parallel_tests (4.3.0) parallel GEM From 8a663bdffe1d53533c01a287aa9d67d4886cc12f Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Mon, 9 Oct 2023 05:16:46 +0200 Subject: [PATCH 173/177] improve instructions for runtime logger (#921) --- Readme.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/Readme.md b/Readme.md index b0ea3f53c..52774eaaa 100644 --- a/Readme.md +++ b/Readme.md @@ -106,11 +106,13 @@ at_exit do end ``` -Even test group run-times -========================= +Even test group runtimes +======================== -Test groups are often not balanced and will run for different times, making everything wait for the slowest group. -Use these loggers to record test runtime and then use the recorded runtime to balance test groups more evenly. +Test groups will often run for different times, making the full test run as slow as the slowest group. + +Step 1: Use these loggers (see below) to record test runtime +Step 2: Your next run will use the recorded test runtimes (use `--runtime-log ` if you picked a location different from below) ### RSpec @@ -128,9 +130,11 @@ Add to your `test_helper.rb`: require 'parallel_tests/test/runtime_logger' if ENV['RECORD_RUNTIME'] ``` -results will be logged to tmp/parallel_runtime_test.log when `RECORD_RUNTIME` is set, +results will be logged to `tmp/parallel_runtime_test.log` when `RECORD_RUNTIME` is set, so it is not always required or overwritten. +### TODO: add instructions for other frameworks + Loggers ======= From 6e9be6f529b64e5f9c8e4439754bca0b2ef3f2b1 Mon Sep 17 00:00:00 2001 From: Lawrence Gripper Date: Fri, 3 Nov 2023 18:15:56 +0000 Subject: [PATCH 174/177] Sort `runtime_logger` output (#924) * Sort `runtime_logger` output Show the slowest tests first * Update changelog and contributor * Delete .devcontainer/devcontainer.json --- CHANGELOG.md | 2 ++ lib/parallel_tests/rspec/runtime_logger.rb | 2 ++ spec/parallel_tests/rspec/runtime_logger_spec.rb | 11 ++++++++++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87a058566..01ff15c90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- Sort the output of `runtime_logger` for RSpec to show slowest tests first + ### Breaking Changes ### Added diff --git a/lib/parallel_tests/rspec/runtime_logger.rb b/lib/parallel_tests/rspec/runtime_logger.rb index ba4637aaa..d18e06be2 100644 --- a/lib/parallel_tests/rspec/runtime_logger.rb +++ b/lib/parallel_tests/rspec/runtime_logger.rb @@ -36,6 +36,8 @@ def dump_pending(*); end def start_dump(*) return unless ENV['TEST_ENV_NUMBER'] # only record when running in parallel lock_output do + # Order the output from slowest to fastest + @example_times = @example_times.sort_by(&:last).reverse @example_times.each do |file, time| relative_path = file.sub(%r{^#{Regexp.escape Dir.pwd}/}, '').sub(%r{^\./}, "") @output.puts "#{relative_path}:#{[time, 0].max}" diff --git a/spec/parallel_tests/rspec/runtime_logger_spec.rb b/spec/parallel_tests/rspec/runtime_logger_spec.rb index ec1000800..14b5a04ab 100644 --- a/spec/parallel_tests/rspec/runtime_logger_spec.rb +++ b/spec/parallel_tests/rspec/runtime_logger_spec.rb @@ -120,13 +120,22 @@ def write(file, content) end RUBY + write "spec/slower_spec.rb", <<-RUBY + describe "xxx" do + it "is slow" do + sleep 3 + end + end + RUBY + system( { 'TEST_ENV_NUMBER' => '1' }, "rspec", "spec", "-I", Bundler.root.join("lib").to_s, "--format", "ParallelTests::RSpec::RuntimeLogger", "--out", "runtime.log" ) || raise("nope") result = File.read("runtime.log") - expect(result).to include "a_spec.rb:1.5" + expect(result).to start_with("spec/slower_spec.rb:3.0") + expect(result).to include "spec/a_spec.rb:1.5" end end end From 7291dfd7067f40f7675a738bfc6d39ee33af5895 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Sun, 24 Dec 2023 15:51:16 -0500 Subject: [PATCH 175/177] Add new ParallelTests::RSpec::VerboseFormatter for enhanced debugging (#926) The new formatter allows users of parallel_rspec to more easily obtain detailed information about the examples running as they occur in real time. Background: In my project, it was observed that an RSpec example would hang intermittently on CI. At first, no team member was able to make this reliably fail enough on CI to facilitate debugging and no one was able to reproduce locally at all. The hang only occurred with parallel tests running and never with just the "rspec" command. In an attempt to gather more information, we began using the RSpec "documentation" formatter which outputs the "description", "context", and "it" strings. Unfortunately, when running in parallel, the output from different processes will interleave with one another making it extremely difficult to understand which example is responsible for the observed hang. Solution: Build a "documentation-like" formatter that plays nicely with the parallel_tests framework. The new formatter always ouputs all information on a single line to avoid important details from different processes interleaving with one another. This means the "describe" and "context" strings will be repeated across multiple "it" blocks. To further assist, the formatter include the PID and parallel process number to help identify which subprocess hangs and which one continues. The output will look something like: ``` [14403] [2] [STARTED] Foo foo [14402] [1] [STARTED] Bar bar [14402] [1] [PASSED] Bar bar ``` In the output above, it is clear the "Foo foo" example is still running. Using this formatter, our project's team was able to successfully identify the example causing the intermittent hang and then address it. As such, I'm hoping that this may be useful for a larger audience. --- CHANGELOG.md | 2 + Readme.md | 16 +++++ lib/parallel_tests/rspec/verbose_formatter.rb | 62 +++++++++++++++++++ .../rspec/verbose_formatter_spec.rb | 52 ++++++++++++++++ spec/spec_helper.rb | 1 + 5 files changed, 133 insertions(+) create mode 100644 lib/parallel_tests/rspec/verbose_formatter.rb create mode 100644 spec/parallel_tests/rspec/verbose_formatter_spec.rb diff --git a/CHANGELOG.md b/CHANGELOG.md index 01ff15c90..eb4d63af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ## Unreleased - Sort the output of `runtime_logger` for RSpec to show slowest tests first +- Add new `ParallelTests::RSpec::VerboseFormatter` to output detailed + information about each example as it starts and finishes. ### Breaking Changes diff --git a/Readme.md b/Readme.md index 52774eaaa..90d3d4316 100644 --- a/Readme.md +++ b/Readme.md @@ -183,6 +183,22 @@ To rerun failures: cucumber @tmp/cucumber_failures.log +Formatters +========== + +RSpec: VerboseFormatter + +Output the RSpec PID, parallel process number, spec status, and the full +example description. The formatter outputs one line when starting an example +and then again when finishing. Use like the RSpec documentation but plays +nicely with parallel processes. + +Usage: + +```console +$ parallel_rspec -- --format ParallelTests::RSpec::VerboseFormatter -- +``` + Setup for non-rails =================== diff --git a/lib/parallel_tests/rspec/verbose_formatter.rb b/lib/parallel_tests/rspec/verbose_formatter.rb new file mode 100644 index 000000000..ebd54deda --- /dev/null +++ b/lib/parallel_tests/rspec/verbose_formatter.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'rspec/core/formatters/base_text_formatter' +require 'parallel_tests/rspec/runner' + +class ParallelTests::RSpec::VerboseFormatter < RSpec::Core::Formatters::BaseTextFormatter + RSpec::Core::Formatters.register( + self, + :example_group_started, + :example_group_finished, + :example_started, + :example_passed, + :example_pending, + :example_failed + ) + + def initialize(output) + super + @line = [] + end + + def example_group_started(notification) + @line.push(notification.group.description) + end + + def example_group_finished(_notification) + @line.pop + end + + def example_started(notification) + @line.push(notification.example.description) + output_formatted_line('STARTED', :yellow) + end + + def example_passed(_passed) + output_formatted_line('PASSED', :success) + @line.pop + end + + def example_pending(_pending) + output_formatted_line('PENDING', :pending) + @line.pop + end + + def example_failed(_failure) + output_formatted_line('FAILED', :failure) + @line.pop + end + + private + + def output_formatted_line(status, console_code) + prefix = ["[#{Process.pid}]"] + if ENV.include?('TEST_ENV_NUMBER') + test_env_number = ENV['TEST_ENV_NUMBER'] == '' ? 1 : Integer(ENV['TEST_ENV_NUMBER']) + prefix << "[#{test_env_number}]" + end + prefix << RSpec::Core::Formatters::ConsoleCodes.wrap("[#{status}]", console_code) + + output.puts [*prefix, *@line].join(' ') + end +end diff --git a/spec/parallel_tests/rspec/verbose_formatter_spec.rb b/spec/parallel_tests/rspec/verbose_formatter_spec.rb new file mode 100644 index 000000000..a82da567b --- /dev/null +++ b/spec/parallel_tests/rspec/verbose_formatter_spec.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ParallelTests::RSpec::VerboseFormatter do + def run(command) + result = IO.popen(command, err: [:child, :out], &:read) + raise "FAILED: #{result}" unless $?.success? + result + end + + it 'outputs verbose information' do + repo_root = Dir.pwd + + use_temporary_directory do + # setup simple structure + FileUtils.mkdir "spec" + + File.write "spec/foo_spec.rb", <<-RUBY + describe "Foo" do + it "foo" do + sleep 0.5 + expect(true).to be(true) + end + end + RUBY + + File.write "spec/bar_spec.rb", <<-RUBY + describe "Bar" do + it "bar" do + sleep 0.25111 + expect(true).to be(true) + end + end + RUBY + + result = run [ + "ruby", + "#{repo_root}/bin/parallel_rspec", + "-n", "2", + "--", + "--format", "ParallelTests::RSpec::VerboseFormatter", + "--" + ] + + expect(result).to match(/^\[\d+\] \[(1|2)\] \[STARTED\] Foo foo$/) + expect(result).to match(/^\[\d+\] \[(1|2)\] \[PASSED\] Foo foo$/) + expect(result).to match(/^\[\d+\] \[(1|2)\] \[STARTED\] Bar bar$/) + expect(result).to match(/^\[\d+\] \[(1|2)\] \[PASSED\] Bar bar$/) + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index b327c6f45..c9aa11a6a 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,6 +8,7 @@ require 'parallel_tests/test/runtime_logger' require 'parallel_tests/rspec/runtime_logger' require 'parallel_tests/rspec/summary_logger' +require 'parallel_tests/rspec/verbose_formatter' String.class_eval do def strip_heredoc From 14933b000e34e2c1ca3fd54dc4feaa987c3d2686 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 24 Dec 2023 22:08:11 -0600 Subject: [PATCH 176/177] unify verbose formatter with other loggers (#927) * typo * unify verbose formatter with other loggers --- Readme.md | 36 ++++++++++--------- ...verbose_formatter.rb => verbose_logger.rb} | 2 +- ...rmatter_spec.rb => verbose_logger_spec.rb} | 4 +-- spec/spec_helper.rb | 2 +- 4 files changed, 23 insertions(+), 21 deletions(-) rename lib/parallel_tests/rspec/{verbose_formatter.rb => verbose_logger.rb} (93%) rename spec/parallel_tests/rspec/{verbose_formatter_spec.rb => verbose_logger_spec.rb} (91%) diff --git a/Readme.md b/Readme.md index 90d3d4316..b34d1201c 100644 --- a/Readme.md +++ b/Readme.md @@ -151,7 +151,7 @@ Add the following to your `.rspec_parallel` (or `.rspec`) : RSpec: FailuresLogger ----------------------- -Produce pastable command-line snippets for each failed example. For example: +Produce pasteable command-line snippets for each failed example. For example: ```bash rspec /path/to/my_spec.rb:123 # should do something @@ -164,6 +164,24 @@ Add to `.rspec_parallel` or use as CLI flag: (Not needed to retry failures, for that pass [--only-failures](https://relishapp.com/rspec/rspec-core/docs/command-line/only-failures) to rspec) + +RSpec: VerboseLogger +----------------------- + +Prints a single line for starting and finishing each example, to see what is currently running in each process. + +``` +# PID, parallel process number, spec status, example description +[14403] [2] [STARTED] Foo foo +[14402] [1] [STARTED] Bar bar +[14402] [1] [PASSED] Bar bar +``` + +Add to `.rspec_parallel` or use as CLI flag: + + --format ParallelTests::RSpec::VerboseLogger + + Cucumber: FailuresLogger ----------------------- @@ -183,22 +201,6 @@ To rerun failures: cucumber @tmp/cucumber_failures.log -Formatters -========== - -RSpec: VerboseFormatter - -Output the RSpec PID, parallel process number, spec status, and the full -example description. The formatter outputs one line when starting an example -and then again when finishing. Use like the RSpec documentation but plays -nicely with parallel processes. - -Usage: - -```console -$ parallel_rspec -- --format ParallelTests::RSpec::VerboseFormatter -- -``` - Setup for non-rails =================== diff --git a/lib/parallel_tests/rspec/verbose_formatter.rb b/lib/parallel_tests/rspec/verbose_logger.rb similarity index 93% rename from lib/parallel_tests/rspec/verbose_formatter.rb rename to lib/parallel_tests/rspec/verbose_logger.rb index ebd54deda..aa7b8ed29 100644 --- a/lib/parallel_tests/rspec/verbose_formatter.rb +++ b/lib/parallel_tests/rspec/verbose_logger.rb @@ -3,7 +3,7 @@ require 'rspec/core/formatters/base_text_formatter' require 'parallel_tests/rspec/runner' -class ParallelTests::RSpec::VerboseFormatter < RSpec::Core::Formatters::BaseTextFormatter +class ParallelTests::RSpec::VerboseLogger < RSpec::Core::Formatters::BaseTextFormatter RSpec::Core::Formatters.register( self, :example_group_started, diff --git a/spec/parallel_tests/rspec/verbose_formatter_spec.rb b/spec/parallel_tests/rspec/verbose_logger_spec.rb similarity index 91% rename from spec/parallel_tests/rspec/verbose_formatter_spec.rb rename to spec/parallel_tests/rspec/verbose_logger_spec.rb index a82da567b..3fb23c5ae 100644 --- a/spec/parallel_tests/rspec/verbose_formatter_spec.rb +++ b/spec/parallel_tests/rspec/verbose_logger_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -describe ParallelTests::RSpec::VerboseFormatter do +describe ParallelTests::RSpec::VerboseLogger do def run(command) result = IO.popen(command, err: [:child, :out], &:read) raise "FAILED: #{result}" unless $?.success? @@ -39,7 +39,7 @@ def run(command) "#{repo_root}/bin/parallel_rspec", "-n", "2", "--", - "--format", "ParallelTests::RSpec::VerboseFormatter", + "--format", "ParallelTests::RSpec::VerboseLogger", "--" ] diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c9aa11a6a..5e16f9395 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -8,7 +8,7 @@ require 'parallel_tests/test/runtime_logger' require 'parallel_tests/rspec/runtime_logger' require 'parallel_tests/rspec/summary_logger' -require 'parallel_tests/rspec/verbose_formatter' +require 'parallel_tests/rspec/verbose_logger' String.class_eval do def strip_heredoc From 8129c4c6feb6db7f94de144b995ea2a42aae0af5 Mon Sep 17 00:00:00 2001 From: Michael Grosser Date: Sun, 24 Dec 2023 20:09:07 -0800 Subject: [PATCH 177/177] v4.4.0 --- CHANGELOG.md | 12 ++++++++---- Gemfile.lock | 2 +- lib/parallel_tests/version.rb | 2 +- spec/fixtures/rails60/Gemfile.lock | 2 +- spec/fixtures/rails61/Gemfile.lock | 2 +- spec/fixtures/rails70/Gemfile.lock | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb4d63af5..ad013541c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,18 @@ ## Unreleased -- Sort the output of `runtime_logger` for RSpec to show slowest tests first -- Add new `ParallelTests::RSpec::VerboseFormatter` to output detailed - information about each example as it starts and finishes. - ### Breaking Changes ### Added +## 4.4.0 - 2023-12-24 + +### Added + +- Sort the output of `runtime_logger` for RSpec to show slowest tests first +- Add new `ParallelTests::RSpec::VerboseLogger` to output detailed + information about each example and it's process as it starts and finishes. + ## 4.3.0 - 2023-10-08 ### Added diff --git a/Gemfile.lock b/Gemfile.lock index 214675c7e..4128ab2cc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - parallel_tests (4.3.0) + parallel_tests (4.4.0) parallel GEM diff --git a/lib/parallel_tests/version.rb b/lib/parallel_tests/version.rb index e978055ad..0dc75353c 100644 --- a/lib/parallel_tests/version.rb +++ b/lib/parallel_tests/version.rb @@ -1,4 +1,4 @@ # frozen_string_literal: true module ParallelTests - VERSION = '4.3.0' + VERSION = '4.4.0' end diff --git a/spec/fixtures/rails60/Gemfile.lock b/spec/fixtures/rails60/Gemfile.lock index e00dd26eb..6e6f396f2 100644 --- a/spec/fixtures/rails60/Gemfile.lock +++ b/spec/fixtures/rails60/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.3.0) + parallel_tests (4.4.0) parallel GEM diff --git a/spec/fixtures/rails61/Gemfile.lock b/spec/fixtures/rails61/Gemfile.lock index 8055a9d99..ae329a261 100644 --- a/spec/fixtures/rails61/Gemfile.lock +++ b/spec/fixtures/rails61/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.3.0) + parallel_tests (4.4.0) parallel GEM diff --git a/spec/fixtures/rails70/Gemfile.lock b/spec/fixtures/rails70/Gemfile.lock index d8ab9fa78..ee391d673 100644 --- a/spec/fixtures/rails70/Gemfile.lock +++ b/spec/fixtures/rails70/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: ../../.. specs: - parallel_tests (4.3.0) + parallel_tests (4.4.0) parallel GEM