Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix xUnit Theory serialization warnings #3186

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

paulmedynski
Copy link

@paulmedynski paulmedynski commented Feb 28, 2025

xUnit makes 2 passes over unit tests:

  1. Discover all of the tests, and for Theory tests, enumerate all of the test data.
  2. Run all of the tests, enumerating the test data again.

If the enumeration won't produce the same data in both steps, xUnit emits a warning. We have many test cases whose Theory data doesn't enumerate identically in both passes, for a variety of reasons. These tests will still run correctly, but they won't appear in test runner UIs like Visual Studio. Instead, xUnit collapses them into a single test for these UIs.

The warnings are clutter in the console (where I like to run tests), so xUnit provides a mechanism to disable enumeration completely in the discovery phase. I have updated the offending tests to use the MemberData DisableDiscoveryEnumeration flag. This doesn't affect how the tests run, and it doesn't change how UIs display them (collapsed). All it does is suppress the console warnings.

Further reading here: https://xunit.net/faq/theory-data-stability-in-vs

I also added 4 new targets to build.proj to make running the tests easier. The existing test running targets function as before.

Commit notes:

  • Suppressed xUnit discovery data enumeration warnings in Function and Manual test projects.
  • Fixed xUnit test data enumeration warnings specific to .NET Framework (enums in the GAC).
  • Added targets to run Windows and Unix tests.
  • Cleaned up test run command lines for improved maintenance and runtime logging.

- Suppressed xUnit discovery data enumeration warnings in Function and Manual test projects.
- Fixed xUnit test data enumeration warnings specific to .NET Framework (enums in the GAC).
- Added targets to run Windows and Unix tests.
- Cleaned up test run command lines for improved maintenance and runtime logging.
<Target Name="RunFunctionalTestsWindows" Condition="'$(IsEnabledWindows)' == 'true'">
<PropertyGroup>
<TestCommand>
$(DotnetPath)dotnet test "@(FunctionalTestsProj)"
Copy link
Author

@paulmedynski paulmedynski Feb 28, 2025

Choose a reason for hiding this comment

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

Formatted for readability, and then squished back into a single line since <Exec> treats each line in the Command as a separate command!

--filter "category!=non$(TargetGroup)tests&amp;category!=failing&amp;category!=nonwindowstests"
--logger:"trx;LogFilePrefix=Functional-Windows$(TargetGroup)-$(TestSet)"
</TestCommand>
<TestCommand>$(TestCommand.Replace($([System.Environment]::NewLine), " "))</TestCommand>
Copy link
Author

Choose a reason for hiding this comment

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

Modern dotnet tooling supports String.ReplaceLineEndings(), but we're using the old .NET Framework msbuild.exe tooling to build, so we can't have the nice toys :(

[MemberData(
nameof(CEKEncryptionReversalData)
#if NETFRAMEWORK
// .NET Framework puts system enums in something called the Global
Copy link
Author

Choose a reason for hiding this comment

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

I've left a comment once in each file where we're using DisableDiscoveryEnumeration, to make it clear why we're using that flag.

@@ -505,33 +519,25 @@ public override IEnumerable<Object[]> GetData(MethodInfo testMethod)
}
}

public class CEKEncryptionReversalParameters : DataAttribute
public static IEnumerable<object[]> CEKEncryptionReversalData()
Copy link
Author

Choose a reason for hiding this comment

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

Since xUnit only supports DisableDiscoveryEnumeration on MemberData attributes, I have converted all of the data sources to be compatible with MemberData.

You will see similar changes throughout the tests, where data source classes become methods.

[CEKEncryptionReversalParameters]
[MemberData(
nameof(CEKEncryptionReversalData)
#if NETFRAMEWORK
Copy link
Author

Choose a reason for hiding this comment

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

.NET doesn't have a GAC, so these tests will enumerate correctly for those targets. We only need to disable for .NET Framework targets.

@@ -4,6 +4,7 @@

using System;
using System.Runtime.InteropServices;
using System.Threading;
Copy link
Author

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 is necessary.

#endif
)]
[MemberData(
nameof(ConstructorTextData)
Copy link
Author

Choose a reason for hiding this comment

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

This adds Text to the mix, which seems to have been missing from the InlineData.

@@ -565,7 +584,20 @@ private void ExecuteAndCheckForError(SqlCommand sqlCmd, bool expectError)
try
{
sqlCmd.ExecuteNonQuery();
Assert.Fail("We should have gotten an error but passed instead.");
StringBuilder builder = new(
Copy link
Author

@paulmedynski paulmedynski Feb 28, 2025

Choose a reason for hiding this comment

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

With broken (now disabled) enumeration, xUnit doesn't include the test data in any failure output, so we need to do it ourselves.

This test fails for me on main as well, so I wanted to see what data set was causing the problem. Turns out to be the Date data set (line 1450).

@@ -1,6 +1,13 @@
{
// Typical Windows SQL Server on the local host via TCP.
Copy link
Author

Choose a reason for hiding this comment

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

These comments are breaking our CI "Update config.json" task because PowerShell's ConvertFrom-Json fails But as of PowerShell v6, ConvertFrom-Json handles comments:

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertfrom-json?view=powershell-7.5

Are we really using ancient PowerShell 5.1 from 2016? I will have to dig into this further.

- Emitting PowerShell version to debug JSON parsing failure.
- Changed config.json update step to use modern PowerShell via the "pwsh" shortcut instead of ancient PowerShell via the "powershell" shortcut.
@@ -126,7 +126,7 @@ parameters:

steps:
# All properties should be added here, and this template should be used for any manipulation of the config.json file.
- powershell: |
- pwsh: |
$PSVersionTable
Copy link
Author

Choose a reason for hiding this comment

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

Remove this once we solve the JSON-with-comments problem.

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