Skip to content

Migrate test projects from xunit 2.x to xunit v3 #289

Description

@zkarachiwala

Background

dotnet list package --deprecated --include-transitive flags xunit 2.9.3 as Legacy across TimeTracker.Tests, TimeTracker.Playwright, and TimeTracker.ComponentTests, recommending xunit.v3. This is a deprecation notice, not a vulnerability — no immediate action required, tracked here for planned future work.

Status: not started. This issue is for tracking/planning only.

Why this is a bigger migration than a normal version bump

xunit v3 changes the test execution model, not just the API surface:

  • Test projects become self-executing console apps run through Microsoft's new Testing Platform (MTP), replacing the generic VSTest host model.
  • Package renames: xunitxunit.v3, plus xunit.core/xunit.assert/etc. → xunit.v3.core/xunit.v3.assert/etc.
  • xunit.runner.visualstudio is either dropped or replaced depending on whether we keep VSTest compatibility or move fully to MTP — affects how dotnet test and CI invoke tests.
  • Xunit.SkippableFact (used by TimeTracker.Playwright write-tests per CLAUDE.md) may no longer be needed — xunit v3 has native dynamic skip support (Assert.Skip/SkipException). This could simplify things, but every [SkippableFact] + Skip.If call site needs rewriting.
  • coverlet.collector compatibility with the new MTP execution model needs verifying (recent versions have improved this).

Scope

  • TimeTracker.Tests
  • TimeTracker.ComponentTests
  • TimeTracker.Playwright (includes the [SkippableFact] write-test pattern)

Suggested approach (for whenever this is picked up)

  1. Migrate one project first (TimeTracker.Tests, smallest surface) to validate the MTP execution model works with existing CI (dotnet test --filter, coverlet, etc.).
  2. Decide whether to keep Xunit.SkippableFact or move to native xunit v3 skip support before touching TimeTracker.Playwright.
  3. Migrate TimeTracker.ComponentTests (bUnit compatibility with xunit v3 needs checking too).
  4. Migrate TimeTracker.Playwright last, given its [SkippableFact] dependency and CI skip-in-CI / run-locally split (WriteTestsEnabled).

Project board

Not yet added to the Timetracker project board (project #1) or given a Priority field value — the available GitHub tooling in this session couldn't set Projects v2 fields for a user-owned project. Needs gh project item-add 1 --owner zkarachiwala --url <issue-url> plus manually setting the Priority field, per CLAUDE.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    infrastructureHosting, deployment, and platform concerns

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions