Skip to content

test: restore silently-dropped Emit_Unit_MeasurementUnit_Predefined theory coverage - #5615

Merged
jamescrosswell merged 1 commit into
mainfrom
fix/metric-emitter-theory-discovery
Sep 23, 2026
Merged

jamescrosswell merged 1 commit into
mainfrom
fix/metric-emitter-theory-discovery

Conversation

@jamescrosswell

Copy link
Copy Markdown
Collaborator

Summary

Emit_Unit_MeasurementUnit_Predefined in test/Sentry.Tests/SentryMetricEmitterTests.Values.cs was never discovered or executed, so its 24 [InlineData] rows provided no coverage:

dotnet test test/Sentry.Tests/Sentry.Tests.csproj -c Release -f net10.0 --list-tests | grep Emit_Unit

listed every sibling Emit_Unit_* test but not this one.

Cause

The theory declared its parameter as MeasurementUnit (a struct) while the inline values were MeasurementUnit.Duration / .Information / .Fraction enum constants. The C# compiler accepts that because MeasurementUnit defines implicit operator overloads for each nested enum — but xUnit does not apply user-defined implicit conversions when binding inline data, and drops the entire theory during discovery without emitting a diagnostic. Nothing appeared even with diagnosticMessages: true in xunit.runner.json; the theory simply vanished.

I isolated the mechanism with throwaway probes rather than assuming it:

Theory parameter [InlineData] Discovered?
long 1 ✅ (built-in widening)
MeasurementUnit.Duration MeasurementUnit.Duration.Nanosecond ✅
object MeasurementUnit.Duration.Nanosecond ✅
MeasurementUnit MeasurementUnit.Duration.Nanosecond ❌ silently dropped
Wrapper (struct, implicit operator Wrapper(int)) 1 ❌ silently dropped

So it is the user-defined conversion that breaks discovery — not the mix of nested enum types, and not anything specific to MeasurementUnit.

Fix

Split into three theories parameterized by the enum types xUnit can bind (Emit_Unit_MeasurementUnit_Duration / _Information / _Fraction), sharing one AssertEmittedUnit helper. The implicit conversion still happens, just at the helper's call site where the compiler handles it. All 24 rows are preserved.

All 24 cases are now discovered and pass — the assertions were correct, they had simply never executed.

Sweep for the same pattern

Since these tests fail invisibly, I diffed every [Fact]/[Theory] declared under test/Sentry.Tests against the full --list-tests output. Every other gap was either #if-guarded platform code (NETFRAMEWORK, ANDROID, IOS, MACCATALYST, DEBUG) not compiled for net10.0, or regex noise — this theory was the only genuinely dropped one. The sibling files called out in the report (SentryMetricEmitterTests.Types.cs, .Options.cs, SentryStructuredLoggerTests.*) are clean. A repo-wide grep found no other [InlineData] relying on a user-defined implicit conversion.

Notes for review

  • One incidental find, left alone as out of scope: test/Sentry.Tests/Helpers/ImmutableTests.cs and test/Sentry.Tests/Protocol/ImmutableTests.cs both declare abstract class ImmutableTests<TType> with a Type_IsImmutable fact, but neither has any subclass — so those never run either. Happy to remove them in a follow-up.
  • dotnet build Sentry-CI-Build-macOS.slnf does not complete on my machine for reasons unrelated to this change (Xcode 27.0 vs the pinned 26.6 for the iOS/MacCatalyst SDKs, sample DSN #errors, missing workloads, sentry-native CMake). test/Sentry.Tests itself is green on net9.0 and net10.0 (2581 passed each), dotnet format is clean, and there is no Verify snapshot churn.

#skip-changelog

The theory declared its parameter as MeasurementUnit while its 24 [InlineData]
rows were MeasurementUnit.Duration/Information/Fraction enum constants. The C#
compiler accepts this via the implicit conversion operators, but xUnit does not
apply user-defined implicit conversions when binding inline data, and drops the
whole theory during discovery without emitting a diagnostic — even with
diagnosticMessages enabled. The 24 cases had never run.

Verified the mechanism in isolation: a theory taking a struct with an implicit
operator from int and [InlineData(1)] is dropped the same way, while a built-in
widening conversion (int -> long) is fine. So it is the user-defined conversion,
not the mix of nested enum types.

Split into three theories parameterized by the enum types xUnit can bind, sharing
one assertion helper. All 24 cases are now discovered and pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@jamescrosswell jamescrosswell added the skip-changelog Suppress automatic changelog generation via Craft label Sep 23, 2026
@codecov

codecov Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.85%. Comparing base (0a820d4) to head (03fad77).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5615      +/-   ##
==========================================
- Coverage   74.87%   74.85%   -0.02%     
==========================================
  Files         515      515              
  Lines       18962    18962              
  Branches     3694     3694              
==========================================
- Hits        14197    14194       -3     
- Misses       3888     3891       +3     
  Partials      877      877              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@jamescrosswell
jamescrosswell marked this pull request as ready for review September 23, 2026 08:02
@github-actions github-actions Bot added the risk: low PR risk score: low label Sep 23, 2026
@jamescrosswell
jamescrosswell merged commit 85cc2bf into main Sep 23, 2026
49 checks passed
@jamescrosswell
jamescrosswell deleted the fix/metric-emitter-theory-discovery branch September 23, 2026 22:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk: low PR risk score: low skip-changelog Suppress automatic changelog generation via Craft

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants