Class: Henitai::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/henitai/runner.rb

Overview

Orchestrates the full mutation testing pipeline.

Pipeline phases (Phase-Gate model):

Gate 1 — Subject selection
  Resolve source files from includes, apply --since filter (incremental),
  build Subject list from AST.

Gate 2 — Mutant generation
  Apply operators to each Subject's AST. Filter arid (non-productive)
  nodes via ignore_patterns. Produces the initial mutant list.

Gate 3 — Static filtering
  Remove ignored mutants (pattern matches), compile-time errors.
  Apply per-test coverage data: mark :no_coverage for uncovered mutants.

Gate 4 — Mutant execution
  Run surviving mutants in isolated child processes (fork isolation).
  Each child process loads the test suite with the mutated method
  injected via Module#define_method. Collect kill/survive/timeout results.

Gate 5 — Reporting
  Write results to configured reporters (terminal, html, json, dashboard).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config: Configuration.load, subjects: nil, since: nil) ⇒ Runner

Returns a new instance of Runner.



31
32
33
34
35
# File 'lib/henitai/runner.rb', line 31

def initialize(config: Configuration.load, subjects: nil, since: nil)
  @config   = config
  @subjects = subjects
  @since    = since
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



29
30
31
# File 'lib/henitai/runner.rb', line 29

def config
  @config
end

#resultObject (readonly)

Returns the value of attribute result.



29
30
31
# File 'lib/henitai/runner.rb', line 29

def result
  @result
end

Instance Method Details

#runResult

Entry point — runs the full pipeline and returns a Result.

Coverage bootstrap (Gate 0) runs in a background thread so that Gate 1 (subject resolution) and Gate 2 (mutant generation) proceed concurrently. The thread is joined before Gate 3 (static filtering), which is the first phase that requires coverage data.

Returns:



45
46
47
48
49
50
51
52
# File 'lib/henitai/runner.rb', line 45

def run
  started_at = Time.now
  source_files = self.source_files
  subjects = resolve_subjects(source_files)
  mutants = execute_mutants(mutants_for(subjects, source_files))

  build_result(mutants, started_at, Time.now)
end