Module: Evilution::Integration::Loading::TestLoadPath Private

Defined in:
lib/evilution/integration/loading/test_load_path.rb

Overview

This module is part of a private API. You should avoid using this module if possible, as it may be removed or be changed in the future.

Mirrors ruby -Itest / -Ispec for in-process test loading.

evilution loads resolved test files with Kernel#load instead of shelling out, so the -Itest shown in the displayed command string is never actually applied to $LOAD_PATH. Minitest and Test::Unit suites near-universally require "test_helper" (which the suite's own runner satisfies via -Itest); without the test root on $LOAD_PATH that bare require raises LoadError and every mutation errors with score 0.0 (EV-52hf / GH #1326).

Anchors against Evilution.project_base_dir, which resolves to PROJECT_ROOT inside an isolated worker (EV-wqxu / GH #1278) and Dir.pwd otherwise, so the same call works on both the baseline (parent) and mutation (child) paths.

Constant Summary collapse

ROOT_NAMES =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

%w[test spec].freeze

Class Method Summary collapse

Class Method Details

.add!(files, base: Evilution.project_base_dir) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Prepend every relevant test directory to $LOAD_PATH (idempotently). Iterate in reverse so the first entry from #dirs_for ends up frontmost, preserving its order (mirrors how ruby -Ia -Ib lands a before b).



25
26
27
28
29
# File 'lib/evilution/integration/loading/test_load_path.rb', line 25

def add!(files, base: Evilution.project_base_dir)
  dirs_for(files, base).reverse_each do |dir|
    $LOAD_PATH.unshift(dir) unless $LOAD_PATH.include?(dir)
  end
end

.conventional_roots(base) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



54
55
56
# File 'lib/evilution/integration/loading/test_load_path.rb', line 54

def conventional_roots(base)
  ROOT_NAMES.map { |name| File.join(base, name) }
end

.dirs_for(files, base) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

The directories to put on $LOAD_PATH for the given resolved test files: the conventional test/ and spec/ roots under base, each file's own directory, and the topmost test/spec ancestor of each file (covers nested layouts like test/unit, spec/lib, spec/unit). Existing directories only, and only those inside the project base -- never a broad outside-project dir (e.g. a /tmp test file), which would over-widen $LOAD_PATH for the whole process (the baseline runs in the long-lived parent).



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/evilution/integration/loading/test_load_path.rb', line 38

def dirs_for(files, base)
  base = File.expand_path(base)
  dirs = conventional_roots(base)
  Array(files).each do |file|
    file_dir = File.dirname(File.expand_path(file, base))
    dirs << file_dir
    root = root_ancestor(file_dir, base)
    dirs << root if root
  end
  dirs.uniq.select { |dir| File.directory?(dir) && within?(dir, base) }
end

.root_ancestor(dir, base) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Walk from dir up to base, returning the highest ancestor whose basename is a conventional test root (test/spec). Highest, so test/unit/foo_test.rb yields test (matching -Itest), not the intermediate test/unit.



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/evilution/integration/loading/test_load_path.rb', line 61

def root_ancestor(dir, base)
  base = File.expand_path(base)
  found = nil
  current = File.expand_path(dir)
  loop do
    found = current if ROOT_NAMES.include?(File.basename(current))
    break if current == base

    parent = File.dirname(current)
    break if parent == current

    current = parent
  end
  found
end

.within?(dir, base) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns:

  • (Boolean)


50
51
52
# File 'lib/evilution/integration/loading/test_load_path.rb', line 50

def within?(dir, base)
  dir == base || dir.start_with?("#{base}/")
end