-
Notifications
You must be signed in to change notification settings - Fork 1.8k
UITests
To run the tests on iOS or Catalyst, you'll need a Mac. To run the tests on Windows, you'll need a Windows machine. Android tests can be run from either platform.
├── Controls
│ ├── tests
│ ├── ├── Controls.TestCases.App
│ │ ├── Controls.TestCases.Shared.Tests
- Controls.TestCases.App: .NET MAUI Sample used for the automated UI tests
- Controls.TestCases.Shared.Tests: .NET MAUI library used to define the UI tests
Each platform has a specific UI tests library project where it is possible to add specific tests per platform.
├── Controls
│ ├── tests
│ │ ├── Controls.TestCases.Android.Tests
│ │ ├── Controls.TestCases.iOS.Tests
│ │ ├── Controls.TestCases.Mac.Tests
│ │ ├── Controls.TestCases.WinUI.Tests
https://github.com/dotnet/maui/blob/main/docs/design/UITesting.md
- make sure a
dotnet tool restore
on the repo home - Make sure Developer Mode is turned on in Windows Settings
- Install LTS version of nodejs https://nodejs.org
- Install Windows App Driver from https://github.com/microsoft/WinAppDriver/releases/tag/v1.2.1
- Validate you have on your path %USERPROFILE%\AppData\Roaming\npm
- Note: you may need to restart your machine for this to take effect
- dotnet pwsh .\eng\scripts\appium-install.ps1
- Ignore "apkanalyzer.bat could NOT be found" error from appium-doctor
- make sure to run
dotnet tool restore
on the repo home
- Install LTS version of nodejs https://nodejs.org
- To install Appium run the following as sudo https://github.com/dotnet/maui/tree/main/eng/scripts/appium-install.ps1
sudo dotnet pwsh /path/to/scripts/appium-install.ps1
- brew install node
- To install Appium run the following script https://github.com/dotnet/maui/tree/main/eng/scripts/appium-install.ps1
dotnet pwsh /path/to/scripts/appium-install.ps1
-
You will need to setup the
ANDROID_HOME
andJAVA_HOME
environment variables so that Appium andandroid.cake
can find them.- https://developer.android.com/tools/variables
- Development guide has instructions for setting these variables on a MAC.
-
Ensure that you have the Android API 30 SDK installed, with the emulator image for Play store on x86/x64. By default, the tests use that. See screenshot below. If you want to use another image you can specify the
--device
argument, with something like--device="android-emulator-64_33"
where the 64 means image x86_x64 and 33 indicates the API level.
Build and run the host app. For Android & iOS, the proper emulator/simulator image is launched.
Android:
./build.ps1 -Script eng/devices/android.cake --target=uitest-build
./build.ps1 -Script eng/devices/android.cake --target=uitest-prepare
iOS:
./build.ps1 -Script eng/devices/ios.cake --target=uitest-build
./build.ps1 -Script eng/devices/ios.cake --target=uitest-prepare
Windows: Launch Controls.TestCases.HostApp
from the IDE
Catalyst: Launch Controls.TestCases.HostApp
from the IDE
- Build the
Controls.AppiumTests.csproj
so the tests show up on the Test Explorer - Run the tests
- If you don't have your development environment already setup, please consult the development guide.
- For Windows & Catalyst, you'll want to deploy the host app first. Go to the Run and Debug window and select the correct project:
However, this will just load the test in the app. To have Appium drive the test, you’ll need to run them in the Testing pane in VS Code. Before that, make sure to build the project where your test is located:
- Ensure that you are in Explorer.
- Expand the Solution Explorer
- Find the project that your test is located in.
- Right click and select build.
Now if you click on the Testing icon, you will see the test that you were working on. Click the play icon to launch your test:
Android
./build.ps1 -Script eng/devices/android.cake --target=uitest-build
./build.ps1 -Script eng/devices/android.cake --target=uitest
iOS
./build.ps1 -Script eng/devices/ios.cake --target=uitest-build
./build.ps1 -Script eng/devices/ios.cake --target=uitest
Windows
./build.ps1 -Script eng/devices/windows.cake --target=uitest-build
./build.ps1 -Script eng/devices/windows.cake --target=uitest
Catalyst
./build.ps1 -Script eng/devices/catalyst.cake --target=dotnet-samples --catalyst --verbosity=diagnostic --usenuget=false
./build.ps1 -Script eng/devices/catalyst.cake --target=uitest --apiversion="10.13" --configuration="Release" --device=mac
You can pass any of the filters that are compatible with dotnet test
dotnet cake eng/devices/android.cake --target=uitest --test-filter="TestCategory=Border"
Below you can find an equivalent table between Xamarin.UITest and Appium.
Action | Description | Xamarin.UITest | Appium (.NET MAUI) | Example |
---|---|---|---|---|
Back | Navigate back. | public void Back (); | public void Back (); | App.Back(); |
BackgroundApp | Send the currently running app for this session to the background. | - | public void BackgroundApp(); | App.BackgroundApp(); |
ForegroundApp | If the application is already running then it will be brought to the foreground. | - | public void ForegroundApp(); | App.ForegroundApp(); |
ClearText | Clears text. | public void ClearText (string marked); | public void ClearText (string marked); | App.ClearText("AutomationId"); |
ClearText | Clears text from a matching element that supports it. | public void ClearText (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppWebQuery> query); | public void ClearText (IQuery query); | |
DismissKeyboard | Hides keyboard if present | public void DismissKeyboard (); | public void DismissKeyboard (); | App.DismissKeyboard(); |
IsKeyboardShown | Whether or not the soft keyboard is shown. | - | public bool IsKeyboardShown(); | bool result = App.IsKeyboardShown(); |
DimissAlert | Dismisses the alert. | - | public void DimissAlert(); | App.DimissAlert(); |
DoubleTap | Performs two quick tap / touch gestures. | public void DoubleTap (string marked); | public void DoubleTap (string marked); | App.DoubleTap("AutomationId"); |
DoubleTap | Performs two quick tap / touch gestures on the matched element. If multiple elements are matched, the first one will be used. | public void DoubleTap (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> query); | public void DoubleTap (IQuery query); | |
DoubleClick | Performs two quick mouse clicks. | - | public void DoubleClick (string marked); | App.DoubleClick("AutomationId"); |
DoubleTapCoordinates | Performs a quick double tap / touch gesture on the given coordinates. | public void DoubleTapCoordinates (float x, float y); | public void DoubleTapCoordinates (float x, float y); | App.DoubleTapCoordinates(100, 100); |
DragAnDrop | Drags the from element to the to element. | public void DragAndDrop (string from, string to); | public void DragAndDrop (string from, string to); | App.DragAnDrop("from", "to"); |
DragAnDrop | Drags the from element to the to element. | public void DragAndDrop (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> from, Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> to); | public void DragAndDrop (IQuery from, IQuery to); | |
DragCoordinates | Performs a continuous drag gesture between 2 points. | public void DragCoordinates (float fromX, float fromY, float toX, float toY); | public void DragCoordinates (float fromX, float fromY, float toX, float toY); | App.DragCoordinates(0, 0, 100, 100); |
EnterText | Enters text into the currently focused element. | public void EnterText (string marked, string text); | public void EnterText (string marked, string text); | App.EnterText("AutomationId", "Text"); |
EnterText | Enters text into a matching element that supports it. | public void EnterText (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppWebQuery> query, string text); | public void EnterText (IQuery query, string text); | |
Flash | Highlights the results of the query by making them flash. | public Xamarin.UITest.Queries.AppResult[] Flash (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> query = null); | - | - |
IncreaseStepper | Increases the value of a Stepper control. | - | public void IncreaseStepper(string marked); | App.IncreaseStepper("AutomationId"); |
DecreaseStepper | Decreases the value of a Stepper control. | - | public void DecreaseStepper(string marked); | App.DecreaseStepper("AutomationId"); |
Invoke | Invokes a method on the app's main activity for Android and app delegate for iOS. | public object Invoke (string methodName, object[] arguments); | - | - |
LongPress | Performs a long mouse click on the matched element. | - | public static void LongPress(string element) | App.LongPress("AutomationId"); |
Lock | Lock the screen. Functionality that's only available on Android and iOS. | - | public void Lock(); | App.Lock(); |
Unlock | Unlock the screen. Functionality that's only available on Android and iOS. | - | public void Unlock(); | App.Unlock(); |
Pan | Performs a pan gesture between 2 points. | - | public void Pan(float fromX, float fromY, float toX, float toY) | App.Pan(0, 0, 100, 100); |
PincToZoomIn | Performs a pinch gestures on the matched element to zoom the view in. | public void PinchToZoomIn (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> query, Nullable duration = null); | public void PinchToZoomIn (string marked, Nullable duration = null); | App.PincToZoomIn("AutomationId"); |
PinchToZoomInCoordinates | Performs a pinch gestures to zoom the view in on the given coordinates. | public void PinchToZoomInCoordinates (float x, float y, Nullable duration); | public void PinchToZoomInCoordinates (float x, float y, Nullable duration); | App.PinchToZoomInCoordinates(100, 100); |
PincToZoomOut | Performs a pinch gestures on the matched element to zoom the view out. | public void PinchToZoomOut (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> query, Nullable duration = null); | public void PinchToZoomOut (string marked, Nullable duration = null); | App.PincToZoomOut("AutomationId"); |
PinchToZoomOutCoordinates | Performs a pinch gestures to zoom the view in on the given coordinates. | public void PinchToZoomOutCoordinates (float x, float y, Nullable duration); | public void PinchToZoomOutCoordinates (float x, float y, Nullable duration); | App.PinchToZoomOutCoordinates(100, 100); |
PressEnter | Presses the enter key in the app. | public void PressEnter (); | public void PressEnter (); | App.PressEnter(); |
PressVolumeDown | Presses the volume down button on the device. | public void PressVolumeDown (); | public void PressVolumeDown (); | App.PressVolumeDown(); |
PressVoumeUp | Presses the volume up button on the device. | public void PressVolumeUp (); | public void PressVolumeUp (); | App.PressVoumeUp(); |
Query | Queries web view objects using the fluent API. Defaults to only return view objects that are visible. | public Xamarin.UITest.Queries.AppWebResult[] Query (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppWebQuery> query); | - | - |
QueryUntilPresent | Repeatedly executes a query until it returns a non-empty value or the specified retry count is reached. | public static T QueryUntilPresent(Func func, int retryCount = 10, int delayInMs = 2000); | public static T QueryUntilPresent(Func func, int retryCount = 10, int delayInMs = 2000); | App.QueryUntilPresent(() => App.WaitForElement("success")); |
QueryUntilNotPresent | Repeatedly executes a query until it returns a null value or the specified retry count is reached. | public static T QueryUntilNotPresent(Func func, int retryCount = 10, int delayInMs = 2000); | public static T QueryUntilNotPresent(Func func, int retryCount = 10, int delayInMs = 2000); | |
Repl | Starts an interactive REPL (Read-Eval-Print-Loop) for app exploration and pauses test execution until it is closed. | public void Repl (); | - | - |
Screenshot | Takes a screenshot of the app in it's current state. | public System.IO.FileInfo Screenshot (string title); | public System.IO.FileInfo Screenshot (string title); | App.Screenshot("Sample"); |
StartRecording | Start recording screen. Functionality that's only available on Android, iOS and Windows. | - | public void StartRecording(); | App.StartRecording(); |
StopRecording | Stop recording screen. Functionality that's only available on Android, iOS and Windows. | - | public void StopRecording(); | App.StopRecording(); |
SetLightMode | Sets light device's theme. | - | public void SetLightMode(); | App.SetLightMode(); |
SetDarkMode | Sets dark device's theme. | - | public void SetDarkMode(); | App.SetDarkMode(); |
ToggleWifi | Switch the state of the wifi service. Functionality that's only available on Android. | - | public void ToggleWifi(); | App.ToggleWifi(); |
ToggleAirplane | Toggle airplane mode on device. Functionality that's only available on Android. | - | public void ToggleAirplane(); | App.TogleAirplane(); |
VerifyScreenshot | Takes a screenshot and compare it pixel by pixel with a reference one using the specified name or the test name. | - | public void VerifyScreenshot(string? name = null); | VerifyScreenshot(); |
ScrollDown | Scrolls down on the first element matching query. | public void ScrollDown (string withinMarked, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | public void ScrollDown(string marked, ScrollStrategy strategy = ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | App.ScrollDown("CollectionView", ScrollStrategy.Gesture, 0.5); |
ScrollDownTo | Scroll down until an element that matches the toQuery is shown on the screen. | public void ScrollDownTo (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> toQuery, Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> withinQuery = null, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true, Nullable timeout = null); | public void ScrollDownTo (IQuery toQuery, string withinMarked, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true, Nullable timeout = null); | - |
ScrollTo | Scroll until an element that matches the toMarkedis shown on the screen. | public void ScrollTo (string toMarked, string withinMarked = null, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true, Nullable timeout = null); | public static void ScrollTo(string toElementId, bool down = true); | App.ScrollTo("Item10", true); |
ScrollUp | Scrolls up on the first element matching query. | public void ScrollUp (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> query = null, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | public static void ScrollUp(string marked, ScrollStrategy strategy = ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | App.ScrollUp("CollectionView", ScrollStrategy.Gesture, 0.5); |
ScrollUpTo | Scroll up until an element that matches the toQuery is shown on the screen. | public void ScrollUpTo (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> toQuery, Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> withinQuery = null, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true, Nullable timeout = null); | public void ScrollUpTo (IQuery toQuery, string withinMarked, Xamarin.UITest.ScrollStrategy strategy = Xamarin.UITest.ScrollStrategy.Auto, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true, Nullable timeout = null); | - |
SetOrientationLandscape | Changes the device (iOS) or current activity (Android) orientation to landscape mode. | public void SetOrientationLandscape (); | public void SetOrientationLandscape (); | App.SetOrientationLandscape(); |
SetOrientationPortrait | Changes the device (iOS) or current activity (Android) orientation to portrait mode. | public void SetOrientationPortrait (); | public void SetOrientationPortrait (); | App.SetOrientationPortrait(); |
SetSliderValue | Sets the value of a slider element that matches marked. | public void SetSliderValue (string marked, double value); | public void SetSliderValue (string marked, double value); | App.SetSliderValue("AutomationId", 4); |
Shake | Simulate the device shaking. Functionality that's only available on iOS. | - | public void Shake(); | App.Shake(); |
SwipeLeftToRight | Performs a left to right swipe gesture on an element matched by 'query'. | public void SwipeLeftToRight (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppWebQuery> query, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | - | - |
SwipeLeftToRight | Performs a left to right swipe gesture on the matching element. If multiple elements are matched, the first one will be used. | public void SwipeLeftToRight (string marked, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | public void SwipeLeftToRight(double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | |
SwipeRightToLeft | Performs a right to left swipe gesture on an element matched by 'query'. | public void SwipeRightToLeft (Func<Xamarin.UITest.Queries.AppQuery,Xamarin.UITest.Queries.AppQuery> query, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | - | - |
SwipeRightToLeft | Performs a right to left swipe gesture on the matching element. If multiple elements are matched, the first one will be used. | public void SwipeRightToLeft (string marked, double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | public void SwipeRightToLeft(double swipePercentage = 0.67, int swipeSpeed = 500, bool withInertia = true); | |
Tap | Performs a tap / touch gesture on the matched element. If multiple elements are matched, the first one will be used. | public void Tap (string marked); | public void Tap (string marked); | App.Tap("AutomationId"); |
TapCoordinates | Performs a tap / touch gesture on the given coordinates. | public void TapCoordinates (float x, float y); | public void TapCoordinates (float x, float y); | App.TapCoordinates(100, 100); |
TouchAndHold | Performs a continuous touch gesture on the matched element. If multiple elements are matched, the first one will be used. | public void TouchAndHold (string marked); | public void TouchAndHold (string marked); | App.TouchAndHold("AutomationId"); |
TouchAndHoldCoordinates | Performs a continuous touch gesture on the given coordinates. | public void TouchAndHoldCoordinates (float x, float y); | public void TouchAndHoldCoordinates (float x, float y); | App.TouchAndHoldCoordinates(100, 100); |
WaitFor | Generic wait function that will repeatly call the predicatefunction until it returns true. Throws a TimeoutExceptionif the predicate is not fullfilled within the time limit. | public void WaitFor (Func predicate, string timeoutMessage = "Timed out waiting...", Nullable timeout = null, Nullable retryFrequency = null, Nullable postTimeout = null); | - | - |
WaitForElement | Wait function that will repeatly query the app until a matching element is found. Throws a TimeoutExceptionif no element is found within the time limit. | public Xamarin.UITest.Queries.AppResult[] WaitForElement (string marked, string timeoutMessage = "Timed out waiting for element...", Nullable timeout = null, Nullable retryFrequency = null, Nullable postTimeout = null); | public IUElement WaitForElement (string marked, string timeoutMessage = "Timed out waiting for element...", Nullable timeout = null, Nullable retryFrequency = null, Nullable postTimeout = null); | App.WaitForElement("AutomationId"); |
WaitForNoElement | Wait function that will repeatly query the app until a matching element is no longer found. Throws aTimeoutExceptionif the element is visible at the end of the time limit. | public void WaitForNoElement (string marked, string timeoutMessage = "Timed out waiting for no element...", Nullable timeout = null, Nullable retryFrequency = null, Nullable postTimeout = null); | public void WaitForNoElement (string marked, string timeoutMessage = "Timed out waiting for no element...", Nullable timeout = null, Nullable retryFrequency = null, Nullable postTimeout = null); | App.WaitForNoElement("Selected: Item 1"); |
- Try starting
appium
from the command line to get a better error messagenode /usr/local/lib/node_modules/appium/build/lib/main.js