Class: Verity::Runner

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

Overview

Public: Executes tests, fires reporter hooks, and records results back to the manifest. A single Runner instance services one worker process.

Defined Under Namespace

Classes: Result

Constant Summary collapse

CONFLICT_RETRY_INTERVAL =
0.05

Instance Method Summary collapse

Constructor Details

#initialize(reporter: nil) ⇒ Runner

Public: Create a new Runner.

reporter - Object implementing Verity::Reporter (default: from configuration).



19
20
21
# File 'lib/verity/runner.rb', line 19

def initialize(reporter: nil)
  @reporter = reporter || Verity.configuration.reporter
end

Instance Method Details

#run(tests = Registry.all) ⇒ Object

Public: Run a list of tests in-process without a manifest. Primarily used for simple single-worker execution.

tests - Array of Verity::Test (default: all registered tests).

Returns true if every test passed.



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

def run(tests = Registry.all)
  run_worker(tests, worker_id: 0)
end

#run_manifest(manifest, worker_id:) ⇒ Object

Public: Claim and execute tests from a shared manifest until none remain. Fires before_worker_start hooks, then loops claim_next until exhausted. When resource resolvers are registered, builds a conflict exclusion list before each claim and sleeps briefly when blocked by running tests.

manifest - A Verity::Manifest instance. worker_id - Integer identifying this worker.

Returns true if every executed test passed.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/verity/runner.rb', line 44

def run_manifest(manifest, worker_id:)
  Verity.hooks[:before_worker_start].each(&:call)

  @reporter.on_run_start(total: manifest.example_count, worker_id: worker_id)

  results = []
  loop do
    claimed = next_claim(manifest, worker_id)
    if claimed == :blocked
      sleep CONFLICT_RETRY_INTERVAL
      next
    end
    break unless claimed

    test = Registry.find(claimed.fingerprint)
    unless test
      err = RuntimeError.new(
        "Test fingerprint not in Registry (load files before replace_tests): #{claimed.fingerprint}"
      )
      manifest.record_error(claimed.fingerprint, err)
      result = Result.new(test: synthetic_test_from_claim(claimed), status: :error, error: err)
      results << result
      @reporter.on_test_complete(result: result, worker_id: worker_id)
      next
    end

    result = run_with_hooks(test)
    results << result
    @reporter.on_test_complete(result: result, worker_id: worker_id)

    case result.status
    when :pass  then manifest.record_pass(test.fingerprint)
    when :fail  then manifest.record_failure(test.fingerprint, result.error)
    when :error then manifest.record_error(test.fingerprint, result.error)
    end
  end

  Registry.all.select { Verity.skipped?(_1) }.each do |t|
    @reporter.on_test_complete(
      result: Result.new(test: t, status: :skip, error: nil),
      worker_id: worker_id
    )
  end

  without_skip = Registry.all.reject { Verity.skipped?(_1) }
  skipped = Registry.all.count { Verity.skipped?(_1) }
  focus = Verity.focus_filter_active?(without_skip)

  @reporter.on_run_finish(
    summary: build_summary(results, skipped: skipped, focus: focus),
    worker_id: worker_id
  )
  results.all? { |r| r.status == :pass }
end