Running tests together with Appium

When it comes to mobile automation testing, there are many different choices for a test tool. One popular option is Appium, an open source project which enables running automated tests on both Android and iOS devices.

No registration is needed and you can either download the latest version of the standalone app here, or you can install the cli version by running:

> brew install node      # get node.js
> npm install -g appium  # get appium
> npm install wd         # get appium client
> appium &               # start appium

We’ve created an example python project for AltTester® Unity SDK together with Appium, which can be found here. It can help you get started on your own projects and will automatically install the requirements needed for running the tests. More details about it below.

Why use Appium together with AltTester® Unreal SDK

There’s a couple of reasons/scenarios for which you would want to use both of these frameworks:

  • By itself, AltTester® Unreal SDK cannot launch an app on a device. If you want to run tests in a pipeline, or by using cloud services, you can either create a script which will start your app, or you can use Appium before the tests execution;

  • AltTester® Unreal SDK cannot perform some types of actions, such as interacting with any native popups your app might have, or putting the app in the background and resuming it. In any of these cases you can use Appium to do the things that AltTester® Unreal SDK can’t.

AltTester® Unreal SDK with Appium example

We currently provide an example project that demonstrates how to use AltTester® Unity SDK together with Appium. You can find it here: AltTester Unity SDK with Appium example.

Even though the project uses a Unity game, the Appium setup (capabilities, driver initialization and reverse port forwarding for AltTester®) is the same when testing Unreal builds that integrate AltTester® Unreal SDK. You can follow the instructions from the Unity example and apply the same configuration values (such as app package/bundle id, device UDID, etc.) for your Unreal application.

Connection settings popup for cloud/Appium flows

When running AltTester® Unreal SDK builds in the cloud and driving them with Appium, you might not know in advance which app name to use from your test scripts to connect to the correct instrumented instance. To address this, AltTester® Unreal SDK provides an optional native connection settings popup that can be shown in the app.

The popup allows you to:

  • Enter the AltTester® Server host;

  • Enter the AltTester® Server port;

  • Enter the app name that will be used by the tests when connecting;

  • Check “Don’t show this again” to prevent the popup from appearing on subsequent launches.

Because the popup is built using native UI elements, you can fully interact with it from Appium: locate the fields and buttons using your preferred locator strategy (for example accessibility id, xpath, or text), type the desired host, port and app name values, and confirm the dialog before starting your AltTester® tests.

Whether this popup is shown or not is controlled by a dedicated setting in AltTester® Unreal SDK. Enable this setting when you want the popup to appear (for example in cloud/Appium runs where connection details are provided dynamically), and disable it when you prefer to configure connection parameters directly in your game or test code without any additional UI.

Examples: identifying and interacting with the popup in Appium

Below is a simple example that shows how you can identify and fill in the connection settings popup with Appium before starting your AltTester® tests.

public static void SetConnectionData(AppiumDriver appiumDriver, string? host = null, string? port = null, string? appName = null, bool dontShowThisAgain = false, int timeout = 60)
{
    if (appiumDriver == null)
    {
        throw new ArgumentNullException(nameof(appiumDriver), "Appium driver cannot be null");
    }
    
    // Set a longer implicit wait to ensure elements are found during connection setup
    appiumDriver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(timeout);

    try
    {
        // Update host if provided
        if (!string.IsNullOrEmpty(host))
        {
            var hostField = appiumDriver.FindElement(MobileBy.AccessibilityId("AltTesterHostInputField"));
            hostField.Clear();
            hostField.SendKeys(host);
        }

        // Update port if provided
        if (!string.IsNullOrEmpty(port))
        {
            var portField = appiumDriver.FindElement(MobileBy.AccessibilityId("AltTesterPortInputField"));
            portField.Clear();
            portField.SendKeys(port);
        }

        // Update app name if provided
        if (!string.IsNullOrEmpty(appName))
        {
            var appNameField = appiumDriver.FindElement(MobileBy.AccessibilityId("AltTesterAppNameInputField"));
            appNameField.Clear();
            appNameField.SendKeys(appName);
        }

        // Set "Don't show this again" if specified
        if (dontShowThisAgain)
        {
            var dontShowAgainCheckbox = appiumDriver.FindElement(MobileBy.AccessibilityId("AltTesterDontShowAgainCheckbox"));
            if (!dontShowAgainCheckbox.Selected)
            {
                dontShowAgainCheckbox.Click();
            }
        }

        // Press OK button
        var okButton = appiumDriver.FindElement(MobileBy.AccessibilityId("AltTesterOkButton"));
        okButton.Click();
    }
    catch (ArgumentException)
    {
        throw;
    }
    catch (Exception ex)
    {
        throw new AppiumHelperException($"Error while setting connection data: {ex.Message}", ex);
    }
}