Skip to content

Commit a14b855

Browse files
[Testing] Rework Catalyst Test Runner to use startup arguments instead of UI navigation (dotnet#31673)
### Description of Change #### This PR reopens the work from the closed [dotnet#30651](dotnet#30651) This pull request introduces functionality to streamline test execution by allowing tests to be launched directly via startup arguments or programmatically. Key changes include adding support for passing test names as environment variables, introducing a `PageFactory` mechanism for dynamic page creation, and enhancing test lifecycle management for specific platforms like Mac Catalyst. Note: This PR is an extension of the PR(dotnet#30286) with a proper implementation. #### Test Execution Enhancements: - **Startup Argument Support**: Added logic to retrieve test names from environment variables and dynamically load the corresponding test page in `CreateDefaultMainPage()` (`MauiProgram.cs`). - **Dynamic Page Creation**: Introduced a `PageFactory` property in the `IssueModel` class to enable dynamic test page instantiation (`TestCases.cs`). - **Direct Test Page Retrieval**: Implemented `TryToGetTestPage()` in `TestCaseScreen` to retrieve test pages by description using `PageFactory` (`TestCases.cs`). #### Platform-Specific Test Lifecycle Improvements: - **Mac Catalyst Test Configuration**: Enhanced `_IssuesUITest` to pass test names as startup arguments and manage app launch/close lifecycle specifically for Mac Catalyst (`_IssuesUITest.cs`). [[1]](https://github.com/dotnet/maui/pull/30651/files#diff-6e8c0ea1f2979b5484d14facb1aa5b2ccef3ee748f1606eaf46220ac0936e3edR22-R46) [[2]](https://github.com/dotnet/maui/pull/30651/files#diff-6e8c0ea1f2979b5484d14facb1aa5b2ccef3ee748f1606eaf46220ac0936e3edR58-R61) - ** Appium Options for Mac Catalyst**: Updated `AppiumCatalystApp` to include environment variables in Appium options for test execution (`AppiumCatalystApp.cs`). #### Helper Methods for Test Execution: - **Parameterized App Launch**: Added a method to launch apps with additional parameters, supporting test-specific configurations (`HelperExtensions.cs`). - **Mac-Specific App Closure**: Modified `FixtureOneTimeTearDown()` to handle app closure for Mac Catalyst during test teardown (`UITestBase.cs`). ### Output https://github.com/user-attachments/assets/82fc12ad-b0d3-4bad-901f-0ab6b2bddda1 ### Issues Fixed Fixes dotnet#30285
1 parent a1abaf8 commit a14b855

File tree

113 files changed

+448
-457
lines changed

Some content is hidden

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

113 files changed

+448
-457
lines changed

src/Controls/tests/TestCases.HostApp/CoreViews/CorePageView.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,25 @@ public Task<bool> NavigateToGalleryPage(string pageTitle)
193193
return Task.FromResult(false);
194194
}
195195

196+
/// <summary>
197+
/// Attempts to retrieve a gallery page by title.
198+
/// </summary>
199+
/// <param name="pageTitle">The title of the gallery page to find.</param>
200+
/// <returns>The Page instance if found; otherwise, null.</returns>
201+
/// <remarks>
202+
/// This method searches for a matching gallery page by title (case-insensitive).
203+
/// If a match is found, it invokes the associated Realize factory to create the page.
204+
/// </remarks>
205+
public Page TryToGetGalleryPage(string pageTitle)
206+
{
207+
if (_titleToPage.TryGetValue(pageTitle.ToLowerInvariant(), out GalleryPageFactory pageFactory))
208+
{
209+
return pageFactory.Realize();
210+
}
211+
212+
return null;
213+
}
214+
196215
public async Task<bool> NavigateToTest(string pageTitle)
197216
{
198217
var testCaseScreen = new TestCases.TestCaseScreen();

src/Controls/tests/TestCases.HostApp/Issues/Bugzilla/Bugzilla53179.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class TestPage : ContentPage
2222

2323
public TestPage(int index)
2424
{
25-
nextBtn = new Button { AutomationId = "Next Page", Text = "Next Page" };
25+
nextBtn = new Button { AutomationId = $"Next Page {index}", Text = $"Next Page {index}" };
2626
rmBtn = new Button { AutomationId = "Remove previous pages", Text = "Remove previous pages" };
2727
popBtn = new Button { AutomationId = "Back", Text = "Back" };
2828

src/Controls/tests/TestCases.HostApp/Issues/Bugzilla/Bugzilla53834.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ protected override void Init()
4444
lstView = new ListView()
4545
{
4646
IsGroupingEnabled = true,
47+
VerticalScrollBarVisibility = ScrollBarVisibility.Never,
4748
HasUnevenRows = true,
4849
ItemTemplate = new DataTemplate(typeof(MyViewCell)),
4950
GroupHeaderTemplate = new DataTemplate(typeof(MyHeaderViewCell)),

src/Controls/tests/TestCases.HostApp/Issues/CollectionViewVisibility.cs

Lines changed: 0 additions & 31 deletions
This file was deleted.

src/Controls/tests/TestCases.HostApp/Issues/Issue18161.xaml.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ async void Issue18161_Loaded(object sender, EventArgs e)
1313
{
1414
// https://github.com/dotnet/maui/issues/13496
1515
await Task.Yield();
16+
#if MACCATALYST
17+
await Task.Delay(500); // Add delay for MacCatalyst when page is loaded directly as window root
18+
#endif
1619
this.IsPresented = true;
1720
}
1821

src/Controls/tests/TestCases.HostApp/Issues/Issue19657.xaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
33
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
44
x:Class="Maui.Controls.Sample.Issues.Issue19657"
5+
xmlns:local="clr-namespace:Maui.Controls.Sample"
56
xmlns:ns="clr-namespace:Maui.Controls.Sample.Issues">
67
<ScrollView>
78
<Grid x:Name="contentGrid">
@@ -20,7 +21,7 @@
2021

2122
<Label HorizontalOptions="Center" x:Name="WaitHere" Text="Check if the Carousel items all show up" AutomationId="WaitHere" Background="Red"/>
2223

23-
<CarouselView x:Name="carousel"
24+
<local:CarouselView2 x:Name="carousel"
2425
ItemTemplate="{StaticResource SampleItemTemplate}"
2526
Loop="False"
2627
HeightRequest="220"

src/Controls/tests/TestCases.HostApp/Issues/Issue7144.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Issue7144()
3333
return image;
3434
});
3535

36-
CarouselView carouselView = new CarouselView
36+
CarouselView2 carouselView = new CarouselView2
3737
{
3838
ItemsSource = Items,
3939
Loop = false,

src/Controls/tests/TestCases.HostApp/Issues/XFIssue/Issue1939.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ async void FillResults(GroupedData results, int items, bool clear)
5757
if (!clear)
5858
return;
5959

60-
await Task.Delay(1000);
60+
await Task.Delay(1500);
6161

6262
results.Clear();
6363
}

src/Controls/tests/TestCases.HostApp/MauiProgram.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,31 @@ public static Page CreateDefaultMainPage()
6868
{
6969
Page mainPage = null;
7070
OverrideMainPage(ref mainPage);
71+
#if MACCATALYST
72+
// Check for startup test argument from environment variables (passed by test runner)
73+
var testName = System.Environment.GetEnvironmentVariable("test");
74+
75+
if (!string.IsNullOrEmpty(testName))
76+
{
77+
// Try to get the test page directly from issues/test cases
78+
var testCaseScreen = new TestCases.TestCaseScreen();
79+
var testPage = testCaseScreen.TryToGetTestPage(testName);
80+
if (testPage is not null)
81+
{
82+
// Return the actual test page
83+
return testPage;
84+
}
85+
86+
// If not found in test cases, try to get gallery page
87+
var corePageView = new CorePageView(null);
88+
var galleryPage = corePageView.TryToGetGalleryPage(testName);
89+
if (galleryPage is not null)
90+
{
91+
// Return the gallery page
92+
return galleryPage;
93+
}
94+
}
95+
#endif
7196
return mainPage ?? new CoreNavigationPage();
7297
}
7398
}

src/Controls/tests/TestCases.HostApp/TestCases.cs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Diagnostics.CodeAnalysis;
22
using System.Reflection;
3+
using System.Linq;
34

45
namespace Maui.Controls.Sample
56
{
@@ -123,6 +124,7 @@ class IssueModel
123124
public string Description { get; set; }
124125
public bool IsInternetRequired { get; set; }
125126
public Action Action { get; set; }
127+
public Func<Page> PageFactory { get; set; }
126128

127129
public bool Matches(string filter)
128130
{
@@ -195,7 +197,9 @@ public TestCaseScreen()
195197
Name = attribute.DisplayName,
196198
Description = attribute.Description,
197199
IsInternetRequired = attribute.IsInternetRequired,
198-
Action = ActivatePageAndNavigate(attribute, type)
200+
Action = ActivatePageAndNavigate(attribute, type),
201+
// PageFactory is used to retrieve the instance of the page.
202+
PageFactory = () => ActivatePage(type)
199203
}).ToList();
200204
#endif
201205

@@ -238,6 +242,23 @@ public bool TryToNavigateTo(string name)
238242
return true;
239243
}
240244

245+
246+
/// <summary>
247+
/// Attempts to retrieve a test page by name or description.
248+
/// </summary>
249+
/// <param name="name">The name or description of the test page to find.</param>
250+
/// <returns>The Page instance if found; otherwise, null.</returns>
251+
/// <remarks>
252+
/// This method first searches for a matching issue by name (case-insensitive),
253+
/// then by description if no match is found by name. If a match is found,
254+
/// it invokes the associated PageFactory to create the page.
255+
/// </remarks>
256+
public Page TryToGetTestPage(string name)
257+
{
258+
var issue = _issues.SingleOrDefault(x => string.Equals(x.Description, name, StringComparison.OrdinalIgnoreCase));
259+
return issue?.PageFactory?.Invoke();
260+
}
261+
241262
public void FilterIssues(string filter = null)
242263
{
243264
filter = filter?.Trim();

0 commit comments

Comments
 (0)