Skip to content

Commit 019c973

Browse files
authored
Fix pending parallel tests (heroku#1606)
The `in_directory_fork` runs a test in a sub-process, which does not play well with the combination of parallel split test and rspec "around" callback. It results in tests not being run. Wrapping tests manually fixes the problem: Before ``` $ bundle exec parallel_split_test spec/helpers/rails_runner_spec.rb Pending: (Failures listed here are expected and do not affect your suite's status) 1) Rails Runner calls run through child object # around hook at ./spec/helpers/rails_runner_spec.rb:4 did not execute the example # ./spec/helpers/rails_runner_spec.rb:31 Finished in 3.21 seconds (files took 0.40941 seconds to load) 1 example, 0 failures, 1 pending * Pending: (Failures listed here are expected and do not affect your suite's status) 1) Rails Runner config objects build propperly formatted commands # around hook at ./spec/helpers/rails_runner_spec.rb:4 did not execute the example # ./spec/helpers/rails_runner_spec.rb:18 Finished in 3.23 seconds (files took 0.40016 seconds to load) 1 example, 0 failures, 1 pending -----> Detecting rails configuration * Pending: (Failures listed here are expected and do not affect your suite's status) 1) Rails Runner failure in one task does not cause another to fail # around hook at ./spec/helpers/rails_runner_spec.rb:4 did not execute the example # ./spec/helpers/rails_runner_spec.rb:71 Finished in 3.49 seconds (files took 0.40116 seconds to load) 1 example, 0 failures, 1 pending -----> Detecting rails configuration * Pending: (Failures listed here are expected and do not affect your suite's status) 1) Rails Runner does not fail when there is an invalid byte sequence # around hook at ./spec/helpers/rails_runner_spec.rb:4 did not execute the example # ./spec/helpers/rails_runner_spec.rb:82 Finished in 3.59 seconds (files took 0.40143 seconds to load) 1 example, 0 failures, 1 pending -----> Detecting rails configuration * Pending: (Failures listed here are expected and do not affect your suite's status) 1) Rails Runner calls a mock interface # around hook at ./spec/helpers/rails_runner_spec.rb:4 did not execute the example # ./spec/helpers/rails_runner_spec.rb:45 Finished in 3.68 seconds (files took 0.40462 seconds to load) 1 example, 0 failures, 1 pending Summary: 1 example, 0 failures, 1 pending 1 example, 0 failures, 1 pending 1 example, 0 failures, 1 pending 1 example, 0 failures, 1 pending 1 example, 0 failures, 1 pending 1 example, 0 failures, 1 pending ``` After ``` $ bundle exec parallel_split_test spec/helpers/rails_runner_spec.rb Summary: 1 example, 0 failures 1 example, 0 failures 1 example, 0 failures 1 example, 0 failures 1 example, 0 failures 1 example, 0 failures 0 examples, 0 failures 0 examples, 0 failures 0 examples, 0 failures 0 examples, 0 failures 0 examples, 0 failures 0 examples, 0 failures Took 3.10 seconds with 12 processes ```
1 parent 0a551ff commit 019c973

1 file changed

Lines changed: 56 additions & 44 deletions

File tree

spec/helpers/rails_runner_spec.rb

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,91 +1,103 @@
11
require 'spec_helper'
22

33
describe "Rails Runner" do
4-
around(:each) do |test|
4+
def isolate(&block)
55
# Process and disk isolation
66
Hatchet::App.new("default_ruby").in_directory_fork do
77
original_path = ENV["PATH"]
88
ENV["PATH"] = "./bin/:#{ENV['PATH']}"
99

1010
Dir.mktmpdir do |tmpdir|
1111
Dir.chdir(tmpdir) do
12-
test.run
12+
block.call
1313
end
1414
end
1515
end
1616
end
1717

1818
it "config objects build propperly formatted commands" do
19-
rails_runner = LanguagePack::Helpers::RailsRunner.new
20-
local_storage = rails_runner.detect("active_storage.service")
19+
isolate do
20+
rails_runner = LanguagePack::Helpers::RailsRunner.new
21+
local_storage = rails_runner.detect("active_storage.service")
2122

22-
expected = 'rails runner "begin; puts %Q{heroku.detecting.config.for.active_storage.service=#{Rails.application.config.try(:active_storage).try(:service)}}; rescue => e; end;"'
23-
expect(rails_runner.command).to eq(expected)
23+
expected = 'rails runner "begin; puts %Q{heroku.detecting.config.for.active_storage.service=#{Rails.application.config.try(:active_storage).try(:service)}}; rescue => e; end;"'
24+
expect(rails_runner.command).to eq(expected)
2425

25-
rails_runner.detect("assets.compile")
26+
rails_runner.detect("assets.compile")
2627

27-
expected = 'rails runner "begin; puts %Q{heroku.detecting.config.for.active_storage.service=#{Rails.application.config.try(:active_storage).try(:service)}}; rescue => e; end; begin; puts %Q{heroku.detecting.config.for.assets.compile=#{Rails.application.config.try(:assets).try(:compile)}}; rescue => e; end;"'
28-
expect(rails_runner.command).to eq(expected)
28+
expected = 'rails runner "begin; puts %Q{heroku.detecting.config.for.active_storage.service=#{Rails.application.config.try(:active_storage).try(:service)}}; rescue => e; end; begin; puts %Q{heroku.detecting.config.for.assets.compile=#{Rails.application.config.try(:assets).try(:compile)}}; rescue => e; end;"'
29+
expect(rails_runner.command).to eq(expected)
30+
end
2931
end
3032

3133
it "calls run through child object" do
32-
rails_runner = LanguagePack::Helpers::RailsRunner.new
33-
def rails_runner.call; @called ||= 0 ; @called += 1; "" end
34-
def rails_runner.called; @called; end
34+
isolate do
35+
rails_runner = LanguagePack::Helpers::RailsRunner.new
36+
def rails_runner.call; @called ||= 0 ; @called += 1; "" end
37+
def rails_runner.called; @called; end
3538

36-
local_storage = rails_runner.detect("active_storage.service")
37-
local_storage.success?
38-
expect(rails_runner.called).to eq(1)
39+
local_storage = rails_runner.detect("active_storage.service")
40+
local_storage.success?
41+
expect(rails_runner.called).to eq(1)
3942

40-
local_storage.success?
41-
local_storage.did_match?("foo")
42-
expect(rails_runner.called).to eq(1)
43+
local_storage.success?
44+
local_storage.did_match?("foo")
45+
expect(rails_runner.called).to eq(1)
46+
end
4347
end
4448

4549
it "calls a mock interface" do
46-
mock_rails_runner
47-
expect(File.executable?("bin/rails")).to eq(true)
50+
isolate do
51+
mock_rails_runner
52+
expect(File.executable?("bin/rails")).to eq(true)
4853

49-
rails_runner = LanguagePack::Helpers::RailsRunner.new
50-
local_storage = rails_runner.detect("active_storage.service")
51-
local_storage = rails_runner.detect("foo.bar")
54+
rails_runner = LanguagePack::Helpers::RailsRunner.new
55+
local_storage = rails_runner.detect("active_storage.service")
56+
local_storage = rails_runner.detect("foo.bar")
5257

53-
expect(rails_runner.output).to match("heroku.detecting.config.for.active_storage.service=active_storage.service")
54-
expect(rails_runner.output).to match("heroku.detecting.config.for.foo.bar=foo.bar")
55-
expect(rails_runner.success?).to be(true)
58+
expect(rails_runner.output).to match("heroku.detecting.config.for.active_storage.service=active_storage.service")
59+
expect(rails_runner.output).to match("heroku.detecting.config.for.foo.bar=foo.bar")
60+
expect(rails_runner.success?).to be(true)
61+
end
5662
end
5763

5864
it "timeout works as expected" do
59-
mock_rails_runner("pid = Process.spawn('sleep 5'); Process.wait(pid)")
65+
isolate do
66+
mock_rails_runner("pid = Process.spawn('sleep 5'); Process.wait(pid)")
67+
68+
diff = time_it do
69+
rails_runner = LanguagePack::Helpers::RailsRunner.new(false, 0.01)
70+
local_storage = rails_runner.detect("active_storage.service")
71+
expect(rails_runner.success?).to eq(false)
72+
expect(rails_runner.timeout?).to eq(true)
73+
end
6074

61-
diff = time_it do
62-
rails_runner = LanguagePack::Helpers::RailsRunner.new(false, 0.01)
63-
local_storage = rails_runner.detect("active_storage.service")
64-
expect(rails_runner.success?).to eq(false)
65-
expect(rails_runner.timeout?).to eq(true)
75+
expect(diff < 1).to eq(true), "expected time difference #{diff} to be less than 1 second, but was longer"
6676
end
67-
68-
expect(diff < 1).to eq(true), "expected time difference #{diff} to be less than 1 second, but was longer"
6977
end
7078

7179
it "failure in one task does not cause another to fail" do
72-
mock_rails_runner('raise "bad" if value == :bad')
80+
isolate do
81+
mock_rails_runner('raise "bad" if value == :bad')
7382

74-
rails_runner = LanguagePack::Helpers::RailsRunner.new(false, 1)
75-
bad_value = rails_runner.detect("bad.value")
76-
local_storage = rails_runner.detect("active_storage.service")
83+
rails_runner = LanguagePack::Helpers::RailsRunner.new(false, 1)
84+
bad_value = rails_runner.detect("bad.value")
85+
local_storage = rails_runner.detect("active_storage.service")
7786

78-
expect(!!bad_value.success?).to eq(false)
79-
expect(!!local_storage.success?).to eq(true)
87+
expect(!!bad_value.success?).to eq(false)
88+
expect(!!local_storage.success?).to eq(true)
89+
end
8090
end
8191

8292
it "does not fail when there is an invalid byte sequence" do
83-
mock_rails_runner('puts "hi \255"')
93+
isolate do
94+
mock_rails_runner('puts "hi \255"')
8495

85-
rails_runner = LanguagePack::Helpers::RailsRunner.new
86-
local_storage = rails_runner.detect("active_storage.service")
96+
rails_runner = LanguagePack::Helpers::RailsRunner.new
97+
local_storage = rails_runner.detect("active_storage.service")
8798

88-
expect(local_storage.success?).to be_truthy
99+
expect(local_storage.success?).to be_truthy
100+
end
89101
end
90102

91103
def time_it

0 commit comments

Comments
 (0)