Commit 42e2dc9
authored
[Test Optimization] Add
## Summary of changes
Add a new test.final_status tag to the final execution span of tests
across NUnit, XUnit, and MsTest frameworks. This tag represents the
adjusted final outcome of a test for CI pipeline result determination,
with values pass, fail, or skip.
Jira: SDTEST-2985
### Core changes:
- Add TestFinalStatus constant to TestTags.cs and FinalStatus property
to TestSpanTags.cs
- Add shared CalculateFinalStatus() helper in Common.cs implementing the
priority logic
- Implement final status tracking in NUnit
(TestOptimizationTestCommand.cs), XUnit (XUnitIntegration.cs), and
MsTest (TestMethodAttributeExecuteIntegration.cs)
- Add ATR budget pre-check methods
(GetRemainingBudget/GetRemainingAtrBudget) for early termination
detection
- Add per-row caching for MsTest parameterized tests to track execution
results independently
### Fix:
- Corrected **test.test_management.attempt_to_fix_passed** tag to only
be set on Attempt-to-Fix (ATF) tests; previously it was incorrectly set
on all retried tests (EFD, ATR, ATF) due to a hardcoded behavior type.
## Reason for change
When retry mechanisms are enabled (ATR, EFD, Attempt to Fix), a single
test can run multiple times with different outcomes. Some intermediate
outcomes are suppressed to avoid failing CI pipelines. Currently, there
is no way to query tests by their final adjusted status to build
monitors and alerts for hard failures on default branches.
The test.final_status tag enables customers to:
- Query tests by their effective CI outcome in Datadog
- Build monitors for tests that are truly failing (not just flaky)
- Distinguish between tests that eventually passed vs. those that
consistently failed
- Track quarantined/disabled tests separately from actual failures
#### Priority logic:
1. Quarantined/disabled tests → always skip (CI never sees actual
result)
2. **ATF tests with any execution failed → fail (test is still flaky,
fix didn't work)**
3. Any execution passed → pass (matches CI behavior: one pass = pipeline
pass)
4. Last retry is skip/inconclusive AND no pass → skip
5. All executions failed → fail
#### ATF (Attempt to Fix) semantics:
For ATF tests, the goal is to determine if a fix actually resolved a
flaky test. Therefore:
- If **any** execution fails (initial or retry), the test is still flaky
→ `final_status = fail`
- Only if **all** executions pass, the fix worked → `final_status =
pass`
- Skip/inconclusive does **not** count as failure (only actual failures
count)
- `attempt_to_fix_passed` tag is derived from the same logic for
consistency
## Implementation details
#### Shared logic (Common.cs):
- CalculateFinalStatus(anyExecutionPassed, anyExecutionFailed,
isSkippedOrInconclusive, testTags) implements the 5-priority
determination
- Added `anyExecutionFailed` parameter to support ATF-specific behavior
#### NUnit:
- Extended RetryState struct with InitialExecutionPassed,
InitialExecutionFailed, and AnyRetryPassed fields
- Added GetRemainingBudget() to FlakyRetryBehavior for ATR budget
exhaustion pre-check
- Set final_status in ExecuteTest() before span close, handling ATR
early exit and budget exhaustion
- AllAttemptsPassed only clears on actual failure (not skip) for ATF
semantics
- AttemptToFixPassed derived from anyExecutionFailed for consistency
#### XUnit:
- Extended TestCaseMetadata with InitialExecutionPassed,
InitialExecutionFailed, and AnyRetryPassed fields
- Added unified GetRemainingAtrBudget() handling both v2 and v3 via
Math.Max() strategy
- Updated WriteFinalTagsFromMetadata() with final execution detection
(handles stale TotalExecutions on initial EFD)
- Track InitialExecutionFailed on exception path for first execution
- AttemptToFixPassed derived from anyExecutionFailed for consistency
#### MsTest:
- Added per-row caches (InitialExecutionPassedCache,
InitialExecutionFailedCache, AnyRetryPassedCache,
AllAttemptsPassedCache) using ConditionalWeakTable<object,
ConcurrentDictionary<string, bool>> to track parameterized test results
independently
- Added SetFinalStatusIfApplicable() helper with proper final execution
detection
- Added GetRemainingAtrBudget() for budget exhaustion pre-check
- Updated SkipTestMethodExecutor and UnitTestRunnerRunSingleTest*
integrations for pre-execution skip paths
- Track InitialExecutionFailed in both exception and non-exception paths
- AttemptToFixPassed derived from anyExecutionFailed for consistency
## Test coverage
#### Unit tests (TestFinalStatusTests.cs): 136 tests covering:
- Priority order verification (quarantined/disabled → ATF-fail → pass →
skip → fail)
- Single execution scenarios (pass/fail/skip)
- EFD scenarios (new tests, duration-based retries, slow abort)
- ATR scenarios (initial pass, retry pass, all fail, budget exhaustion)
- ATF scenarios (any failure → fail, all pass → pass, skip semantics)
- ATF skip semantics: skip does NOT count as failure (5 dedicated tests)
- MsTest-specific: parameterized per-row tracking, class/assembly init
errors, inconclusive/not-runnable
- XUnit-specific: SkipException handling, null metadata
- NUnit-specific: ITR skipped, attribute skipped, inconclusive
- Mixed feature interactions (EFD+ATR, EFD+ATF, ATR+ATF)
- Edge cases: empty strings, case sensitivity, null tags
#### Integration tests:
- Added TestFinalStatus to span ordering in TestingFrameworkEvpTest.cs
for deterministic snapshot verification
## Other details
<!-- Fixes #{issue} -->
<!-- test.final_status tag (#8091)1 parent 9281c0d commit 42e2dc9
66 files changed
Lines changed: 2721 additions & 118 deletions
File tree
- tracer
- src/Datadog.Trace
- Ci
- Tagging
- Tags
- ClrProfiler/AutoInstrumentation/Testing
- MsTestV2
- NUnit
- XUnit
- V3
- Generated
- net461/Datadog.Trace.SourceGenerators/TagListGenerator
- net6.0/Datadog.Trace.SourceGenerators/TagListGenerator
- netcoreapp3.1/Datadog.Trace.SourceGenerators/TagListGenerator
- netstandard2.0/Datadog.Trace.SourceGenerators/TagListGenerator
- test
- Datadog.Trace.ClrProfiler.IntegrationTests/CI
- Datadog.Trace.Tests/Ci
- snapshots
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
127 | 127 | | |
128 | 128 | | |
129 | 129 | | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
130 | 133 | | |
131 | 134 | | |
132 | 135 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
156 | 156 | | |
157 | 157 | | |
158 | 158 | | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
159 | 174 | | |
160 | 175 | | |
161 | 176 | | |
| |||
185 | 200 | | |
186 | 201 | | |
187 | 202 | | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
188 | 208 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
555 | 555 | | |
556 | 556 | | |
557 | 557 | | |
558 | | - | |
559 | | - | |
| 558 | + | |
| 559 | + | |
560 | 560 | | |
561 | 561 | | |
562 | 562 | | |
| |||
Lines changed: 49 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
10 | 10 | | |
11 | 11 | | |
12 | 12 | | |
| 13 | + | |
13 | 14 | | |
14 | 15 | | |
15 | 16 | | |
| |||
188 | 189 | | |
189 | 190 | | |
190 | 191 | | |
191 | | - | |
| 192 | + | |
192 | 193 | | |
193 | 194 | | |
194 | 195 | | |
| |||
211 | 212 | | |
212 | 213 | | |
213 | 214 | | |
214 | | - | |
| 215 | + | |
215 | 216 | | |
216 | 217 | | |
217 | 218 | | |
| |||
244 | 245 | | |
245 | 246 | | |
246 | 247 | | |
247 | | - | |
| 248 | + | |
248 | 249 | | |
249 | 250 | | |
250 | 251 | | |
| |||
273 | 274 | | |
274 | 275 | | |
275 | 276 | | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
276 | 322 | | |
Lines changed: 8 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
8 | 8 | | |
9 | 9 | | |
10 | 10 | | |
| 11 | + | |
11 | 12 | | |
12 | 13 | | |
13 | 14 | | |
| |||
37 | 38 | | |
38 | 39 | | |
39 | 40 | | |
40 | | - | |
41 | | - | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
42 | 48 | | |
43 | 49 | | |
44 | 50 | | |
| |||
0 commit comments