Skip to content

Honor Timeout on StaFact/StaTheory and other UI test attributes - #237

Merged
AArnott merged 5 commits into
v4.0from
copilot/fix-timeout-parameter-stafact
Oct 1, 2026
Merged

AArnott merged 5 commits into
v4.0from
copilot/fix-timeout-parameter-stafact

Conversation

Copilot AI commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Timeout had no effect on StaFact, StaTheory, or the other UI fact/theory attributes. A test like this never failed:

[StaFact(Timeout = 1000)]
public void TimeoutTest() => Thread.Sleep(2000);

There were two causes. Facts dropped the value during discovery. On top of that, nothing enforced timeouts for either facts or theories.

Changes

  • Discovery (Utilities.CreateTestCasesForFact)
    • Now passes details.Timeout to UITestCase. The theory paths already did this.
  • Execution (UITestRunner.RunTest)
    • This method fully overrides xunit's CoreTestRunner.RunTest, where RunTestWithTimeout lives, so timeouts were never applied. The xunit behavior is now reimplemented here:
      • The test races Task.Delay(timeout). If the delay wins, the runner records a TestTimeoutException, updates the test context, and calls TestContext.Current.CancelCurrentTest().
      • When a timeout is set, the test is posted to the UI thread instead of invoked inline. Otherwise a test that blocks the thread synchronously, such as with Thread.Sleep, would keep the runner from ever reaching the timeout check.
      • The delay timer is cancelled once the test completes.
      • As in xunit, the timeout is skipped when a debugger is attached.

Behavior worth reviewing

  • Timed-out tests keep running. As in xunit, the result is reported without waiting for the test. A test that ignores the cancellation token keeps occupying its UI thread. Later work that needs that thread waits behind it: a MaxAttempts retry, a culture restore, or tests sharing the thread through a UIThreadFixtureBase fixture.
  • Late reports for blocking UIFact tests. These tests use a sync context set as current on the UI thread. If such a test blocks that thread, the timeout is recorded, but the failure is only reported once the thread frees up, because the outer pipeline resumes on that context.

Tests

  • Timeout_NotExceeded (fact and theory): checks that the timeout reaches the test case and that the ctor and test thread/sync context stay the same on the new posted path.
  • Timeout_Exceeded_Sync / Timeout_Exceeded_Async (fact and theory): tagged FailureExpected, so CI skips them. They cover a test that blocks the thread and an async one.

Copilot AI changed the title [WIP] Fix timeout parameter for StaFact and StaTheory in version 4.0.23 Honor Timeout on StaFact/StaTheory and other UI test attributes Oct 1, 2026
Copilot AI requested a review from AArnott October 1, 2026 15:01
@AArnott

AArnott commented Oct 1, 2026

Copy link
Copy Markdown
Owner

@copilot retarget this change to the v4.0 branch.

@AArnott AArnott added this to the v4.0 milestone Oct 1, 2026

Copilot AI commented Oct 1, 2026

Copy link
Copy Markdown
Contributor Author

@copilot retarget this change to the v4.0 branch.

I couldn't retarget this PR. I can't change a PR's base branch, and my push tool can't force-push. Rebasing this branch onto v4.0 needs a force-push, because main is 55 commits ahead of v4.0. If you switch the base in the UI as-is, those commits will show up in the diff.

I did check the port locally:

  • Discovery: v4.0 already passes Timeout in CreateTestCaseForFact, so the Utilities.cs change isn't needed there.
  • What's needed: only the UITestRunner.cs timeout enforcement and the new tests.
  • Results: with ffcd6a3 and ec232ce cherry-picked onto origin/v4.0, keeping v4.0's Utilities.cs on conflict, the build has no errors. The non-FailureExpected tests pass on net8.0, and the timeout tests fail by timing out after about 100ms.

You can do either of these:

  • Cherry-pick ffcd6a3 and ec232ce onto a branch off v4.0 and open a PR from it. I can't open PRs.
  • Force-push a rebased branch here yourself, then switch the base to v4.0.

This PR is unchanged and still targets main.

Copilot AI and others added 2 commits October 1, 2026 09:27
Co-authored-by: AArnott <3548+AArnott@users.noreply.github.com>
Co-authored-by: AArnott <3548+AArnott@users.noreply.github.com>
@AArnott
AArnott force-pushed the copilot/fix-timeout-parameter-stafact branch from ec232ce to 5476ccf Compare October 1, 2026 15:38
@AArnott
AArnott changed the base branch from main to v4.0 October 1, 2026 15:38
@AArnott
AArnott requested a balanced review from Copilot October 1, 2026 15:40
@AArnott
AArnott marked this pull request as ready for review October 1, 2026 15:40
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

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 review overview

🟡 Changes recommended

Constructors remain outside timeout enforcement, and timeout failures are excluded from automated CI coverage.

Review effort: Balanced
Findings: 1 High severity · 2 Medium severity

Open (3)
What changed in this PR

Adds timeout enforcement for UI-based facts and theories.

Changes:

  • Propagates fact timeout metadata during discovery.
  • Races UI-thread execution against the configured timeout.
  • Adds timeout and thread-affinity tests.
File Description
src/​Xunit.StaFact/​Sdk/​Utilities.cs Preserves fact timeout values.
src/​Xunit.StaFact/​Sdk/​UITestRunner.cs Implements timeout execution and cancellation.
test/​Xunit.StaFact.Tests/​UIFactTests.cs Adds fact timeout scenarios.
test/​Xunit.StaFact.Tests/​UITheoryTests.cs Adds theory timeout scenarios.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Xunit.StaFact/Sdk/UITestRunner.cs Outdated
Comment thread test/Xunit.StaFact.Tests/UIFactTests.cs
Comment thread test/Xunit.StaFact.Tests/UITheoryTests.cs
@codecov-commenter

codecov-commenter commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.30435% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.34%. Comparing base (90275fd) to head (87c3413).

Files with missing lines Patch % Lines
src/Xunit.StaFact/Sdk/UITestRunner.cs 89.74% 2 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             v4.0     #237      +/-   ##
==========================================
+ Coverage   83.94%   85.34%   +1.39%     
==========================================
  Files          36       36              
  Lines         760      805      +45     
  Branches       64       69       +5     
==========================================
+ Hits          638      687      +49     
+ Misses        100       95       -5     
- Partials       22       23       +1     
Flag Coverage Δ
Linux 82.76% <91.30%> (+1.78%) ⬆️
Windows 81.24% <91.30%> (+1.63%) ⬆️
macOS 82.76% <91.30%> (+1.78%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ 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.

Keep timeout reporting independent of blocked UI threads and add runner-level regression tests for lifecycle, fact, and theory timeout failures.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@AArnott
AArnott merged commit 7542fbf into v4.0 Oct 1, 2026
4 checks passed
@AArnott
AArnott deleted the copilot/fix-timeout-parameter-stafact branch October 1, 2026 16:07
@AArnott AArnott mentioned this pull request Oct 1, 2026
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.

Timeout parameter for StaFact and StaTheory has no effect in version 4.0.23

4 participants