From 9e1ab3a4d725ae24a2448b9b010ba4c4987ca592 Mon Sep 17 00:00:00 2001 From: Johannes Vetter Date: Thu, 8 May 2025 12:56:07 -0700 Subject: [PATCH 1/6] The --specify-groups option supports to read from STDIN --- Readme.md | 3 +- lib/parallel_tests/grouper.rb | 9 +- spec/parallel_tests/grouper_spec.rb | 138 ++++++++++++++++++++-------- 3 files changed, 112 insertions(+), 38 deletions(-) diff --git a/Readme.md b/Readme.md index 9c6480ca..09e1444d 100644 --- a/Readme.md +++ b/Readme.md @@ -258,7 +258,8 @@ Options are: --failure-exit-code INT Specify the exit code to use when tests fail --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. If SPECS is a `-` the actual value for this + option is read from STDIN instead. 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 diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index 44402764..bd3c9d87 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -48,8 +48,15 @@ def in_even_groups_by_size(items, num_groups, options = {}) private + def specified_groups(options) + groups = options[:specify_groups] + return groups if groups != '-' + + $stdin.gets + end + def specify_groups(items, num_groups, options, groups) - specify_test_process_groups = options[:specify_groups].split('|') + specify_test_process_groups = specified_groups(options).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 diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index 57f0764c..ca18e143 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -76,50 +76,116 @@ def call(num_groups, options = {}) ) 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 + context 'with specific groups provided directly' do + 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 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 "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 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 doesn't 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 selected files & folders" - ) - end + 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( + "Could not find [\"6\"] from --specify-groups in the selected files & folders" + ) + end - 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( - "Could not find [\"6\"] from --specify-groups in the selected files & folders" - ) - end + 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( + "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 specs that aren't run:\n\["4", "5"\]/) + 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 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 + expect(call(3, specify_groups: '1,2|3,4|5')).to eq([["1", "2"], ["3", "4"], ["5"]]) + end 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"]]) + context 'with specific groups provided through STDIN' do + it "groups specify_groups as specified when specify_groups is just one spec" do + allow($stdin).to receive(:gets).and_return('1') + + expect(call(3, specify_groups: '-')).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 + allow($stdin).to receive(:gets).and_return('3,1') + + expect(call(3, specify_groups: '-')).to eq([["3", "1"], ["5"], ["2", "4"]]) + end + + it "groups specify_groups as specified when specify_groups is multiple specs" do + allow($stdin).to receive(:gets).and_return('1,2|4') + + expect(call(3, specify_groups: '-')).to eq([["1", "2"], ["4"], ["3", "5"]]) + end + + it "specify_groups aborts when number of specs separated by pipe is out of bounds" do + allow($stdin).to receive(:gets).and_return('1|2|3|4') + + expect do + call(3, specify_groups: '-') + 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 doesn't match existing specs" do + allow($stdin).to receive(:gets).and_return('1|2|6') + + expect do + call(3, specify_groups: '-') + end.to raise_error( + "Could not find [\"6\"] from --specify-groups in the selected files & folders" + ) + end + + it "specify_groups aborts when spec passed in doesn't match existing specs again" do + allow($stdin).to receive(:gets).and_return('1,6|2') + + expect do + call(3, specify_groups: '-') + end.to raise_error( + "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 + allow($stdin).to receive(:gets).and_return('1|2|3') + + expect do + call(3, specify_groups: '-') + 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 + allow($stdin).to receive(:gets).and_return('1,2|3,4|5') + + expect(call(3, specify_groups: '-')).to eq([["1", "2"], ["3", "4"], ["5"]]) + end end end From 90937f9c7df0a8553cea189eeb9d790a984e7e2f Mon Sep 17 00:00:00 2001 From: Johannes Vetter Date: Thu, 8 May 2025 13:55:08 -0700 Subject: [PATCH 2/6] Add entry to Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c34e040..e9065fed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +- The `specify-groups` option supports to read from STDIN when set to `-` + ### Breaking Changes ### Added From d905e963592be47a568a00ca27fc0b219901a811 Mon Sep 17 00:00:00 2001 From: Johannes Vetter Date: Thu, 8 May 2025 15:52:34 -0700 Subject: [PATCH 3/6] Improve language --- CHANGELOG.md | 2 +- Readme.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9065fed..8e2058db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased -- The `specify-groups` option supports to read from STDIN when set to `-` +- The `specify-groups` option supports reading from STDIN when set to `-` ### Breaking Changes diff --git a/Readme.md b/Readme.md index 09e1444d..1943f8f7 100644 --- a/Readme.md +++ b/Readme.md @@ -258,7 +258,7 @@ Options are: --failure-exit-code INT Specify the exit code to use when tests fail --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. If SPECS is a `-` the actual value for this + pipes indicate specs in a new process. If SPECS is a `-` the value for this option is read from STDIN instead. Cannot use with --single, --isolate, or --isolate-n. Ex. $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb' From f698218aff656d0cd7f2c803073415f8d49863f8 Mon Sep 17 00:00:00 2001 From: Johannes Vetter Date: Thu, 8 May 2025 15:52:50 -0700 Subject: [PATCH 4/6] Use read instead of gets and ensure to chomp the trailling newlines --- lib/parallel_tests/grouper.rb | 2 +- spec/parallel_tests/grouper_spec.rb | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/parallel_tests/grouper.rb b/lib/parallel_tests/grouper.rb index bd3c9d87..b444a5e6 100644 --- a/lib/parallel_tests/grouper.rb +++ b/lib/parallel_tests/grouper.rb @@ -52,7 +52,7 @@ def specified_groups(options) groups = options[:specify_groups] return groups if groups != '-' - $stdin.gets + $stdin.read.chomp end def specify_groups(items, num_groups, options, groups) diff --git a/spec/parallel_tests/grouper_spec.rb b/spec/parallel_tests/grouper_spec.rb index ca18e143..0240c066 100644 --- a/spec/parallel_tests/grouper_spec.rb +++ b/spec/parallel_tests/grouper_spec.rb @@ -126,25 +126,25 @@ def call(num_groups, options = {}) context 'with specific groups provided through STDIN' do it "groups specify_groups as specified when specify_groups is just one spec" do - allow($stdin).to receive(:gets).and_return('1') + allow($stdin).to receive(:read).and_return("1\n") expect(call(3, specify_groups: '-')).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 - allow($stdin).to receive(:gets).and_return('3,1') + allow($stdin).to receive(:read).and_return("3,1\n") expect(call(3, specify_groups: '-')).to eq([["3", "1"], ["5"], ["2", "4"]]) end it "groups specify_groups as specified when specify_groups is multiple specs" do - allow($stdin).to receive(:gets).and_return('1,2|4') + allow($stdin).to receive(:read).and_return("1,2|4\n") expect(call(3, specify_groups: '-')).to eq([["1", "2"], ["4"], ["3", "5"]]) end it "specify_groups aborts when number of specs separated by pipe is out of bounds" do - allow($stdin).to receive(:gets).and_return('1|2|3|4') + allow($stdin).to receive(:read).and_return("1|2|3|4\n") expect do call(3, specify_groups: '-') @@ -154,7 +154,7 @@ def call(num_groups, options = {}) end it "specify_groups aborts when spec passed in doesn't match existing specs" do - allow($stdin).to receive(:gets).and_return('1|2|6') + allow($stdin).to receive(:read).and_return("1|2|6\n") expect do call(3, specify_groups: '-') @@ -164,7 +164,7 @@ def call(num_groups, options = {}) end it "specify_groups aborts when spec passed in doesn't match existing specs again" do - allow($stdin).to receive(:gets).and_return('1,6|2') + allow($stdin).to receive(:read).and_return("1,6|2\n") expect do call(3, specify_groups: '-') @@ -174,7 +174,7 @@ def call(num_groups, options = {}) end it "specify_groups aborts when number of specs is equal to number passed in" do - allow($stdin).to receive(:gets).and_return('1|2|3') + allow($stdin).to receive(:read).and_return("1|2|3\n") expect do call(3, specify_groups: '-') @@ -182,7 +182,7 @@ def call(num_groups, options = {}) end it "specify_groups does not abort when the every single spec is specified in it" do - allow($stdin).to receive(:gets).and_return('1,2|3,4|5') + allow($stdin).to receive(:read).and_return("1,2|3,4|5\n") expect(call(3, specify_groups: '-')).to eq([["1", "2"], ["3", "4"], ["5"]]) end From 5308c8048ecb39e9f6e6b20e4967aadc24677288 Mon Sep 17 00:00:00 2001 From: Johannes Vetter Date: Thu, 8 May 2025 15:54:41 -0700 Subject: [PATCH 5/6] Also update the CLI parser's help --- lib/parallel_tests/cli.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/parallel_tests/cli.rb b/lib/parallel_tests/cli.rb index 56b51dbc..23dbca41 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -254,7 +254,8 @@ def parse_options!(argv) <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") 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. If SPECS is a `-` the value for this + option is read from STDIN instead. 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 From dd40e135044a02754fd784f1f48ea130869066ab Mon Sep 17 00:00:00 2001 From: Johannes Vetter Date: Thu, 8 May 2025 15:55:32 -0700 Subject: [PATCH 6/6] Don't use backticks --- 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 23dbca41..7bebffcd 100644 --- a/lib/parallel_tests/cli.rb +++ b/lib/parallel_tests/cli.rb @@ -254,7 +254,7 @@ def parse_options!(argv) <<~TEXT.rstrip.split("\n").join("\n#{newline_padding}") 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. If SPECS is a `-` the value for this + pipes indicate specs in a new process. If SPECS is a '-' the value for this option is read from STDIN instead. Cannot use with --single, --isolate, or --isolate-n. Ex. $ parallel_tests -n 3 . --specify-groups '1_spec.rb,2_spec.rb|3_spec.rb'