Skip to content

Comments

feat: Migrate tests from xunit to TUnit#875

Open
BenjaminMichaelis wants to merge 1 commit intomainfrom
bmichaelis/tunit
Open

feat: Migrate tests from xunit to TUnit#875
BenjaminMichaelis wants to merge 1 commit intomainfrom
bmichaelis/tunit

Conversation

@BenjaminMichaelis
Copy link
Member

  • Replace xunit + coverlet with TUnit test framework
  • Update test project files to use TUnit package references
  • Add Microsoft.Testing.Platform runner config to global.json
  • Update CI test command for TUnit MTP compatibility
  • Convert all test classes and assertions to TUnit syntax
  • Add [NotInParallel] to tests using shared SQLite state
  • Use IsEquivalentTo for collection comparisons

- Replace xunit + coverlet with TUnit test framework
- Update test project files to use TUnit package references
- Add Microsoft.Testing.Platform runner config to global.json
- Update CI test command for TUnit MTP compatibility
- Convert all test classes and assertions to TUnit syntax
- Add [NotInParallel] to tests using shared SQLite state
- Use IsEquivalentTo for collection comparisons

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings February 25, 2026 05:50
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Migrates the solution’s test projects from xUnit/vstest to TUnit running on Microsoft.Testing.Platform (MTP), updating CI and test code to the new attribute/assertion model.

Changes:

  • Configure dotnet test to use Microsoft.Testing.Platform via global.json, and update PR CI to emit TRX under MTP.
  • Replace xUnit + coverlet + vstest package references with TUnit in both test projects.
  • Convert test attributes and assertions from xUnit syntax to TUnit syntax (including parallelization controls/data sources).

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
global.json Selects Microsoft.Testing.Platform as the test runner for dotnet test.
EssentialCSharp.Web.Tests/Usings.cs Removes global xUnit using.
EssentialCSharp.Web.Tests/StringExtensionsTests.cs Converts xUnit theory/assertions to TUnit [Test]/[Arguments] + Assert.That.
EssentialCSharp.Web.Tests/SitemapXmlHelpersTests.cs Converts fixture pattern to TUnit data source and adds [NotInParallel].
EssentialCSharp.Web.Tests/SiteMappingTests.cs Converts xUnit facts/theories to TUnit tests and equivalents.
EssentialCSharp.Web.Tests/RouteConfigurationServiceTests.cs Converts xUnit fixture usage to TUnit class data source.
EssentialCSharp.Web.Tests/ListingSourceCodeServiceTests.cs Converts assertions to TUnit and adjusts collection comparisons.
EssentialCSharp.Web.Tests/ListingSourceCodeControllerTests.cs Converts integration tests to TUnit assertions.
EssentialCSharp.Web.Tests/Integration/CaptchaTests.cs Converts xUnit fixture test to TUnit class data source and assertions.
EssentialCSharp.Web.Tests/FunctionalTests.cs Converts xUnit theories/facts to TUnit argument-based tests.
EssentialCSharp.Web.Tests/EssentialCSharp.Web.Tests.csproj Swaps xUnit/vstest/coverlet references for TUnit.
EssentialCSharp.Chat.Tests/MarkdownChunkingServiceTests.cs Converts xUnit tests to TUnit assertions.
EssentialCSharp.Chat.Tests/EssentialCSharp.Chat.Tests.csproj Swaps xUnit/vstest/coverlet references for TUnit.
Directory.Packages.props Central package updates: remove xUnit/vstest/coverlet versions; add TUnit version.
.github/workflows/PR-Build-And-Test.yml Updates dotnet test invocation to use MTP TRX reporting arguments.

[Fact]
public void EnsureSitemapHealthy_WithValidSiteMappings_DoesNotThrow()
[Test]
public async Task EnsureSitemapHealthy_WithValidSiteMappings_DoesNotThrow()
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

EnsureSitemapHealthy_WithValidSiteMappings_DoesNotThrow is declared as async Task but contains no await. With TreatWarningsAsErrors enabled, this will fail the build with CS1998. Remove async (or return Task.CompletedTask), or add an awaited TUnit assertion (e.g., an explicit does-not-throw assertion).

Suggested change
public async Task EnsureSitemapHealthy_WithValidSiteMappings_DoesNotThrow()
public void EnsureSitemapHealthy_WithValidSiteMappings_DoesNotThrow()

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +27
await Assert.That(result.ChapterNumber).IsEqualTo(1);
await Assert.That(result.ListingNumber).IsEqualTo(1);
await Assert.That(result.FileExtension).IsEqualTo("cs");
await Assert.That(result.Content).IsNotEmpty();
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

result is nullable (ListingSourceCodeResponse?) but is dereferenced after IsNotNull(). If TUnit assertions don’t update nullable flow analysis, result.ChapterNumber will raise CS8602 and fail the build under TreatWarningsAsErrors. Consider using result! (or a non-null local) before accessing properties.

Suggested change
await Assert.That(result.ChapterNumber).IsEqualTo(1);
await Assert.That(result.ListingNumber).IsEqualTo(1);
await Assert.That(result.FileExtension).IsEqualTo("cs");
await Assert.That(result.Content).IsNotEmpty();
ListingSourceCodeResponse nonNullResult = result!;
await Assert.That(nonNullResult.ChapterNumber).IsEqualTo(1);
await Assert.That(nonNullResult.ListingNumber).IsEqualTo(1);
await Assert.That(nonNullResult.FileExtension).IsEqualTo("cs");
await Assert.That(nonNullResult.Content).IsNotEmpty();

Copilot uses AI. Check for mistakes.
Comment on lines 65 to +67
// Assert
Assert.NotNull(result);
Assert.Equal("xml", result.FileExtension);
await Assert.That(result).IsNotNull();
await Assert.That(result.FileExtension).IsEqualTo("xml");
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

Same nullable-flow issue here: result is nullable and result.FileExtension is accessed after IsNotNull(). If TUnit doesn’t inform nullable analysis, this will produce CS8602 with warnings-as-errors. Use result! (or capture a non-null local) before dereferencing.

Copilot uses AI. Check for mistakes.
Comment on lines 23 to +26
ListingSourceCodeResponse? result = await response.Content.ReadFromJsonAsync<ListingSourceCodeResponse>();
Assert.NotNull(result);
Assert.Equal(1, result.ChapterNumber);
Assert.Equal(1, result.ListingNumber);
Assert.NotEmpty(result.FileExtension);
Assert.NotEmpty(result.Content);
await Assert.That(result).IsNotNull();
await Assert.That(result.ChapterNumber).IsEqualTo(1);
await Assert.That(result.ListingNumber).IsEqualTo(1);
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

result is nullable (ListingSourceCodeResponse?) but is dereferenced after IsNotNull(). If the TUnit assertion doesn’t affect nullable analysis, accessing result.ChapterNumber/etc. will emit CS8602 and fail the build with warnings-as-errors. Use result! (or a non-null local) before accessing properties.

Copilot uses AI. Check for mistakes.
Comment on lines 73 to +79
List<ListingSourceCodeResponse>? results = await response.Content.ReadFromJsonAsync<List<ListingSourceCodeResponse>>();
Assert.NotNull(results);
Assert.NotEmpty(results);
await Assert.That(results).IsNotNull();
await Assert.That(results).IsNotEmpty();

// Verify all results are from chapter 1
Assert.All(results, r => Assert.Equal(1, r.ChapterNumber));

foreach (var r in results)
{
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

results is declared nullable but is iterated/used after IsNotNull(). If TUnit’s IsNotNull() doesn’t update nullable flow, foreach (var r in results) will trigger CS8602 under TreatWarningsAsErrors. Consider assigning var nonNullResults = results!; after the assertion and using that for the rest of the test.

Copilot uses AI. Check for mistakes.
HCaptchaResult? response = await captchaService.VerifyAsync(hCaptchaSecret, hCaptchaToken, hCaptchaSiteKey);

await Assert.That(response).IsNotNull();
await Assert.That(response.Success).IsTrue();
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

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

response is HCaptchaResult? and is dereferenced (response.Success) after IsNotNull(). If TUnit’s IsNotNull() doesn’t inform nullable flow analysis, this will produce CS8602 and fail the build with warnings-as-errors. Use response! (or capture a non-null local) before accessing .Success.

Suggested change
await Assert.That(response.Success).IsTrue();
HCaptchaResult nonNullResponse = response!;
await Assert.That(nonNullResponse.Success).IsTrue();

Copilot uses AI. Check for mistakes.
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.

1 participant