Skip to content

[testing] Migrate NUnit tests to xUnit framework #29978

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

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@
<PackageReference Include="Microsoft.CodeAnalysis" Version="4.5.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.5.0" PrivateAssets="All" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="xunit" Version="$(XunitPackageVersion)" />
</ItemGroup>

<ItemGroup>
Expand Down
16 changes: 8 additions & 8 deletions src/Controls/tests/SourceGen.UnitTests/SourceGenCssTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.Maui.Controls.SourceGen;
using NUnit.Framework;
using Xunit;

using static Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen.SourceGeneratorDriver;

Expand All @@ -14,7 +14,7 @@ public class SourceGenCssTests : SourceGenTestsBase
private record AdditionalCssFile(string Path, string Content, string? RelativePath = null, string? TargetPath = null, string? ManifestResourceName = null, string? TargetFramework = null)
: AdditionalFile(Text: SourceGeneratorDriver.ToAdditionalText(Path, Content), Kind: "Css", RelativePath: RelativePath ?? Path, TargetPath: TargetPath, ManifestResourceName: ManifestResourceName ?? Path, TargetFramework: TargetFramework);

[Test]
[Fact]
public void TestCodeBehindGenerator_BasicCss()
{
var css =
Expand All @@ -28,14 +28,14 @@ public void TestCodeBehindGenerator_BasicCss()
var cssFile = new AdditionalCssFile("Test.css", css);
var result = SourceGeneratorDriver.RunGenerator<CodeBehindGenerator>(compilation, cssFile);

Assert.IsFalse(result.Diagnostics.Any());
Assert.False(result.Diagnostics.Any());

var generated = result.Results.Single().GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(generated.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", StringComparison.Ordinal));
Assert.True(generated.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", StringComparison.Ordinal));
}

[Test]
[Fact]
public void TestCodeBehindGenerator_ModifiedCss()
{
var css =
Expand All @@ -61,10 +61,10 @@ public void TestCodeBehindGenerator_ModifiedCss()
var output1 = result1.GeneratedSources.Single().SourceText.ToString();
var output2 = result2.GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.AreEqual(output1, output2);
Assert.True(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.Equal(output1, output2);

Assert.IsTrue(output1.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", StringComparison.Ordinal));
Assert.True(output1.Contains($"XamlResourceId(\"{cssFile.ManifestResourceName}\", \"{cssFile.Path}\"", StringComparison.Ordinal));

(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
using NUnit.Framework;
using Xunit;

namespace Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen;

Expand All @@ -12,7 +12,7 @@ public static void VerifyStepRunReasons(GeneratorRunResult result2, Dictionary<s
foreach (var expected in expectedReasons)
{
var actualReason = result2.TrackedSteps[expected.Key].Single().Outputs.Single().Reason;
Assert.AreEqual(expected.Value, actualReason, message: expected.Key);
Assert.Equal(expected.Value, actualReason);
}
}
}
40 changes: 20 additions & 20 deletions src/Controls/tests/SourceGen.UnitTests/SourceGenXamlTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.Maui.Controls.SourceGen;
using NUnit.Framework;
using Xunit;

using static Microsoft.Maui.Controls.Xaml.UnitTests.SourceGen.SourceGeneratorDriver;

Expand All @@ -14,7 +14,7 @@ public class SourceGenXamlTests : SourceGenTestsBase
private record AdditionalXamlFile(string Path, string Content, string? RelativePath = null, string? TargetPath = null, string? ManifestResourceName = null, string? TargetFramework = null)
: AdditionalFile(Text: SourceGeneratorDriver.ToAdditionalText(Path, Content), Kind: "Xaml", RelativePath: RelativePath ?? Path, TargetPath: TargetPath, ManifestResourceName: ManifestResourceName, TargetFramework: TargetFramework);

[Test]
[Fact]
public void TestCodeBehindGenerator_BasicXaml()
{
var xaml =
Expand All @@ -30,14 +30,14 @@ public void TestCodeBehindGenerator_BasicXaml()
var compilation = SourceGeneratorDriver.CreateMauiCompilation();
var result = SourceGeneratorDriver.RunGenerator<CodeBehindGenerator>(compilation, new AdditionalXamlFile("Test.xaml", xaml));

Assert.IsFalse(result.Diagnostics.Any());
Assert.False(result.Diagnostics.Any());

var generated = result.Results.Single().GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(generated.Contains("Microsoft.Maui.Controls.Button MyButton", StringComparison.Ordinal));
Assert.True(generated.Contains("Microsoft.Maui.Controls.Button MyButton", StringComparison.Ordinal));
}

[Test]
[Fact]
public void TestCodeBehindGenerator_LocalXaml()
{
var xaml =
Expand All @@ -54,14 +54,14 @@ public void TestCodeBehindGenerator_LocalXaml()
var compilation = SourceGeneratorDriver.CreateMauiCompilation();
var result = SourceGeneratorDriver.RunGenerator<CodeBehindGenerator>(compilation, new AdditionalXamlFile("Test.xaml", xaml));

Assert.IsFalse(result.Diagnostics.Any());
Assert.False(result.Diagnostics.Any());

var generated = result.Results.Single().GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(generated.Contains("Test.TestControl MyTestControl", StringComparison.Ordinal));
Assert.True(generated.Contains("Test.TestControl MyTestControl", StringComparison.Ordinal));
}

[Test]
[Fact]
public void TestCodeBehindGenerator_CompilationClone()
{
var xaml =
Expand All @@ -83,8 +83,8 @@ public void TestCodeBehindGenerator_CompilationClone()
var output1 = result1.GeneratedSources.Single().SourceText.ToString();
var output2 = result2.GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.AreEqual(output1, output2);
Assert.True(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.Equal(output1, output2);

(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
Expand All @@ -104,7 +104,7 @@ public void TestCodeBehindGenerator_CompilationClone()
VerifyStepRunReasons(result2, expectedReasons);
}

[Test]
[Fact]
public void TestCodeBehindGenerator_ReferenceAdded()
{
var xaml =
Expand All @@ -126,8 +126,8 @@ public void TestCodeBehindGenerator_ReferenceAdded()
var output1 = result1.GeneratedSources.Single().SourceText.ToString();
var output2 = result2.GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.AreEqual(output1, output2);
Assert.True(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.Equal(output1, output2);

(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
Expand All @@ -147,7 +147,7 @@ public void TestCodeBehindGenerator_ReferenceAdded()
VerifyStepRunReasons(result2, expectedReasons);
}

[Test]
[Fact]
public void TestCodeBehindGenerator_ModifiedXaml()
{
var xaml =
Expand Down Expand Up @@ -180,13 +180,13 @@ public void TestCodeBehindGenerator_ModifiedXaml()
var output1 = result1.GeneratedSources.Single().SourceText.ToString();
var output2 = result2.GeneratedSources.Single().SourceText.ToString();

Assert.IsTrue(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.AreNotEqual(output1, output2);
Assert.True(result1.TrackedSteps.All(s => s.Value.Single().Outputs.Single().Reason == IncrementalStepRunReason.New));
Assert.NotEqual(output1, output2);

Assert.IsTrue(output1.Contains("MyButton", StringComparison.Ordinal));
Assert.IsFalse(output1.Contains("MyButton2", StringComparison.Ordinal));
Assert.IsTrue(output2.Contains("MyButton", StringComparison.Ordinal));
Assert.IsTrue(output2.Contains("MyButton2", StringComparison.Ordinal));
Assert.True(output1.Contains("MyButton", StringComparison.Ordinal));
Assert.False(output1.Contains("MyButton2", StringComparison.Ordinal));
Assert.True(output2.Contains("MyButton", StringComparison.Ordinal));
Assert.True(output2.Contains("MyButton2", StringComparison.Ordinal));

(GeneratorDriver, Compilation) ApplyChanges(GeneratorDriver driver, Compilation compilation)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,90 +1,13 @@
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Commands;

namespace Microsoft.Maui.TestCases.Tests
namespace Microsoft.Maui.TestCases.Tests;

public class FlakyTestAttribute : IgnoreAttribute
{
/// <summary>
/// Custom NUnit attribute to mark a test as flaky, allowing retries (by default 2).
/// If after the retries the test fails, can ignore it.
/// Note: This attribute should be used temporarily until the test is changed.
/// </summary>
/// <example>
/// <code>
/// [FlakyTest("Description with details of the test that sometimes fails.", retryCount: 2, ignore: true)]
/// </code>
/// </example>
internal class FlakyTestAttribute : Attribute, IWrapTestMethod, IWrapSetUpTearDown
public FlakyTestAttribute() : base(nameof(FlakyTestAttribute))
{
}
public FlakyTestAttribute(string reason) : base(reason)
{
readonly string _ignoreMessage;
readonly int _retryCount;
readonly bool _ignore;

public FlakyTestAttribute(string message, int retryCount = 2, bool ignore = true)
{
_ignoreMessage = message;
_retryCount = retryCount;
_ignore = ignore;
}

public ActionTargets Targets => ActionTargets.Suite | ActionTargets.Test;

public TestCommand Wrap(TestCommand command)
{
return new CustomRetryCommand(command, _ignoreMessage, _retryCount, _ignore);
}

public class CustomRetryCommand : DelegatingTestCommand
{
readonly string _ignoreMessage;
readonly int _retryCount;
readonly bool _ignore;

int _failedAttempts = 0;

public CustomRetryCommand(TestCommand innerCommand, string ignoreMessage, int retryCount, bool ignore)
: base(innerCommand)
{
_ignoreMessage = ignoreMessage;
_retryCount = retryCount;
_ignore = ignore;
}

public override TestResult Execute(TestExecutionContext context)
{
int count = _retryCount;
while (count-- > 0)
{
context.CurrentResult = innerCommand.Execute(context);
var results = context.CurrentResult.ResultState;

if (results.Equals(ResultState.Error)
|| results.Equals(ResultState.Failure)
|| results.Equals(ResultState.SetUpError)
|| results.Equals(ResultState.SetUpFailure)
|| results.Equals(ResultState.TearDownError)
|| results.Equals(ResultState.ChildFailure)
|| results.Equals(ResultState.Cancelled))
{
_failedAttempts++;
TestExecutionContext.CurrentContext.OutWriter.WriteLine("Test Failed on attempt #" + _failedAttempts);
}
else
{
TestExecutionContext.CurrentContext.OutWriter.WriteLine("Test Passed on attempt #" + (_failedAttempts + 1));
break;
}
}

// If want to ignore and all retry attempts fail, ignore the test with the provided message.
if (_ignore && _failedAttempts == _retryCount)
{
context.CurrentResult.SetResult(ResultState.Ignored, _ignoreMessage);
}

return context.CurrentResult;
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class FontImageUITest : _IssuesUITest
{
public override string Issue => "FontImage UI Test";

public FontImageUITest(TestDevice device)
: base(device)
{ }

[Test]
[Category(UITestCategories.Image)]
public void VerifyFontImage()
{
App.WaitForElement("Image");
VerifyScreenshot();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues;

public class Issue14497 : _IssuesUITest
{
public Issue14497(TestDevice device) : base(device) { }

public override string Issue => "Dynamically setting SearchHandler Query property does not update text in the search box";
const string ChangeSearchText = "ChangeSearchText";

[Test]
[Category(UITestCategories.Shell)]
public void DynamicallyQueryNotUpdating()
{
App.WaitForElement(ChangeSearchText);
App.Tap(ChangeSearchText);
var searchHandlerString = App.GetShellSearchHandler().GetText();
Assert.That(searchHandlerString, Is.EqualTo("Hello World"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue27614 : _IssuesUITest
{
public Issue27614(TestDevice testDevice) : base(testDevice)
{
}

public override string Issue => "Label not sized correctly on Android";

[Test, Order(1)]
[Category(UITestCategories.Label)]
public void LabelShouldSizeCorrectlyOnHorizontalStartLayoutOptions()
{
App.WaitForElement("Label");
VerifyScreenshot();
}

[Test, Order(2)]
[Category(UITestCategories.Label)]
public void LabelShouldSizeCorrectlyOnHorizontalCenterLayoutOptions()
{
App.WaitForElement("CenterButton");
App.Tap("CenterButton");
VerifyScreenshot();
}

[Test, Order(3)]
[Category(UITestCategories.Label)]
public void LabelShouldSizeCorrectlyOnHorizontalEndLayoutOptions()
{
App.WaitForElement("EndButton");
App.Tap("EndButton");
VerifyScreenshot();
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if TEST_FAILS_ON_WINDOWS && TEST_FAILS_ON_IOS && TEST_FAILS_ON_ANDROID // Windows Character Spacing Issue Link - https://github.com/dotnet/maui/issues/29493
#if TEST_FAILS_ON_WINDOWS // Windows Character Spacing Issue Link - https://github.com/dotnet/maui/issues/29493
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;
Expand Down
Loading
Loading