Skip to content

Add Azure DevOps history-driven slow-test threshold enricher (#9140)#9182

Open
Evangelink wants to merge 5 commits into
mainfrom
evangelink/issue-9140-azdo-slow-test-history
Open

Add Azure DevOps history-driven slow-test threshold enricher (#9140)#9182
Evangelink wants to merge 5 commits into
mainfrom
evangelink/issue-9140-azdo-slow-test-history

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Fixes #9140.

Summary

Adds an Azure DevOps history-driven slow-test threshold enricher to the existing Microsoft.Testing.Extensions.AzureDevOpsReport package (issue Option A — reuses the existing history-fetch infrastructure rather than a new package).

For tests with a known-short historical runtime it lowers the per-test still running after Ns threshold and decorates each emitted line with the historical p95/p99:

[slow] still running after 5s: Foo (historical p95 = 2s, p99 = 3s, samples = 120)

Knobs (best defaults)

Option Default Meaning
--report-azdo-slow-test-history <days> Enable + window (1-90). Requires --report-azdo.
--report-azdo-slow-test-history-min-sample <N> 10 Min samples before history is trusted.
--report-azdo-slow-test-history-multiplier <X> 3.0 Threshold = min(60s static, p99 * multiplier).

Emission uses exponential backoff (T -> 2T -> 4T ...). Falls back to the static 60s threshold when history is unavailable/below min-sample, and silently no-ops outside Azure DevOps (TF_BUILD not set) or when env/token are missing.

Implementation

  • Reuses the single flaky-history fetch: AzureDevOpsHistoryService now loads when flaky or slow-test history is enabled, captures durationInMs only when slow-test history is on, and exposes TryGetDurationStats (p95/p99/samples). No extra Azure DevOps round-trip.
  • New pure/testable helpers: PercentileCalculator (nearest-rank), DurationHistoryStats, AzureDevOpsSlowTestThresholds (threshold/decoration/formatting), TestNodeIdentity (shared FQN history key).
  • New AzureDevOpsSlowTestReporter performs the surfacing/backoff.

Note on #9139

#9140 was specced to hook into IProgressEnricher from #9139, which isn't merged yet. The surfacing here is therefore self-contained, with all decision logic isolated in pure methods and documented in-code to migrate onto IProgressEnricher once #9139 lands.

Tests

  • 21 new unit tests (percentile math, duration aggregation + below-min/no-history fallback, threshold computation, decoration formatting). Full Microsoft.Testing.Extensions.UnitTests AzureDevOps suite: 143 passing.
  • 5 new command-line validation acceptance tests.
  • --help / --info acceptance expectations updated (both blocks, alphabetically); xlf regenerated for all 13 locales.

All new types are internal (no public API surface added).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 16, 2026 11:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the Microsoft.Testing.Extensions.AzureDevOpsReport extension to support Azure DevOps history-driven slow-test surfacing: it fetches per-test duration history, computes p95/p99, lowers the “still running after …” threshold for historically-fast tests, and decorates emitted slow-test lines with the computed stats.

Changes:

  • Added new slow-test history CLI options (--report-azdo-slow-test-history*) plus help/info output updates and validation.
  • Reused the existing Azure DevOps history fetch to optionally collect durations and publish per-test p95/p99/sample-count stats.
  • Introduced a new AzureDevOpsSlowTestReporter plus pure helpers (PercentileCalculator, DurationHistoryStats, AzureDevOpsSlowTestThresholds, TestNodeIdentity) and accompanying unit/acceptance tests and localized resources.
Show a summary per file
File Description
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/AzureDevOpsSlowTestHistoryTests.cs Adds unit tests for percentile math, duration stats, threshold computation, and formatting.
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/AzureDevOpsHistoryServiceTests.cs Adds coverage for duration-stat aggregation when slow-test history is enabled/disabled.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/HelpInfoAllExtensionsTests.cs Updates --help/--info expectations to include new AzDO slow-test history options.
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/AzureDevOpsCommandLineTests.cs Adds acceptance validation tests for the new command-line options.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/TestNodeIdentity.cs Centralizes stable test-name resolution for history lookups.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/PercentileCalculator.cs Implements nearest-rank percentile computation for client-side p95/p99.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/IAzureDevOpsHistoryService.cs Extends history service contract to expose duration stats.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/DurationHistoryStats.cs Adds immutable p95/p99/sample-count container + builder from raw durations.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsSlowTestThresholds.cs Adds pure logic for threshold selection and compact duration formatting.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsSlowTestReporter.cs New background scanner that emits slow-test lines with exponential backoff and optional history decoration.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsReporter.cs Refactors to reuse TestNodeIdentity for stable naming.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsHistoryService.cs Reuses history fetch to optionally retain duration samples and publish p95/p99 stats.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsHistoryClient.cs Plumbs duration (durationInMs) from results into the in-memory model.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsExtensions.cs Registers the new slow-test reporter in the AzDO extension pipeline.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsCommandLineProvider.cs Adds new options, descriptions, and validation rules.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsCommandLineOptions.cs Defines new option names and default constants for slow-test history.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/AzureDevOpsResources.resx Adds resource strings for new options, validation, and slow-test output formatting.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.cs.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.de.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.es.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.fr.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.it.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.ja.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.ko.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.pl.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.pt-BR.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.ru.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.tr.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.zh-Hans.xlf Localization updates for new resource strings.
src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/Resources/xlf/AzureDevOpsResources.zh-Hant.xlf Localization updates for new resource strings.

Copilot's findings

Comments suppressed due to low confidence (1)

src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsCommandLineProvider.cs:122

  • When '--report-azdo' is not enabled, ValidateCommandLineOptionsAsync only checks '--report-azdo-slow-test-history' but does not check the dependent options '--report-azdo-slow-test-history-min-sample' / '--report-azdo-slow-test-history-multiplier'. As a result, users can pass these options without '--report-azdo' and validation will incorrectly succeed (errorMessage stays null). Add checks for these options in the "!IsOptionSet(--report-azdo)" block so they fail fast.
            else if (commandLineOptions.IsOptionSet(AzureDevOpsCommandLineOptions.AzureDevOpsSlowTestHistory))
            {
                errorMessage = AzureDevOpsResources.AzureDevOpsSlowTestHistoryRequiresAzureDevOps;
            }
            else if (commandLineOptions.IsOptionSet(AzureDevOpsCommandLineOptions.AzureDevOpsStackFrameFilter))
            {
                errorMessage = AzureDevOpsResources.AzureDevOpsStackFrameFilterRequiresAzureDevOps;
            }
  • Files reviewed: 30/30 changed files
  • Comments generated: 1

@Evangelink

This comment has been minimized.

@Evangelink Evangelink left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

🤖 Automated review by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

# Dimension Verdict
2 Threading & Concurrency 🟠 1 MAJOR
13 Test Completeness & Coverage 🟠 1 MAJOR
1 Algorithmic Correctness 🟡 1 MODERATE

✅ 19/22 dimensions clean.

  • Threading_active, _multiplier, and _minimumSampleCount in AzureDevOpsSlowTestReporter are written on the session-lifecycle thread and read concurrently in ConsumeAsync without volatile or Interlocked.*. The JIT may cache the pre-start value of _active = false, causing the reporter to silently skip all slow-test tracking. See inline comment for fix.

  • Test CompletenessAzureDevOpsSlowTestReporter is a 302-line class with no direct unit tests. The pure-logic helpers (PercentileCalculator, DurationHistoryStats, AzureDevOpsSlowTestThresholds) are well-tested, but the class's own behaviour is entirely covered by the acceptance tests, which are expensive to run and don't exercise fine-grained paths. The following scenarios have no test coverage at all:

    • TF_BUILD not set → warning emitted, scan loop not started
    • ConsumeAsync with InProgressTestNodeStateProperty → entry added to _inProgress with correct threshold
    • ConsumeAsync with a terminal state → entry removed
    • ScanLoopAsync emission path: with history decoration vs. static fallback
    • Exponential-backoff doubling of NextEmitThreshold
    • OnTestSessionFinishingAsync drains and cancels the loop task
  • CorrectnessValidateSlowTestHistoryMultiplierArgumentsAsync accepts multiplier > 0 without an upper bound. p99 * double.MaxValue overflows to ; TimeSpan.FromMilliseconds(∞) throws OverflowException in ResolveThreshold, which ConsumeAsync's catch block silently swallows — disabling slow-test detection for every test that has a history entry. See inline comment for fix.


Other observations (non-blocking):

  • LogUnexpectedException logs at Warning level. Per codebase conventions (Dimension 8), unexpected exceptions from internal callbacks are more naturally Error-level (warnings signal user-actionable conditions). Low impact given the catch is guarding an enhancement feature, but worth aligning with convention in a follow-up.

  • TestNodeIdentity.GetTestName uses .OfType<SerializableKeyValuePairStringProperty>().FirstOrDefault(...) — allocates an enumerator per call. This was pre-existing in AzureDevOpsReporter; the refactoring into a shared helper is the right move and doesn't introduce new regressions.

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Expert Code Review (on PR ready) workflow. · 562.4 AIC · ⌖ 13 AIC ·

@Evangelink Evangelink enabled auto-merge (squash) June 16, 2026 13:03
- Make slow-test history truly no-op outside Azure DevOps (no output-device line, downgrade log to Trace)
- Use volatile fields / Volatile.Read for cross-thread publication in AzureDevOpsSlowTestReporter
- Cap --report-azdo-slow-test-history-multiplier at 10000 and guard ComputeThreshold against infinity/NaN
- Avoid floating-point equality in TrimTrailingZero
- Document the expected OperationCanceledException swallow

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Evangelink

This comment has been minimized.

…ng for slow-test history

- Extract ScanOnceAsync and add direct unit tests for AzureDevOpsSlowTestReporter (no-op outside AzDO, emission, history decoration, exponential backoff, terminal removal, finish drain).
- Validate that --report-azdo-slow-test-history-min-sample/-multiplier require --report-azdo-slow-test-history even when --report-azdo is absent (Copilot review note), with acceptance coverage.
- Dogfood --report-azdo-slow-test-history in test/Directory.Build.targets, gated on TF_BUILD.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 16, 2026 14:00

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 32/32 changed files
  • Comments generated: 3

Comment on lines +28 to +37
double historyThresholdMs = stats.P99Milliseconds * multiplier;
if (double.IsNaN(historyThresholdMs) || double.IsInfinity(historyThresholdMs) || historyThresholdMs < 0)
{
// A pathological multiplier (or overflow to infinity) would make TimeSpan.FromMilliseconds throw;
// fall back to the static threshold instead of silently disabling slow-test detection.
return staticThreshold;
}

var historyThreshold = TimeSpan.FromMilliseconds(historyThresholdMs);
return historyThreshold < staticThreshold ? historyThreshold : staticThreshold;

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fb67002 — ComputeThreshold now short-circuits to the static threshold whenever historyThresholdMs >= staticThreshold.TotalMilliseconds (in addition to NaN/<=0), so the TimeSpan.FromMilliseconds conversion is skipped entirely for large finite values that would exceed TimeSpan.MaxValue. Added regression test ComputeThreshold_WhenHistoryExceedsTimeSpanMax_UsesStaticThreshold.

Comment on lines +230 to +231
// Exponential backoff so a genuinely stuck test does not spam the log: T, 2T, 4T, ...
test.NextEmitThreshold = TimeSpan.FromTicks(test.NextEmitThreshold.Ticks * 2);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fb67002 — the exponential-backoff doubling now clamps at TimeSpan.MaxValue before doubling: currentTicks > TimeSpan.MaxValue.Ticks / 2 ? TimeSpan.MaxValue : TimeSpan.FromTicks(currentTicks * 2), so Ticks * 2 can no longer overflow into a negative value.

Comment on lines +318 to +322
if (TryGetWindowInDays(AzureDevOpsCommandLineOptions.AzureDevOpsFlakyHistory, out int flakyWindow))
{
anyEnabled = true;
historyWindowInDays = Math.Max(historyWindowInDays, flakyWindow);
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in fb67002 — documented the behavior in TryGetHistoryConfiguration: flaky-history and slow-test-history deliberately share a single query using the maximum of the two windows so neither feature is starved of data, and the comment now calls out that the flaky in last {N}d annotation reflects the effective (maximum) window when the slow-test window is larger.

…-azdo-slow-test-history

# Conflicts:
#	src/Platform/Microsoft.Testing.Extensions.AzureDevOpsReport/AzureDevOpsExtensions.cs
@Evangelink

This comment has been minimized.

…red history window

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings June 16, 2026 14:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 32/32 changed files
  • Comments generated: 1

Comment on lines +6 to +8
using Microsoft.Testing.Extensions.AzureDevOpsReport;
using Microsoft.Testing.Extensions.Reporting;
using Microsoft.Testing.Platform.CommandLine;
@Evangelink

Copy link
Copy Markdown
Member Author

🧪 Test quality grade — PR #9182

29 test methods graded (15 A, 14 B) across 5 changed files — none below B. The dominant B driver is the ComputeThreshold_* family, where each test is focused and correct but carries only one equality assertion. The one test most worth splitting is HasUsableHistory_RespectsMinimumSampleCount, which tests three conditions (below/at/no-stats) in a single body and would produce sharper failure messages if separated.

ΔTestGradeBandNotes
new AzureDevOpsHistoryServiceTests.
HistoryService_
ComputesDurationStatsWhenSlowTestHistoryEnabledAsync
B 80–89 Rich multi-assertion coverage; 100-item setup loop is long but necessary for accurate p95/p99 values.
new AzureDevOpsHistoryServiceTests.
HistoryService_
DoesNotComputeDurationStatsWhenSlowTestHistoryDisabledAsync
B 80–89 Single IsFalse; a check that flaky-history stats still work would confirm the scope of the skip.
new AzureDevOpsSlowTestHistoryTests.
ComputeThreshold_
BelowMinimumSampleCount_
UsesStaticThreshold
B 80–89 Single equality; minimum-sample-count boundary tested from one side only (5 < 10).
new AzureDevOpsSlowTestHistoryTests.
ComputeThreshold_
WhenHistoryExceedsStatic_
KeepsStaticThreshold
B 80–89 Single equality; comment explains the 90s > 60s clamping logic clearly.
new AzureDevOpsSlowTestHistoryTests.
ComputeThreshold_
WhenHistoryExceedsTimeSpanMax_
UsesStaticThreshold
B 80–89 Single equality; named hugeButFinite and detailed comment make the overflow edge case self-explanatory.
new AzureDevOpsSlowTestHistoryTests.
ComputeThreshold_
WhenMultiplierOverflowsToInfinity_
UsesStaticThreshold
B 80–89 Single equality; comment explains the +Infinity overflow guard correctly.
new AzureDevOpsSlowTestHistoryTests.
ComputeThreshold_
WithoutHistory_
UsesStaticThreshold
B 80–89 Single equality; hasStats: false and named params make the no-history case self-documenting.
new AzureDevOpsSlowTestHistoryTests.
ComputeThreshold_
WithShortHistory_
LowersThreshold
B 80–89 Single equality; comment explains the p99 × multiplier derivation (3s × 3 = 9s threshold).
new AzureDevOpsSlowTestHistoryTests.
DurationHistoryStats_
TryCreate_
WithNoPositiveSamples_
ReturnsFalse
B 80–89 Single IsFalse; the negative case is covered cleanly.
new AzureDevOpsSlowTestHistoryTests.
HasUsableHistory_
RespectsMinimumSampleCount
B 80–89 Three conditions (below, at, and no-stats) in one test body; consider splitting for sharper failure messages.
new AzureDevOpsSlowTestHistoryTests.
Percentile_
SingleSample_
ReturnsThatSample
B 80–89 Single equality on a concise edge-case test; minimal but complete.
new AzureDevOpsSlowTestReporterTests.
ConsumeAsync_
TerminalState_
StopsTrackingAsync
B 80–89 Single IsEmpty; cleanly verifies that a terminal state stops slow-test tracking.
new AzureDevOpsSlowTestReporterTests.
OnTestSessionFinishing_
DrainsLoopAndClearsTrackingAsync
B 80–89 Single IsEmpty; multi-step Act sequence is well-commented and reflects the drain-then-stop contract.
new AzureDevOpsSlowTestReporterTests.
OnTestSessionStarting_
WhenNotInAzureDevOps_
NoOpsAndIgnoresUpdatesAsync
B 80–89 Single IsEmpty confirms the no-op path; a symmetrical test for the in-AzDO path would round out coverage.
new AzureDevOpsSlowTestHistoryTests.
DurationHistoryStats_
TryCreate_
IgnoresNonPositiveSamples
A 90–100 IsTrue on return value, AreEqual on count and p99; three assertions cover the key filtering behavior.
new AzureDevOpsSlowTestHistoryTests.
FormatDuration_
ProducesCompactStrings
A 90–100 Data-driven with 6 cases covering seconds, milliseconds, minutes, fractional, and negative values.
new AzureDevOpsSlowTestHistoryTests.
Percentile_
EmptySamples_
Throws
A 90–100 ThrowsExactly is complete; tests the empty-array boundary precisely.
new AzureDevOpsSlowTestHistoryTests.
Percentile_
NearestRank_
ReturnsExpectedSamples
A 90–100 Five equality checks across boundary and mid-range percentiles; clear and comprehensive.
new AzureDevOpsSlowTestHistoryTests.
Percentile_
OutOfRange_
Throws
A 90–100 Data-driven with 3 DataRows; ThrowsExactly(ArgumentOutOfRangeException) is precise.
new AzureDevOpsSlowTestReporterTests.
ScanOnce_
AfterThreshold_
EmitsSingleSlowTestLineAsync
A 90–100 Five assertions: before-threshold silence, line count, message content, test name, and no-history decoration.
new AzureDevOpsSlowTestReporterTests.
ScanOnce_
UsesExponentialBackoffAsync
A 90–100 Three count assertions track progression through two backoff doublings; mechanism is precisely verified.
new AzureDevOpsSlowTestReporterTests.
ScanOnce_
WithHistory_
LowersThresholdAndDecoratesLineAsync
A 90–100 Three assertions verify below-threshold silence, line count, and exact decoration format string.
new AzureDevOpsCommandLineTests.
AzureDevOps_
WhenSlowTestHistoryMinSampleUsedWithoutSlowTestHistory_
ShouldFail
A 90–100 No issues found.
new AzureDevOpsCommandLineTests.
AzureDevOps_
WhenSlowTestHistoryMultiplierIsInvalid_
ShouldFail
A 90–100 No issues found.
new AzureDevOpsCommandLineTests.
AzureDevOps_
WhenSlowTestHistoryMultiplierUsedWithoutSlowTestHistoryAndWithoutReportAzdo_
ShouldFail
A 90–100 No issues found.
new AzureDevOpsCommandLineTests.
AzureDevOps_
WhenSlowTestHistoryUsedWithoutReportAzdo_
ShouldFail
A 90–100 No issues found.
new AzureDevOpsCommandLineTests.
AzureDevOps_
WhenSlowTestHistoryValueIsInvalid_
ShouldFail
A 90–100 No issues found.
mod HelpInfoAllExtensionsTests.
Help_
WithAllExtensionsRegistered_
OutputFullHelpContent
A 90–100 Snapshot-style wildcard match verifies the full help surface including the new slow-test options.
mod HelpInfoAllExtensionsTests.
Info_
WithAllExtensionsRegistered_
OutputFullInfoContent
A 90–100 Snapshot-style wildcard match verifies the full --info surface with new option entries.

This advisory comment was generated automatically. Grades are heuristic
and informational — they do not block merging. Re-run with
/grade-tests.

🤖 Automated content by GitHub Copilot. Posted via a maintainer's GitHub token, so it appears under their account — the account owner did not write or approve this content personally. Generated by the Grade Tests on PR (on open / sync) workflow. · 966.4 AIC · ⌖ 25.6 AIC · [◷]( · )

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Azure DevOps history-driven slow-test threshold enricher

3 participants