Class: Testprune::Recorder

Inherits:
Object
  • Object
show all
Defined in:
lib/testprune/recorder.rb

Overview

Process-wide singleton that the framework adapters drive. It starts Coverage, snapshots peek_result around each test, and writes run.json when the suite ends.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config) ⇒ Recorder

Returns a new instance of Recorder.



23
24
25
26
27
# File 'lib/testprune/recorder.rb', line 23

def initialize(config)
  @config = config
  @tests  = []
  @framework = nil
end

Instance Attribute Details

#frameworkObject

Returns the value of attribute framework.



29
30
31
# File 'lib/testprune/recorder.rb', line 29

def framework
  @framework
end

Class Method Details

.instanceObject



13
14
15
# File 'lib/testprune/recorder.rb', line 13

def self.instance
  @instance ||= new(Configuration.from_env)
end

.reset!Object

Used in testprune’s own test suite to prevent Recorder state from leaking between test runs (the singleton is normally process-scoped by design).



19
20
21
# File 'lib/testprune/recorder.rb', line 19

def self.reset!
  @instance = nil
end

Instance Method Details

#around(id:, file:, line:, description: nil) ⇒ Object

Bracket a single test (RSpec around(:each)). Minitest uses start_test/ finish_test directly from lifecycle hooks instead, to avoid wrapping #run.



49
50
51
52
53
54
55
56
# File 'lib/testprune/recorder.rb', line 49

def around(id:, file:, line:, description: nil)
  start_test
  begin
    yield
  ensure
    finish_test(id: id, file: file, line: line, description: description)
  end
end

#dumpObject



80
81
82
83
84
85
86
# File 'lib/testprune/recorder.rb', line 80

def dump
  return if @dumped

  @dumped = true
  FileUtils.mkdir_p(@config.output_dir)
  File.write(@config.run_file, JSON.generate(payload))
end

#finish_test(id:, file:, line:, description: nil) ⇒ Object

Record this test’s coverage delta + wall time. Coverage keeps running between tests — the peek_result diff is accurate for serial suites because nothing else executes between start_test and finish_test.



67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/testprune/recorder.rb', line 67

def finish_test(id:, file:, line:, description: nil)
  wall = monotonic - @test_started
  delta = CoverageDelta.compute(@before, Coverage.peek_result, @config)
  @tests << {
    'id'          => id,
    'description' => description || id,
    'file'        => file && File.expand_path(file),
    'line'        => line,
    'wall_time'   => wall,
    'coverage'    => delta
  }
end

#start_coverageObject

Start Coverage with all required options and keep it running for the entire suite. Staying always-on means ‘Coverage.running?` is true before SimpleCov (or any other coverage tool) loads, so they see it already running and skip their own `Coverage.start` call — no guard needed in test_helper.rb. Per-test footprints are captured by diffing `peek_result` snapshots before and after each test; `peek_result` is non-destructive so SimpleCov’s final ‘Coverage.result` call at suite end still gets the full aggregate unaffected.



39
40
41
42
43
44
45
# File 'lib/testprune/recorder.rb', line 39

def start_coverage
  return if @started

  Coverage.setup(lines: true, branches: true, methods: true)
  Coverage.resume
  @started = true
end

#start_testObject

Snapshot coverage counts before the test begins.



59
60
61
62
# File 'lib/testprune/recorder.rb', line 59

def start_test
  @before = Coverage.peek_result
  @test_started = monotonic
end