diff --git a/.github/workflows/build_artifacts.yml b/.github/workflows/build_artifacts.yml index 028e0a9511..04124bed57 100644 --- a/.github/workflows/build_artifacts.yml +++ b/.github/workflows/build_artifacts.yml @@ -55,7 +55,7 @@ jobs: uses: actions/upload-artifact@v7 with: name: Screenshots-${{ github.run_number }} - path: ${{ github.workspace }}\tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net9.0-windows\Screenshots + path: ${{ github.workspace }}\tests\MaterialDesignThemes.UITests\bin\${{ inputs.build-configuration }}\net10.0-windows\Screenshots if-no-files-found: ignore - name: Build NuGets diff --git a/Directory.packages.props b/Directory.packages.props index 7b6068480f..caf0d57aed 100644 --- a/Directory.packages.props +++ b/Directory.packages.props @@ -12,31 +12,31 @@ - - - - - + + + + + - + - + - + - - - + + + - + \ No newline at end of file diff --git a/tests/MaterialDesignThemes.UITests/AllStyles.cs b/tests/MaterialDesignThemes.UITests/AllStyles.cs index cf78a95deb..e7cd822b1b 100644 --- a/tests/MaterialDesignThemes.UITests/AllStyles.cs +++ b/tests/MaterialDesignThemes.UITests/AllStyles.cs @@ -5,6 +5,7 @@ namespace MaterialDesignThemes.UITests; public class AllStyles : TestBase { [Test] + [DoesNotRequireInteraction] [Arguments("Button", "MaterialDesignRaisedButton")] [Arguments("Calendar", "MaterialDesignCalendarPortrait")] [Arguments("CheckBox", "MaterialDesignCheckBox")] diff --git a/tests/MaterialDesignThemes.UITests/DoesNotRequireInteractionAttribute.cs b/tests/MaterialDesignThemes.UITests/DoesNotRequireInteractionAttribute.cs new file mode 100644 index 0000000000..c379435c2d --- /dev/null +++ b/tests/MaterialDesignThemes.UITests/DoesNotRequireInteractionAttribute.cs @@ -0,0 +1,16 @@ +using TUnit.Core.Interfaces; + +[assembly: NotInParallel("Default")] + +namespace MaterialDesignThemes.UITests; + +[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] +public sealed class DoesNotRequireInteractionAttribute : Attribute, ITestDiscoveryEventReceiver +{ + public ValueTask OnTestDiscovered(DiscoveredTestContext context) + { + context.AddParallelConstraint(new ParallelGroupConstraint("NoInteraction", 0)); + context.AddParallelConstraint(new NotInParallelConstraint([Guid.NewGuid().ToString()])); + return default; + } +} diff --git a/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj b/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj index cc91938039..86ee4a7191 100644 --- a/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj +++ b/tests/MaterialDesignThemes.UITests/MaterialDesignThemes.UITests.csproj @@ -1,4 +1,4 @@ - + net10.0-windows false @@ -19,6 +19,7 @@ + diff --git a/tests/MaterialDesignThemes.UITests/TUnitExtensions.cs b/tests/MaterialDesignThemes.UITests/TUnitExtensions.cs new file mode 100644 index 0000000000..401d13358b --- /dev/null +++ b/tests/MaterialDesignThemes.UITests/TUnitExtensions.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Linq.Expressions; +using System.Reflection; +using System.Text; +using Expression = System.Linq.Expressions.Expression; + +namespace MaterialDesignThemes.UITests; + +internal static class TUnitExtensions +{ + private const string GetDisplayNameMethodName = "GetDisplayName"; + + private static readonly Lazy> _getDisplayNameFunc = new(() => + { + var testContextType = typeof(TestContext); + MethodInfo? getDisplayNameMethod = testContextType.GetMethod( + GetDisplayNameMethodName, + BindingFlags.NonPublic | BindingFlags.Instance) + ?? throw new InvalidOperationException($"Could not find {GetDisplayNameMethodName} method on {testContextType.FullName}."); + + if (getDisplayNameMethod.ReturnType != typeof(string) || getDisplayNameMethod.GetParameters().Length != 0) + { + throw new InvalidOperationException( + $"{GetDisplayNameMethodName} on {testContextType.FullName} has an unexpected signature."); + } + + ParameterExpression testContextParameter = Expression.Parameter(testContextType, "testContext"); + MethodCallExpression callExpression = Expression.Call(testContextParameter, getDisplayNameMethod); + var lambdaExpression = Expression.Lambda>(callExpression, testContextParameter); + + return lambdaExpression.Compile(); + }); + + extension(TestContext testContext) + { + public string GetDisplayName() + => _getDisplayNameFunc.Value(testContext); + } +} diff --git a/tests/MaterialDesignThemes.UITests/TestBase.cs b/tests/MaterialDesignThemes.UITests/TestBase.cs index b80e7288e7..87017c67e8 100644 --- a/tests/MaterialDesignThemes.UITests/TestBase.cs +++ b/tests/MaterialDesignThemes.UITests/TestBase.cs @@ -2,13 +2,8 @@ using System.Windows.Media; using MaterialDesignThemes.UITests; using MaterialDesignThemes.Wpf.Internal; -using Microsoft.VisualStudio.TestPlatform.ObjectModel; -using Microsoft.VisualStudio.TestPlatform.Utilities; -using TUnit.Core; using TUnit.Core.Interfaces; -[assembly: ParallelLimiter] - [assembly: GenerateHelpers(typeof(AutoSuggestBox))] [assembly: GenerateHelpers(typeof(ColorPicker))] [assembly: GenerateHelpers(typeof(DecimalUpDown))] @@ -23,11 +18,15 @@ [assembly: GenerateHelpers(typeof(TreeListViewItem))] [assembly: GenerateHelpers(typeof(PaddedBringIntoViewStackPanel))] + +[assembly: ParallelLimiter] + + namespace MaterialDesignThemes.UITests; -public record SingleParallelLimit : IParallelLimit +public record ParallelLimit : IParallelLimit { - public int Limit => 1; + public int Limit => 10; } public abstract class TestBase @@ -63,12 +62,16 @@ protected async Task LoadUserControl(Type userControlType) return await App.CreateWindowWithUserControl(userControlType); } + private static bool IsNonInteractiveTest() + => TestContext.Current?.Metadata.TestDetails.GetAttributes().Any() == true; + public Task StartApp() { return XamlTest.App.StartRemote(new AppOptions { #if !DEBUG - MinimizeOtherWindows = !System.Diagnostics.Debugger.IsAttached, + // Minimizing other windows would also minimize the windows of tests running in parallel + MinimizeOtherWindows = !System.Diagnostics.Debugger.IsAttached && !IsNonInteractiveTest(), #endif AllowVisualStudioDebuggerAttach = AttachedDebuggerToRemoteProcess, LogMessage = Output.WriteLine diff --git a/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs b/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs index 5b4156b60f..de23246304 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/AutoSuggestBoxes/AutoSuggestTextBoxTests.cs @@ -2,6 +2,7 @@ using MaterialDesignThemes.UITests.Samples.AutoSuggestBoxes; using MaterialDesignThemes.UITests.Samples.AutoSuggestTextBoxes; using TUnit.Core.Exceptions; + namespace MaterialDesignThemes.UITests.WPF.AutoSuggestBoxes; public class AutoSuggestBoxTests : TestBase diff --git a/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs b/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs index 9158740a13..36546dd425 100644 --- a/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs +++ b/tests/MaterialDesignThemes.UITests/WPF/Buttons/OutlineButtonTests.cs @@ -5,6 +5,7 @@ namespace MaterialDesignThemes.UITests.WPF.Buttons; public class OutlineButtonTests : TestBase { [Test] + [DoesNotRequireInteraction] public async Task OutlinedButton_UsesThemeColorForBorder() { //Arrange @@ -23,15 +24,18 @@ public async Task OutlinedButton_UsesThemeColorForBorder() } [Test] + [DoesNotRequireInteraction] public async Task OutlinedButton_BorderCanBeOverridden() { //Arrange var button = await LoadXaml