mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-16 21:00:14 +00:00
### Description Add test project that will perform an automated UI test that runs the unit tests on Android. ### Motivation - Enables end-to-end on-device MAUI unit testing which we want to add to the packaging pipelines ### Context Microsoft.ML.OnnxRuntime.Tests.MAUI uses DeviceRunners.VisualRunners to allow running the unit tests (found in Microsoft.ML.OnnxRuntime.Tests.Common) across multiple devices. DeviceRunners.VisualRunners provides a simple UI with a button that will run the unit tests and a panel with the unit test results. In order to automate the process of running the unit tests across mobile devices, Appium is used for UI testing orchestration (it provides a way to interact with the UI), and BrowserStack automatically runs these Appium tests across different mobile devices. This project does not include the capability to start an Appium server locally or attach to a local emulator or device. ## Build & run instructions ### Requirements * A BrowserStack account with access to App Automate * You can set BrowserStack credentials as environment variables as shown [here](https://www.browserstack.com/docs/app-automate/appium/getting-started/c-sharp/nunit/integrate-your-tests#CLI) * ONNXRuntime NuGet package 1. You can either download the [stable NuGet package](https://www.nuget.org/packages/Microsoft.ML.OnnxRuntime) then follow the instructions from [NativeLibraryInclude.props file](../Microsoft.ML.OnnxRuntime.Tests.Common/NativeLibraryInclude.props) to use the downloaded .nupkg file 2. Or follow the [build instructions](https://onnxruntime.ai/docs/build/android.html) to build the Android package locally * The dotnet workloads for maui and maui-android, which will not always automatically install correctly 1. `dotnet workload install maui` 2. `dotnet workload install maui-android` * [Appium](https://appium.io/docs/en/latest/quickstart/) and the [UiAutomator2 driver](https://appium.io/docs/en/latest/quickstart/uiauto2-driver/) ### Run instructions 1. Build the Microsoft.ML.OnnxRuntime.Tests.MAUI project into a signed APK. 1. Run the following: `dotnet publish -c Release -f net8.0-android` in the Microsoft.ML.OnnxRuntime.Tests.MAUI directory. 2. Search for the APK files generated. They should be located in `bin\Release\net8.0-android\publish`. 3. If they're in a different location, edit the `browserstack.yml` file to target the path to the signed APK. 2. Ensure you've set the BrowserStack credentials as environment variables. 3. Run the following in the Microsoft.ML.OnnxRuntime.Tests.Android.BrowserStack directory: `dotnet test` 4. Navigate to the [BrowserStack App Automate dashboard](https://app-automate.browserstack.com/dashboard/v2/builds) to see your test running!
123 lines
4.5 KiB
C#
123 lines
4.5 KiB
C#
using OpenQA.Selenium.Appium;
|
|
using OpenQA.Selenium;
|
|
using NUnit.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android
|
|
{
|
|
/// <summary>
|
|
/// This class contains a single test: RunAll, which interacts with the UI from
|
|
/// https://github.com/mattleibow/DeviceRunners/tree/main by clicking the "Run All" button and checking the number
|
|
/// of passed and failed tests.
|
|
///
|
|
/// It searches for elements on the page using Appium's WebDriver. These searches use the XPath attributes.
|
|
///
|
|
/// Launching the MAUI test app in Appium Inspector will allow you to see the exact XPath attributes for each
|
|
/// element.
|
|
/// </summary>
|
|
[TestFixture]
|
|
public class RunAllTest : BrowserStackTest
|
|
{
|
|
public AppiumElement FindAppiumElement(String xpathQuery, String text)
|
|
{
|
|
IReadOnlyCollection<AppiumElement> appiumElements = driver.FindElements(By.XPath(xpathQuery));
|
|
|
|
foreach (var element in appiumElements)
|
|
{
|
|
if (element.Text.Contains(text))
|
|
{
|
|
return element;
|
|
}
|
|
}
|
|
// was unable to find given element
|
|
throw new Exception(String.Format("Could not find {0}: {1} on the page.", xpathQuery, text));
|
|
}
|
|
|
|
public AppiumElement FindAppiumElementThenClick(String xpathQuery, String text)
|
|
{
|
|
AppiumElement appiumElement = FindAppiumElement(xpathQuery, text);
|
|
appiumElement.Click();
|
|
return appiumElement;
|
|
}
|
|
|
|
public (int, int) GetPassFailCount()
|
|
{
|
|
int numPassed = -1;
|
|
int numFailed = -1;
|
|
|
|
IReadOnlyCollection<AppiumElement> labelElements =
|
|
driver.FindElements(By.XPath("//android.widget.TextView"));
|
|
|
|
for (int i = 0; i < labelElements.Count; i++)
|
|
{
|
|
AppiumElement element = labelElements.ElementAt(i);
|
|
|
|
if (element.Text.Equals("✔"))
|
|
{
|
|
i++;
|
|
numPassed = int.Parse(labelElements.ElementAt(i).Text);
|
|
}
|
|
|
|
if (element.Text.Equals("⛔"))
|
|
{
|
|
i++;
|
|
numFailed = int.Parse(labelElements.ElementAt(i).Text);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Assert.That(numPassed, Is.GreaterThanOrEqualTo(0), "Could not find number passed label.");
|
|
Assert.That(numFailed, Is.GreaterThanOrEqualTo(0), "Could not find number failed label.");
|
|
|
|
return (numPassed, numFailed);
|
|
}
|
|
|
|
[Test]
|
|
public async Task ClickRunAllTest()
|
|
{
|
|
// XAML for the main page:
|
|
// https://github.com/mattleibow/DeviceRunners/blob/cba7644e07b305ba64dc930b01c3eee55ef2b93d/src/DeviceRunners.VisualRunners.Maui/App/Pages/HomePage.xaml
|
|
AppiumElement runAllButton = FindAppiumElementThenClick("//android.widget.Button", "Run All");
|
|
|
|
while (!runAllButton.Enabled)
|
|
{
|
|
// waiting for unit tests to execute
|
|
await Task.Delay(500);
|
|
}
|
|
|
|
var (numPassed, numFailed) = GetPassFailCount();
|
|
|
|
if (numFailed == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// click into test results if tests have failed
|
|
FindAppiumElementThenClick("//android.widget.TextView", "⛔");
|
|
await Task.Delay(500);
|
|
|
|
// Brings you to the test assembly page
|
|
// XAML for test assembly page:
|
|
// https://github.com/mattleibow/DeviceRunners/blob/cba7644e07b305ba64dc930b01c3eee55ef2b93d/src/DeviceRunners.VisualRunners.Maui/App/Pages/TestAssemblyPage.xaml
|
|
FindAppiumElementThenClick("//android.widget.EditText", "All");
|
|
await Task.Delay(100);
|
|
FindAppiumElementThenClick("//android.widget.TextView", "Failed");
|
|
await Task.Delay(500);
|
|
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.AppendLine("PASSED TESTS: " + numPassed + " | FAILED TESTS: " + numFailed);
|
|
|
|
IReadOnlyCollection<AppiumElement> textResults = driver.FindElements(By.XPath("//android.widget.TextView"));
|
|
foreach (var element in textResults)
|
|
{
|
|
sb.AppendLine(element.Text);
|
|
}
|
|
|
|
Assert.That(numFailed, Is.EqualTo(0), sb.ToString());
|
|
}
|
|
}
|
|
}
|