Class: Mutineer::MinitestIntegration
- Inherits:
-
Object
- Object
- Mutineer::MinitestIntegration
- Defined in:
- lib/mutineer/minitest_integration.rb,
lib/mutineer/minitest_integration/stop_at_first_failure.rb
Overview
Child-process-only: loads a test file in the current process and runs it programmatically, returning an exit status integer (0 = all passed, 1 = any failure/error).
Never call this in the parent — it manipulates global Minitest state (autorun, runnables) that only makes sense in a throwaway forked child.
A missing minitest is rescued as FrameworkUnavailable (Isolation.run still turns that raise into exit 2). There is no rescue around the suite run itself: Isolation.run's fork block is the single exception boundary for unexpected errors. Swallowing those here would create a second exit-2 path and break this method's 0/1 return contract.
Defined Under Namespace
Modules: StopAtFirstFailure
Constant Summary collapse
- STOP_AT_FIRST_FAILURE_SEED =
The seed of a run that stops at the first failure, unless
SEEDis set. With the stop, the test order can decidekilledvstimeout; a fixed order keeps the verdict stable for a--baselinegate. 1
Class Method Summary collapse
-
.run(test_files, stop_at_first_failure: false) ⇒ Integer
Tested via runner_test.rb, not in isolation — a direct unit test would require forking and duplicate isolation_test's coverage.
Class Method Details
.run(test_files, stop_at_first_failure: false) ⇒ Integer
Tested via runner_test.rb, not in isolation — a direct unit test would require forking and duplicate isolation_test's coverage.
test_files is one path or an Array of paths (coverage selection
passes the covering subset); each is loaded before the single
Minitest.run.
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/mutineer/minitest_integration.rb', line 35 def self.run(test_files, stop_at_first_failure: false) begin require "minitest" rescue LoadError raise Mutineer::FrameworkUnavailable, "minitest is not available — add minitest to the project under test, " \ "or use --framework rspec" end # minitest is required LAZILY (never at load time) so Mutineer keeps # zero runtime gem deps and loads fine in an rspec-only project; a missing # minitest raises a clear Mutineer error rather than a LoadError backtrace. # Neutralise autorun so a test file's `require "minitest/autorun"` # registers no at_exit hook. def Minitest.autorun; end # rubocop:disable Lint/NestedMethodDefinition # Drop runnables inherited from the parent suite (this is the child's # private copy — the parent is unaffected) so only the target test runs. Minitest::Runnable.reset Array(test_files).each { |f| load f } args = [] if stop_at_first_failure && StopAtFirstFailure.arm!(Minitest::Runnable.runnables) # Pin the seed only when the stop is armed; an unknown Minitest shape # gets the normal full, randomly ordered run. args = ["--seed", STOP_AT_FIRST_FAILURE_SEED.to_s] unless ENV["SEED"] end # No silencing here: the fork boundary that calls this method has already # pointed stdout at File::NULL (see ChildStdout). passed = Minitest.run(args) # A plugin can replace the summary reporter, so a stop decides by itself. passed && !StopAtFirstFailure.stopped_here? ? 0 : 1 ensure StopAtFirstFailure.disarm! end |