Class: Henitai::TestPrioritizer

Inherits:
Object
  • Object
show all
Defined in:
lib/henitai/test_prioritizer.rb,
sig/henitai.rbs

Overview

Orders test files so previously effective tests run first.

Primary key: kill-history count (a test that killed neighbouring mutants probably kills this one). Tiebreaker: measured per-test-file runtime, ascending, so the first kill costs as little wall-clock as possible. Untimed tests sort after timed ones by original inventory order; with no timing source at all the ordering is exactly the historical behavior.

Instance Method Summary collapse

Constructor Details

#initialize(timing_source: nil) ⇒ TestPrioritizer

Returns a new instance of TestPrioritizer.

Parameters:

  • timing_source (#call, nil) (defaults to: nil)

    returns a Hash of test file path to wall-clock seconds; resolved lazily on first sort.

  • timing_source: (Object, nil) (defaults to: nil)


14
15
16
# File 'lib/henitai/test_prioritizer.rb', line 14

def initialize(timing_source: nil)
  @timing_source = timing_source
end

Instance Method Details

#runtime(test) ⇒ Float

Parameters:

  • (Object)

Returns:

  • (Float)


26
27
28
29
30
31
32
33
34
# File 'lib/henitai/test_prioritizer.rb', line 26

def runtime(test)
  durations = timing_durations
  history_key_candidates(test).each do |key|
    value = durations[key]
    return value.to_f unless value.nil?
  end

  Float::INFINITY
end

#sort(tests, _mutant, history) ⇒ Array[String]

Parameters:

  • (Array[String])
  • (Object)
  • (Hash[untyped, untyped])

Returns:

  • (Array[String])


18
19
20
21
22
# File 'lib/henitai/test_prioritizer.rb', line 18

def sort(tests, _mutant, history)
  Array(tests).each_with_index.sort_by do |test, index|
    [-history_count(history, test), runtime(test), index]
  end.map(&:first)
end

#timing_durationsHash[String, untyped]

Returns:

  • (Hash[String, untyped])


36
37
38
# File 'lib/henitai/test_prioritizer.rb', line 36

def timing_durations
  @timing_durations ||= @timing_source&.call || {}
end