Skip to content

Commit f31fe78

Browse files
authored
Updating tests to use TUnit and MTP (#3838)
* Updating to xUnit v3 1.x * Adding MTP https://devblogs.microsoft.com/dotnet/mtp-adoption-frameworks/ * Starting conversion to TUnit * Tests all compile * Adds cancellation tokens to async delays Ensures that asynchronous delay calls use cancellation tokens to allow for tests to be cancelled correctly. * WIP * Refactors test suite and updates dependencies Updates the test suite to use TUnit for improved test clarity and maintainability. Removes unused xunit packages and addresses nullable warnings in RatingBar converters. Also includes changes to CustomColorTheme, DataGridAssist, DialogHost, DrawerHost, FlipperAssist, Internal/TreeListViewItemsCollection, Label, MaterialDesignThemes.Wpf.Tests.csproj, MdixHelper, PackIcon, PopupBox, RatingBar, SnackbarMessageQueue, TextBlock, TextBox, Theme and Transitioner tests. * Updates test framework and fixes assertions Updates test framework from Fact to Test. Updates tests to use Assert.That for improved readability and consistency. * Reverting stupid * Save point * Assert.True * Updates tests to be async Updates tests to be async to prevent possible deadlocks and improve reliability. * Removes TUnit dependencies from tests Removes the TUnit library and associated code from test projects, modernizing testing using the default testing framework. * Tests are now compiling * Updates test framework for DecimalUpDown Converts the DecimalUpDown test to use the `Arguments` attribute and updates assertions to improve reliability and clarity. * Fixing member data sources Updates TimePicker unit tests to use MethodDataSource with Func to prevent test data from being eagerly evaluated, resolving issues with the test framework. * Refactors code for brevity and adds tests Updates collection initialization to use more concise syntax. Adds tests for the ButtonProgressAssist, CheckBoxAssist, ColorPicker, and DataGridAssist classes. Adds a new test executor and removes redundant STAThreadExecutor attributes. Adds NotInParallel attribute to CalendarFormatInfoTests and DialogHostTests. Refactors the PreviewIndicatorTransformXConverter and PreviewIndicatorTransformYConverter. * Updates screenshot artifact path Updates the path for screenshot artifacts to target the .NET 9 framework. * Fixes artifact upload path Corrects the artifact upload path in the build workflow. * Updates coordinate assertion method Uses IsCloseTo method for asserting coordinate proximity in UI tests for ComboBoxes, DatePickers, PasswordBoxes, and TextBoxes. This improves the accuracy and reliability of the tests by checking if the coordinates are within a specified tolerance range. * Updates NuGet package versions Updates several NuGet package versions, including Microsoft.NET.Test.Sdk, TUnit, and XAMLTest. Fixes a potential issue in a test case by using CancellationToken.None instead of TestContext.Current!.CancellationToken * Fixes UI test failures Corrects failing UI tests by adjusting assertions and adding exception handling. The fixes improve the stability and reliability of the UI test suite. * Fixes combo box test assertion Updates test assertion to expect a null text value when a combo box is uninitialized. This corrects the expected behavior of the test. * Updates artifact path for .NET 9 Updates the artifact upload path in the build workflow to correctly target the .NET 9 framework. This resolves an issue where artifacts were not being correctly uploaded due to an incorrect target framework name. * Adds success recorder in auto suggest box tests * Skips flaky GetDialogSession test * Skips failing saturation drag test Skips a ColorPicker test that was failing before the move to Machine.Time.Past due to timing issues in the while loop. * Ensures DialogHost is properly unloaded Introduces a `ControlHost` class to ensure the `DialogHost` is properly unloaded when the test is complete. This prevents orphaned `DialogHost` instances from interfering with subsequent tests.
1 parent bbdee06 commit f31fe78

File tree

85 files changed

+2520
-2539
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

85 files changed

+2520
-2539
lines changed

.github/workflows/build_artifacts.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
uses: actions/upload-artifact@v4
5555
with:
5656
name: Screenshots-${{ github.run_number }}
57-
path: ${{ github.workspace }}tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net8.0-windows7\Screenshots
57+
path: ${{ github.workspace }}\tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net9.0-windows\Screenshots
5858
if-no-files-found: ignore
5959

6060
- name: Build NuGets

Directory.packages.props

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<Project>
22
<ItemGroup>
33
<PackageVersion Include="BluwolfIcons" Version="1.0.1" />
4-
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.2.2" />
4+
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
55
<PackageVersion Include="Dragablz" Version="0.0.3.234" />
6-
<PackageVersion Include="GitHubActionsTestLogger" Version="2.3.3" />
6+
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
77
<PackageVersion Include="Humanizer" Version="2.14.1" />
88
<PackageVersion Include="MahApps.Metro" Version="2.4.10" />
99
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" PrivateAssets="all" />
@@ -14,7 +14,7 @@
1414
<PackageVersion Include="Microsoft.Composition" Version="1.0.31" />
1515
<PackageVersion Include="Microsoft.CSharp" Version="4.7.0" />
1616
<PackageVersion Include="Microsoft.NETCore.Platforms" Version="7.0.4" />
17-
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
17+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
1818
<PackageVersion Include="Microsoft.Toolkit.MVVM" Version="7.1.2" />
1919
<PackageVersion Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.77" />
2020
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
@@ -24,11 +24,10 @@
2424
<PackageVersion Include="ShowMeTheXAML.MSBuild" Version="2.0.0" />
2525
<PackageVersion Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
2626
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
27+
<PackageVersion Include="System.Private.Uri" Version="4.3.2" />
2728
<PackageVersion Include="System.Text.RegularExpressions" Version="4.3.1" />
29+
<PackageVersion Include="TUnit" Version="0.25.21" />
2830
<PackageVersion Include="VirtualizingWrapPanel" Version="1.5.8" />
29-
<PackageVersion Include="XAMLTest" Version="1.3.0-ci602" />
30-
<PackageVersion Include="xunit" Version="2.6.2" />
31-
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.4" />
32-
<PackageVersion Include="Xunit.StaFact" Version="1.1.11" />
31+
<PackageVersion Include="XAMLTest" Version="1.3.0-ci616" />
3332
</ItemGroup>
3433
</Project>

src/MaterialDesignColors.Wpf/SwatchesProvider.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace MaterialDesignColors;
1212
/// </summary>
1313
public class SwatchesProvider
1414
{
15+
private static readonly object _syncLock = new();
1516
/// <summary>
1617
/// Generates an instance reading swatches from the provided assembly, allowing
1718
/// colours outside of the standard material palette to be loaded provided the are stored in the expected XAML format.
@@ -39,12 +40,7 @@ public SwatchesProvider(Assembly assembly)
3940
Read(assemblyName, x.SingleOrDefault(y => y.match.Groups["type"].Value == "primary")?.key),
4041
Read(assemblyName, x.SingleOrDefault(y => y.match.Groups["type"].Value == "secondary")?.key)
4142
))
42-
.ToList() ??
43-
#if NETCOREAPP3_1_OR_GREATER
44-
(IEnumerable<Swatch>)Array.Empty<Swatch>();
45-
#else
46-
(IEnumerable<Swatch>)new Swatch[0];
47-
#endif
43+
.ToList() ?? [];
4844
}
4945

5046
/// <summary>
@@ -98,8 +94,12 @@ static Hue GetHue(ResourceDictionary dictionary, DictionaryEntry entry)
9894
if (assemblyName is null || path is null)
9995
return null;
10096

101-
return (ResourceDictionary)Application.LoadComponent(new Uri(
102-
$"/{assemblyName};component/{path.Replace(".baml", ".xaml")}",
103-
UriKind.RelativeOrAbsolute));
97+
lock (_syncLock)
98+
{
99+
//NB: Application.LoadComponent is not thread safe
100+
return (ResourceDictionary)Application.LoadComponent(new Uri(
101+
$"/{assemblyName};component/{path.Replace(".baml", ".xaml")}",
102+
UriKind.RelativeOrAbsolute));
103+
}
104104
}
105105
}

src/MaterialDesignThemes.Wpf/DialogHost.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public class DialogHost : ContentControl
5050
/// </summary>
5151
public static readonly RoutedCommand CloseDialogCommand = new();
5252

53-
private static readonly HashSet<WeakReference<DialogHost>> LoadedInstances = new();
53+
private static readonly HashSet<WeakReference<DialogHost>> LoadedInstances = [];
5454

5555
private DialogOpenedEventHandler? _asyncShowOpenedEventHandler;
5656
private DialogClosingEventHandler? _asyncShowClosingEventHandler;
@@ -221,7 +221,7 @@ private static DialogHost GetInstance(object? dialogIdentifier)
221221
if (LoadedInstances.Count == 0)
222222
throw new InvalidOperationException("No loaded DialogHost instances.");
223223

224-
List<DialogHost> targets = new();
224+
List<DialogHost> targets = [];
225225
foreach (var instance in LoadedInstances.ToList())
226226
{
227227
if (instance.TryGetTarget(out DialogHost? dialogInstance))

src/MaterialDesignThemes.Wpf/Internal/TreeListViewItemsCollection.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ namespace MaterialDesignThemes.Wpf.Internal;
66

77
public class TreeListViewItemsCollection : ObservableCollection<object?>
88
{
9-
private List<int> ItemLevels { get; } = new();
10-
private List<bool> ItemIsExpanded { get; } = new();
9+
private List<int> ItemLevels { get; } = [];
10+
private List<bool> ItemIsExpanded { get; } = [];
1111

1212
public TreeListViewItemsCollection(object? wrappedSource)
1313
{

src/MaterialDesignThemes.Wpf/RatingBar.cs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ internal class TextBlockForegroundConverter : IMultiValueConverter
378378

379379
public static TextBlockForegroundConverter Instance { get; } = new();
380380

381-
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
381+
public object? Convert(object?[]? values, Type targetType, object? parameter, CultureInfo culture)
382382
{
383383
if (values?.Length == 5
384384
&& values[0] is SolidColorBrush brush
@@ -411,28 +411,28 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur
411411
return new SolidColorBrush(semiTransparent);
412412
}
413413

414-
GradientStopCollection CreateGradientStopCollection(Color originalColor, Color semiTransparent, double offset, bool invertDirection)
414+
static GradientStopCollection CreateGradientStopCollection(Color originalColor, Color semiTransparent, double offset, bool invertDirection)
415415
{
416416
if (invertDirection)
417417
{
418-
return new()
419-
{
420-
new GradientStop {Color = semiTransparent, Offset = offset},
421-
new GradientStop {Color = originalColor, Offset = offset},
422-
};
423-
}
424-
return new()
425-
{
418+
return
419+
[
420+
new GradientStop {Color = semiTransparent, Offset = offset},
426421
new GradientStop {Color = originalColor, Offset = offset},
427-
new GradientStop {Color = semiTransparent, Offset = offset}
428-
};
422+
];
423+
}
424+
return
425+
[
426+
new GradientStop {Color = originalColor, Offset = offset},
427+
new GradientStop {Color = semiTransparent, Offset = offset}
428+
];
429429
}
430430

431431
// This should never happen (returning actual brush to avoid the compilers squiggly line warning)
432432
return Brushes.Transparent;
433433
}
434434

435-
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
435+
public object?[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) => throw new NotImplementedException();
436436
}
437437

438438
internal class PreviewIndicatorTransformXConverter : IMultiValueConverter
@@ -441,9 +441,9 @@ internal class PreviewIndicatorTransformXConverter : IMultiValueConverter
441441

442442
internal static double Margin => 2.0;
443443

444-
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
444+
public object? Convert(object?[]? values, Type targetType, object? parameter, CultureInfo culture)
445445
{
446-
if (values.Length >= 7
446+
if (values?.Length >= 7
447447
&& values[0] is double ratingBarButtonActualWidth
448448
&& values[1] is double previewValueActualWidth
449449
&& values[2] is Orientation ratingBarOrientation
@@ -482,7 +482,7 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur
482482
return 1.0;
483483
}
484484

485-
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
485+
public object?[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) => throw new NotImplementedException();
486486
}
487487

488488
internal class PreviewIndicatorTransformYConverter : IMultiValueConverter
@@ -491,9 +491,9 @@ internal class PreviewIndicatorTransformYConverter : IMultiValueConverter
491491

492492
internal static double Margin => 2.0;
493493

494-
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
494+
public object? Convert(object?[]? values, Type targetType, object? parameter, CultureInfo culture)
495495
{
496-
if (values.Length >= 7
496+
if (values?.Length >= 7
497497
&& values[0] is double ratingBarButtonActualHeight
498498
&& values[1] is double previewValueActualHeight
499499
&& values[2] is Orientation ratingBarOrientation
@@ -531,6 +531,6 @@ public object Convert(object[] values, Type targetType, object parameter, Cultur
531531
return 1.0;
532532
}
533533

534-
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) => throw new NotImplementedException();
534+
public object?[]? ConvertBack(object? value, Type[] targetTypes, object? parameter, CultureInfo culture) => throw new NotImplementedException();
535535
}
536536
}

src/MaterialDesignThemes.Wpf/ResourceDictionaryExtensions.g.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//------------------------------------------------------------------------------
22
// <auto-generated>
3-
// This code was generated by mdresgen.
3+
// This code was generated by MaterialDesignToolkit.ResourceGeneration.
44
// </auto-generated>
55
//------------------------------------------------------------------------------
66

src/MaterialDesignThemes.Wpf/Theme.g.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//------------------------------------------------------------------------------
22
// <auto-generated>
3-
// This code was generated by mdresgen.
3+
// This code was generated by MaterialDesignToolkit.ResourceGeneration.
44
// </auto-generated>
55
//------------------------------------------------------------------------------
66

src/MaterialDesignThemes.Wpf/ThemeExtensions.g.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//------------------------------------------------------------------------------
22
// <auto-generated>
3-
// This code was generated by mdresgen.
3+
// This code was generated by MaterialDesignToolkit.ResourceGeneration.
44
// </auto-generated>
55
//------------------------------------------------------------------------------
66

src/MaterialDesignToolkit.ResourceGeneration/Brushes.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ void WriteBrush(Brush brush, string name)
482482
{{indent}}{{indent}}{
483483
{{indent}}{{indent}}{{indent}}IVisualElement<TextBlock> textBlock = await panel.GetElement<TextBlock>("[Text=\"{{name}}\"]");
484484
{{indent}}{{indent}}{{indent}}Color? textBlockBackground = await textBlock.GetBackgroundColor();
485-
{{indent}}{{indent}}{{indent}}Assert.Equal(await GetResourceColor("{{brush.Name}}"), textBlockBackground);
485+
{{indent}}{{indent}}{{indent}}await Assert.That(textBlockBackground).IsEqualTo(await GetResourceColor("{{brush.Name}}"));
486486
{{indent}}{{indent}}}
487487
""");
488488
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
using System.Windows.Media;
22
using MaterialDesignColors.ColorManipulation;
3-
using Xunit;
43

54
namespace MaterialDesignColors.Wpf.Tests;
65

76
public class ColorAssistTests
87
{
9-
[Fact]
10-
public void EnsureContrastRatio_AdjustsColor()
8+
[Test]
9+
public async Task EnsureContrastRatio_AdjustsColor()
1110
{
1211
var background = Color.FromRgb(0xFA, 0xFA, 0xFA);
1312
var foreground = Color.FromRgb(0xFF, 0xC1, 0x07);
1413

1514
var adjusted = foreground.EnsureContrastRatio(background, 3.0f);
1615

1716
double contrastRatio = adjusted.ContrastRatio(background);
18-
Assert.True(contrastRatio >= 2.9);
19-
Assert.True(contrastRatio <= 3.1);
17+
await Assert.That(contrastRatio).IsGreaterThanOrEqualTo(2.9);
18+
await Assert.That(contrastRatio).IsLessThanOrEqualTo(3.1);
2019
}
2120
}

tests/MaterialDesignColors.Wpf.Tests/MaterialDesignColors.Wpf.Tests.csproj

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
<TargetFrameworks>net472;net8.0-windows</TargetFrameworks>
55
<AssemblyTitle>MaterialDesignColors.Wpf.Tests</AssemblyTitle>
66
<Product>MaterialDesignColors.Wpf.Tests</Product>
7+
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
8+
<OutputType>Exe</OutputType>
9+
<TestingPlatformDotnetTestSupport>true</TestingPlatformDotnetTestSupport>
710
</PropertyGroup>
811
<ItemGroup Condition="'$(TargetFramework)'=='net472'">
912
<Reference Include="PresentationCore" />
@@ -25,9 +28,9 @@
2528
<PrivateAssets>all</PrivateAssets>
2629
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2730
</PackageReference>
28-
<PackageReference Include="xunit" />
29-
<PackageReference Include="xunit.runner.visualstudio" />
30-
<PackageReference Include="Shouldly" />
31-
<PackageReference Include="Microsoft.NET.Test.Sdk" />
31+
<PackageReference Include="System.Net.Http" />
32+
<PackageReference Include="System.Private.Uri" />
33+
<PackageReference Include="System.Text.RegularExpressions" />
34+
<PackageReference Include="TUnit" />
3235
</ItemGroup>
3336
</Project>
Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,62 @@
1-
using Shouldly;
2-
using Xunit;
3-
4-
namespace MaterialDesignColors.Wpf.Fixture;
1+
namespace MaterialDesignColors.Wpf.Tests;
52

63
public class ResourceProviderFixture
74
{
8-
[Fact]
9-
public void ExcludesBlack()
5+
[Test]
6+
public async Task ExcludesBlack()
107
{
118
SwatchesProvider swatchesProvider = new ();
129

1310
bool containsBlack = swatchesProvider.Swatches.Any(
1411
swatch => string.Compare(swatch.Name, "Black", StringComparison.InvariantCultureIgnoreCase) == 0);
1512

16-
containsBlack.ShouldBe(false);
13+
await Assert.That(containsBlack).IsFalse();
1714
}
1815

19-
[Fact]
20-
public void IncludesGrey()
16+
[Test]
17+
public async Task IncludesGrey()
2118
{
2219
SwatchesProvider swatchesProvider = new ();
2320

2421
bool containsBlack = swatchesProvider.Swatches.Any(
2522
swatch => string.Compare(swatch.Name, "Grey", StringComparison.InvariantCultureIgnoreCase) == 0);
2623

27-
containsBlack.ShouldBe(true);
24+
await Assert.That(containsBlack).IsTrue();
2825
}
2926

30-
[Fact]
31-
public void BrownHasNoSecondary()
27+
[Test]
28+
public async Task BrownHasNoSecondary()
3229
{
3330
SwatchesProvider swatchesProvider = new ();
3431

3532
var brownSwatch = swatchesProvider.Swatches.Single(
3633
swatch => swatch.Name == "brown");
3734

38-
brownSwatch.SecondaryHues.ShouldNotBeNull();
39-
brownSwatch.SecondaryHues.Count.ShouldBe(0);
35+
await Assert.That(brownSwatch.SecondaryHues).IsNotNull();
36+
await Assert.That(brownSwatch.SecondaryHues.Count).IsEqualTo(0);
4037
}
4138

42-
[Fact]
43-
public void BrownHasPrimaries()
39+
[Test]
40+
public async Task BrownHasPrimaries()
4441
{
4542
SwatchesProvider swatchesProvider = new ();
4643

4744
var brownSwatch = swatchesProvider.Swatches.Single(
4845
swatch => swatch.Name == "brown");
4946

50-
brownSwatch.PrimaryHues.ShouldNotBeNull();
51-
brownSwatch.PrimaryHues.Count.ShouldBe(10);
47+
await Assert.That(brownSwatch.PrimaryHues).IsNotNull();
48+
await Assert.That(brownSwatch.PrimaryHues.Count).IsEqualTo(10);
5249
}
5350

54-
[Fact]
55-
public void IndigoHasSecondaries()
51+
[Test]
52+
public async Task IndigoHasSecondaries()
5653
{
5754
SwatchesProvider swatchesProvider = new ();
5855

5956
var brownSwatch = swatchesProvider.Swatches.Single(
6057
swatch => swatch.Name == "indigo");
6158

62-
brownSwatch.SecondaryHues.ShouldNotBeNull();
63-
brownSwatch.SecondaryHues.Count.ShouldBe(4);
59+
await Assert.That(brownSwatch.SecondaryHues).IsNotNull();
60+
await Assert.That(brownSwatch.SecondaryHues.Count).IsEqualTo(4);
6461
}
6562
}

0 commit comments

Comments
 (0)