Skip to content

Fork-parallel reports should need zero developer setup #258

Description

@pftg

Retargeted to 2.0 under ADR-010 (2.0 carries the features; 2.1 carries the deletions).

Problem

Under Rails' default parallelize(workers: N), the HTML report is not written and the [snap_diff] summary line is not printed. Minitest skips after_run hooks in forked children (allow_fork = false, minitest.rb:64; guard next if !Minitest.allow_fork && Process.pid != pid at :79), so the workers holding the results never finalize, and the parent that does finalize recorded nothing.

Measured with a real harness (8 classes × 8 tests, committed baselines, the real gem from namer through reporter), 10/10 runs: report=NO, ledger_pids=5 — four workers hold 16 records each and never finalize.

Pass/fail is correct throughout (failures marshal back over DRb) and every on-disk artifact survives. Only the HTML index and the summary line are lost.

docs/reporters.md now documents a manual workaround (#252), but boilerplate in every consuming app is the wrong shape: nobody pastes it, and the failure is silent. ActiveSupport.test_parallelization_threshold defaults to 50, so a suite silently starts losing its report the day someone adds the 51st test.

The seams already exist

Verified against activesupport 8.1.3.1 — both run inside the worker:

  • ActiveSupport::Testing::Parallelization.after_fork_hookparallelization.rb:22, invoked at worker.rb:24
  • ActiveSupport::Testing::Parallelization.run_cleanup_hookparallelization.rb:30, invoked at worker.rb:31

Checklist

  • after_fork_hook — give each worker a record sink keyed by pid
  • run_cleanup_hook — flush that worker's records before it exits
  • Parent's existing Minitest.after_run merges the fragments into one report at the documented path, then removes them
  • Feature-detect — register only when ActiveSupport::Testing::Parallelization is defined; the gem must keep working without Rails
  • Guard the two modes that work TODAY so they cannot regress: serial, and parallelize(with: :threads) (verified correct — same failures and counts as serial, only entry order differs)
  • Do not use save_path as the per-worker lever. config.screenshot_area derives from it (config.rb:143-148), so a per-worker save_path points every comparison at an empty baseline directory and records everything as new. The per-worker path must be the report output path only
  • Serialization format for assertion records — internal and boring
  • Prove it: run the harness repeatedly (a 1-in-5 race is still a bug), show all failures preserved across workers
  • Update docs/reporters.md — the manual workaround becomes a fallback, not the answer

Out of scope

Separate-process runners (parallel_tests, RSpec, CI sharding), where each process finalizes correctly and the last writer wins. Different problem; the current docs describe it accurately.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions