Skip to content

Commit 47b61ce

Browse files
committed
Include eval coverage in the strict profile
The strict profile pins line, branch, and method coverage at 100%, but left eval coverage off. On Ruby 3.2+, code reached through Kernel#eval (notably ERB templates whose ERB#filename= has been set) gets routed through the standard line and branch counters, so leaving the toggle off meant strict was quietly lenient on the exact code paths most likely to grow untested. The profile now flips `enable_coverage :eval` on when the runtime supports it. The guard avoids the "Coverage for eval is not available" warning that would otherwise fire every time the profile loaded on Ruby 3.1 (the project's minimum), keeping graceful degradation consistent with how the existing branch and method clauses no-op on JRuby. A new spec asserts the toggle matches `coverage_for_eval_supported?` on whichever runtime the suite is running on, and the README's "equivalent" example mirrors the new conditional.
1 parent dec1550 commit 47b61ce

3 files changed

Lines changed: 29 additions & 1 deletion

File tree

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -970,12 +970,15 @@ That's equivalent to writing out:
970970
SimpleCov.start do
971971
enable_coverage :branch
972972
enable_coverage :method
973+
enable_coverage :eval if Coverage.respond_to?(:supported?) && Coverage.supported?(:eval)
973974
minimum_coverage line: 100, branch: 100, method: 100
974975
end
975976
```
976977

977978
The profile drops the branch / method clauses on engines that don't support those criteria (JRuby), so it still
978-
loads cleanly there — just enforcing line coverage at 100%.
979+
loads cleanly there — just enforcing line coverage at 100%. `:eval` is included on Ruby 3.2+ (where the runtime
980+
supports it), so any code reached through `Kernel#eval` — typically ERB templates with `ERB#filename=` set — is
981+
held to the same 100% bar. On older Rubies, the `:eval` clause is silently skipped.
979982

980983
### Custom profiles
981984

lib/simplecov/profiles/strict.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@
1414
# materialize. `CoverageViolations` skips threshold lookups for
1515
# criteria not in the stats, so the `:branch` / `:method` clauses below
1616
# silently no-op on JRuby and only `:line` is enforced.
17+
#
18+
# `:eval` widens the universe of code held to 100% to include strings
19+
# passed through `Kernel#eval` (typically ERB templates, when the user
20+
# sets `ERB#filename=`). Guarded on `coverage_for_eval_supported?` so
21+
# the profile stays quiet on Ruby < 3.2, where `enable_coverage :eval`
22+
# would otherwise warn about the missing runtime support every time
23+
# the profile loads.
1724
SimpleCov.profiles.define "strict" do
1825
enable_coverage :branch
1926
enable_coverage :method
27+
# simplecov:disable branch — dogfood runs on Ruby >= 3.2 only, so
28+
# the else arm (eval coverage not supported) is unreachable from CI.
29+
enable_coverage :eval if coverage_for_eval_supported?
30+
# simplecov:enable
2031
minimum_coverage line: 100, branch: 100, method: 100
2132
end

spec/profiles_spec.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,13 @@
2929
around do |example|
3030
prev_criteria = SimpleCov.coverage_criteria.dup
3131
prev_min = SimpleCov.minimum_coverage.dup
32+
prev_eval = SimpleCov.instance_variable_get(:@coverage_for_eval_enabled)
3233
example.run
3334
ensure
3435
SimpleCov.clear_coverage_criteria
3536
prev_criteria.each { |c| SimpleCov.enable_coverage(c) }
3637
SimpleCov.minimum_coverage(prev_min.empty? ? {} : prev_min)
38+
SimpleCov.instance_variable_set(:@coverage_for_eval_enabled, prev_eval)
3739
end
3840

3941
# No engine-conditional logic in the profile itself — every clause
@@ -47,5 +49,17 @@
4749
expect(SimpleCov.coverage_criteria).to include(:line, :branch, :method)
4850
expect(SimpleCov.minimum_coverage).to eq(line: 100, branch: 100, method: 100)
4951
end
52+
53+
# `:eval` widens the strict universe to include code passed through
54+
# `Kernel#eval` (ERB templates, etc.) on runtimes that support it.
55+
# On older Rubies the toggle is silently skipped — `enable_coverage
56+
# :eval` would otherwise warn about missing runtime support every
57+
# time the profile loaded.
58+
it "enables :eval when the runtime supports it" do
59+
SimpleCov.instance_variable_set(:@coverage_for_eval_enabled, false)
60+
SimpleCov.load_profile "strict"
61+
62+
expect(SimpleCov.coverage_for_eval_enabled?).to eq(SimpleCov.coverage_for_eval_supported?)
63+
end
5064
end
5165
end

0 commit comments

Comments
 (0)