minitest-fork_executor 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b399f50e3a52b2505c2125113c05ab712b1db59d26f00dd1075d7be2346c979b
4
+ data.tar.gz: a3394aab364af126482879b30badfd400ab2168185b1e746305555c42ef84ff2
5
+ SHA512:
6
+ metadata.gz: b6014495cb3f12a88165cb983533be9a9b2f4e3188cbb67fa2e355577de3af285fc0ea6bf575e82e194d2526bedfa25ef979482be9377d96e1ca67082994a211
7
+ data.tar.gz: d887d4b98c08f8c7ba5e5c41687b88875ea431c9dd4ea0fbf5cb546947a524c6326ea5212519c98dcf3c91bceb417cc8feaeb04c1ef6e00cf6face124e8fef62
@@ -0,0 +1,48 @@
1
+ module Minitest
2
+ class ForkExecutor
3
+ def start
4
+ # Minitest runs test cases via Minitest.run_one_method. Each test case
5
+ # in a test class is run separately. We need to override that method and
6
+ # fork there. run_one_method is a method on the Minitest module so we need
7
+ # to *prepend* our version so that it's called first.
8
+ metaclass = (class << Minitest; self; end)
9
+ metaclass.prepend ClassMethods
10
+ end
11
+
12
+ def shutdown
13
+ # Nothing to do here but required by Minitest.
14
+ end
15
+
16
+ module ClassMethods
17
+ # The updated version of Minitest.run_one_method that forks before
18
+ # actually running a test case, makes the child run it and send the result
19
+ # to the parent process.
20
+ def run_one_method klass, method_name
21
+ read_io, write_io = IO.pipe
22
+ read_io.binmode
23
+ write_io.binmode
24
+
25
+ if fork
26
+ # Parent: load the result sent from the child
27
+
28
+ write_io.close
29
+ result = Marshal.load(read_io)
30
+ read_io.close
31
+
32
+ Process.wait
33
+ else
34
+ # Child: just run normally, dump the result, and exit the process to
35
+ # avoid double-reporting.
36
+ result = super
37
+
38
+ read_io.close
39
+ Marshal.dump(result, write_io)
40
+ write_io.close
41
+ exit
42
+ end
43
+
44
+ result
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ require 'tempfile'
2
+
3
+ require 'minitest/autorun'
4
+ require 'minitest/fork_executor'
5
+
6
+ Minitest.parallel_executor = Minitest::ForkExecutor.new
7
+
8
+ # This test may seem to be more complicated than necessary but it's actually
9
+ # not. If we had only one test method then an implementation that forked an
10
+ # run *all* tests in the fork would pass the test.
11
+ #
12
+ # We need to ensure that:
13
+ #
14
+ # 1. Different test methods are run in different processes - hence two tests.
15
+ # 2. These processes are different from the parent process that spawned the
16
+ # test suite - hence recording @@parent_pid at the top.
17
+ class ForkTest < Minitest::Test
18
+ @@log = Tempfile.new
19
+ @@parent_pid = Process.pid
20
+
21
+ def test_run_in_process_one
22
+ log_and_assert
23
+ end
24
+
25
+ def test_run_in_process_two
26
+ log_and_assert
27
+ end
28
+
29
+ private
30
+
31
+ def log_and_assert
32
+ @@log.seek(0, IO::SEEK_END)
33
+ @@log.write("#{Process.pid}\n")
34
+ @@log.rewind
35
+
36
+ pids = @@log.readlines.map(&:chop).map(&:to_i)
37
+ if pids.count == 2
38
+ assert_equal 2, pids.uniq.count
39
+ refute pids.include?(@@parent_pid)
40
+ end
41
+ end
42
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: minitest-fork_executor
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Greg Navis
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-01-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: minitest
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Run each test_* method in a separate process thus eliminating test case
42
+ interference.
43
+ email: contact@gregnavis.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/minitest/fork_executor.rb
49
+ - test/minitest/fork_executor_test.rb
50
+ homepage: https://github.com/gregnavis/minitest-fork_executor
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubygems_version: 3.0.1
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: Near-perfect process-level test case isolation.
73
+ test_files:
74
+ - test/minitest/fork_executor_test.rb