Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 20, 2025

Thread.Sleep() and Task.Delay() cause test flakiness when operations don't complete in fixed time windows. This analyzer detects these patterns at build time instead of via CodeQL, shifting feedback left.

Changes

  • New analyzer: AvoidSleepAndDelayInTestsAnalyzer (MSTEST0059)

    • Detects Thread.Sleep() and Task.Delay() invocations in test methods and fixtures
    • Reports as Info (disabled by default, Category: Design)
    • Scopes to: TestMethod, DataTestMethod, TestInitialize/Cleanup, ClassInitialize/Cleanup, AssemblyInitialize/Cleanup
    • Ignores non-test helper methods
    • Must be explicitly enabled via configuration to opt-in
  • Test coverage: 13 test cases covering all fixture types, positive/negative scenarios, and async alternatives

  • Localization: Added resources for all 13 supported languages

Example

// Before - no diagnostic (analyzer disabled by default)
[TestMethod]
public void MyTest()
{
    Thread.Sleep(1000);
    Task.Delay(100);  // Without await
}

// After enabling the analyzer - info diagnostics shown
[TestMethod]
public void MyTest()
{
    Thread.Sleep(1000);  // MSTEST0059: Avoid using 'Thread.Sleep' in test methods
    Task.Delay(100);     // MSTEST0059: Avoid using 'Task.Delay' in test methods
}

// Suggested fix - use await with Task.Delay
[TestMethod]
public async Task MyTest()
{
    await Task.Delay(1000);  // Properly awaited - no diagnostic
}

Note

This analyzer is disabled by default and reports as Info severity. Users can enable it in their .editorconfig if they want to detect these patterns in their test code.

The analyzer detects arbitrary delays (Thread.Sleep and non-awaited Task.Delay) that can cause test flakiness. Task.Wait() is not flagged as it represents synchronous waiting for task completion rather than an arbitrary delay.

Original prompt

This section details on the original issue you should resolve

<issue_title>Detect Thread.Sleep(x) and Thread.Wait(x) inside test code to reduce flakiness</issue_title>
<issue_description>Detect Thread.Sleep(x) and Thread.Wait(x) inside test code to reduce flakiness

Background and Motivation

Thread.Sleep(x) and Thread.Wait(x) are causing test flakiness when operation is not completed in the specific time frame. In most of the cases asynchronous calls would be much better solution.

Proposed Feature

Detection of Thread.Sleep(x) and Thread.Wait(x) should be added for the test code so INFO or WARNING should inform developer during build time that there is possible flakiness in the test code.

Alternative Designs

Currently we are detecting above patterns using CodeQL inside the test code. Using test analyzer would be much better solution because it would shift the detection to the left (build time), speeding up detection and increasing quality.</issue_description>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Detect Thread.Sleep and Thread.Wait in test code Add analyzer to detect Thread.Sleep and Task.Wait in test methods Nov 20, 2025
Copilot AI requested a review from Evangelink November 20, 2025 10:06
Copilot finished work on behalf of Evangelink November 20, 2025 10:06
return;
}

// Check if the invocation is Task.Wait
Copy link
Member

Choose a reason for hiding this comment

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

Should we be looking at Task.Delay instead?

Copy link
Member

@Evangelink Evangelink Nov 24, 2025

Choose a reason for hiding this comment

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

I agree for the purpose of this rule, calls to Wait should be fine but we should instead catch Task.Delay.

@copilot please update.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, we're detecting Task.Wait (blocking call) not Task.Delay. Task.Delay is the recommended async alternative. The analyzer detects Thread.Sleep and Task.Wait as problematic patterns, while Task.Delay (used with await) is the suggested replacement. Commit: 79f86da

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to detect Task.Delay instead of Task.Wait. Task.Wait is now allowed as it's not an arbitrary delay. Commit: ae6e946

/// MSTEST0059: <inheritdoc cref="Resources.AvoidBlockingCallsInTestsTitle"/>.
/// </summary>
[DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)]
public sealed class AvoidBlockingCallsInTestsAnalyzer : DiagnosticAnalyzer
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this name is accurate. It's not about blocking IMO. It's about arbitrary delays/sleeps.

Copy link
Member

Choose a reason for hiding this comment

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

I agree! Please @copilot update the name, rule name etc to reflect that change.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Renamed to AvoidSleepAndDelayInTests to better reflect that it detects arbitrary delays/sleeps. Commit: 79f86da

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Already renamed in previous commit 79f86da. The analyzer is now named AvoidSleepAndDelayInTests.

MessageFormat,
Description,
Category.Design,
DiagnosticSeverity.Warning,
Copy link
Member

Choose a reason for hiding this comment

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

I wouldn't put as Warning by default. That's too aggressive IMO.
It should be Info. And not even sure if should be enabled by default or not.

Copy link
Member

Choose a reason for hiding this comment

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

@copilot update as info and make it disabled by default

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to Info severity and disabled by default. Commit: 79f86da

- Renamed AvoidBlockingCallsInTests to AvoidSleepAndDelayInTests to better reflect that it detects arbitrary delays/sleeps rather than blocking calls
- Changed severity from Warning to Info
- Changed isEnabledByDefault from true to false
- Updated all resource strings and localization files
- Updated AnalyzerReleases.Unshipped.md

Co-authored-by: Evangelink <[email protected]>
- Updated analyzer to detect Task.Delay calls instead of Task.Wait
- Task.Wait is now allowed, as it's not an arbitrary delay
- Task.Delay without await is detected as problematic pattern
- Updated all resource strings and localization files
- Updated tests to reflect the new behavior:
  - Task.Delay without await now triggers diagnostic
  - await Task.Delay is allowed (no diagnostic)
  - Task.Wait is now allowed (no diagnostic)

Co-authored-by: Evangelink <[email protected]>
Copilot AI changed the title Add analyzer to detect Thread.Sleep and Task.Wait in test methods Add analyzer to detect Thread.Sleep and Task.Delay in test methods Nov 24, 2025
Copilot finished work on behalf of Evangelink November 24, 2025 17:21
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.

Detect Thread.Sleep(x) and Thread.Wait(x) inside test code to reduce flakiness

3 participants