Advanced Usage

Build games from the command line

To build your game from command line you need a static method in your project that handles the build logic.
To instrument your game with AltUnity Server, your build method must define AltUnity Tester and must insert AltUnity Prefab in the first scene of the game.

Depending on your project’s setup, there are two ways in which games can be built from the command line:

1. If you already have a custom build method for your game

If you already have a custom build method for your game, you can add the following two lines to your build method:

AltUnityBuilder.AddAltUnityTesterInScritpingDefineSymbolsGroup(BuildTargetGroup.Android);
AltUnityBuilder.InsertAltUnityInScene(FirstSceneOfTheGame);

Note

Change BuildTargetGroup above to the target group for which you are building.

2. If you create a new custom build method for your game

The following example script can be used.
It sets all the project settings needed and uses the same two important lines from point 1 above.

This example method is configured for the Android platform, so make sure to update it based on your target platform.

static void BuildFromCommandLine () {
    try {

        BuildPlayerOptions buildPlayerOptions = new BuildPlayerOptions ();
        buildPlayerOptions.scenes = new string[] {
            "Assets/AltUnityTesterExamples/Scenes/Scene 1 AltUnityDriverTestScene.unity",
            "Assets/AltUnityTesterExamples/Scenes/Scene 2 Draggable Panel.unity",
            "Assets/AltUnityTesterExamples/Scenes/Scene 3 Drag And Drop.unity",
            "Assets/AltUnityTesterExamples/Scenes/Scene 4 No Cameras.unity",
            "Assets/AltUnityTesterExamples/Scenes/Scene 5 Keyboard Input.unity",
            "Assets/AltUnityTesterExamples/Scenes/Scene6.unity"
        };

        buildPlayerOptions.locationPathName = "sampleGame.apk";
        buildPlayerOptions.target = BuildTarget.Android;
        buildPlayerOptions.options = BuildOptions.Development | BuildOptions.AutoRunPlayer;

        // Setup for AltUnity
        AltUnityBuilder.AddAltUnityTesterInScritpingDefineSymbolsGroup (BuildTargetGroup.Android);
        AltUnityBuilder.InsertAltUnityInScene (buildPlayerOptions.scenes[0]);

        var results = BuildPipeline.BuildPlayer (buildPlayerOptions);
        AltUnityBuilder.RemoveAltUnityTesterFromScriptingDefineSymbols (BuildTargetGroup.Android);

    } catch (Exception exception) {
        Debug.LogException (exception);
    }

}

The following command is used to call the build method:

<UnityPath>/Unity -projectPath $CI_PROJECT_DIR -executeMethod BuilderClass.BuildFromCommandLine -logFile logFile.log -quit

You can find more information about the build command and arguments here.

Note

After building from the command line you can run the tests by using the commands from the next section.

Run tests from the command line

In order to run tests from the command line you can use the following example commands:

<UnityPath>/Unity -projectPath $PROJECT_DIR -executeMethod AltUnityTestRunner.RunTestFromCommandLine -tests MyFirstTest.TestStartGame -logFile logFile.log -batchmode -quit
mvn test
python <nameOfYourTestFile.py>

Run tests on a Continuous Integration Server

  1. Instrument your game build with altUnity Tester from Unity or by building from the command line.

  2. Start the game build on a device.

  3. Run your tests - see commands in the “Run tests from the command line” section.

An example CI configuration file can be viewed in the AltUnity Tester GitLab repository.

What is port forwarding and when to use it

Port forwarding, or tunneling, is the behind-the-scenes process of intercepting data traffic headed for a computer’s IP/port combination and redirecting it to a different IP and/or port.

When you run your game instrumented with AltUnity Server, on a device, you need to tell your AltUnity Driver how to connect to it.

Port forwarding can be set up either through a command line command or in the test code by using the methods available in AltUnity classes.

The following are some cases when Port Forwarded is needed:

  1. Connect to the game running on a USB connected device

  2. Connect to multiple devices running the game

How to setup port forwarding

Port forwarding can be set up in two ways:

  • through a command line command (using adb / IProxy) or

  • in the test code by using the methods available in AltUnity classes.

  • Have ADB installed and added in PATH Environment Variables (check this article for more information on ADB)

  • Click on the refresh button in the Port Forwarding section in the Editor

  • Forward the port using the following command:

    adb [-s UDID] forward tcp:local_port tcp:device_port

  • Install IProxy: brew install libimobiledevice

  • Click on the refresh button in the Port Forwarding section in the Editor

  • Forward the port using the following command:

    iproxy LOCAL_TCP_PORT DEVICE_TCP_PORT [UDID]

Set up the path to ADB in AltUnity Editor window by writting it in the Adb Path input field. Use the following static methods (from the AltUnityPortHandler class) in your test file:

  • ForwardAndroid (string deviceId = “”, int localPort = 13000, int remotePort = 13000)

  • RemoveForwardAndroid (int localPort = -1, string deviceId = “”)

Example test file:

using NUnit.Framework;
using Assets.AltUnityTester.AltUnityDriver;
using Assets.AltUnityTester.AltUnityDriver.UnityStruct;

public class MyFirstTest
{
  private AltUnityDriver altUnityDriver;

  [OneTimeSetUp]
  public void SetUp()
  {
    AltUnityPortHandler.ForwardAndroid();
    altUnityDriver = new AltUnityDriver();
  }

  [OneTimeTearDown]
  public void TearDown()
  {
    altUnityDriver.Stop();
    AltUnityPortHandler.RemoveForwardAndroid();
  }

  [Test]
  public void TestStartGame()
  {
    altUnityDriver.LoadScene("Scene 2 Draggable Panel");

    altUnityDriver.FindObject(By.NAME, "Close Button").Tap();
    altUnityDriver.FindObject(By.NAME, "Button").Tap();

    var panelElement = altUnityDriver.WaitForObject(By.NAME, "Panel");
    Assert.IsTrue(panelElement.enabled);
  }
}

Set up IProxy path in AltUnity Editor window. Use the following static methods (from the AltUnityPortHandler class) in your test file:

  • ForwardIos (string id = “”, int localPort = 13000, int remotePort = 13000)

  • KillIProxy (int id)

Example test file:

using NUnit.Framework;
using Assets.AltUnityTester.AltUnityDriver;
using Assets.AltUnityTester.AltUnityDriver.UnityStruct;

public class MyFirstTest
{
  private AltUnityDriver altUnityDriver;

  [OneTimeSetUp]
  public void SetUp()
  {
    AltUnityPortHandler.ForwardIos();
    altUnityDriver = new AltUnityDriver();
  }

  [OneTimeTearDown]
  public void TearDown()
  {
    altUnityDriver.Stop();
    AltUnityPortHandler.KillIProxy();
  }

  [Test]
  public void TestStartGame()
  {
    altUnityDriver.LoadScene("Scene 2 Draggable Panel");

    altUnityDriver.FindObject(By.NAME, "Close Button").Tap();
    altUnityDriver.FindObject(By.NAME, "Button").Tap();

    var panelElement = altUnityDriver.WaitForObject(By.NAME, "Panel");
    Assert.IsTrue(panelElement.enabled);
  }
}

Have ADB installed and added in PATH Environment Variables (check this article for more information on ADB) for Android and IProxy for iOS.

Use the following static methods (from the AltUnityDriver class) in your test file:

  • SetupPortForwarding (String platform, String deviceId, int local_port, int remote_port)

  • RemovePortForwarding ()

Example test file:

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import ro.altom.altunitytester.AltUnityDriver;
import ro.altom.altunitytester.AltUnityObject;
import ro.altom.altunitytester.Commands.FindObject.AltFindObjectsParameters;
import ro.altom.altunitytester.Commands.FindObject.AltWaitForObjectsParameters;

import java.io.IOException;

public class myFirstTest {

  private static AltUnityDriver altdriver;

  @BeforeClass
  public static void setUp() throws IOException {
    AltUnityDriver.setupPortForwarding("android", "", 13000, 13000);
    altdriver = new AltUnityDriver();
  }

  @AfterClass
  public static void tearDown() throws Exception {
    altdriver.stop();
    AltUnityDriver.removePortForwarding();
  }

  @Test
  public void openClosePanelTest() {

      altdriver.loadScene("Scene 2 Draggable Panel");

      AltFindObjectsParameters altFindObjectsParametersCamera = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.PATH, "//Main Camera")
              .build();
      AltUnityObject camera = altdriver.findObject(altFindObjectsParametersCamera);

      AltFindObjectsParameters closeButtonObjectsParameters = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.NAME, "Close Button")
              .withCamera(AltUnityDriver.By.ID, String.valueOf(camera.id))
              .build();
      altdriver.findObject(closeButtonObjectsParameters).tap();

      AltFindObjectsParameters buttonObjectsParameters = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.NAME, "Button")
              .withCamera(AltUnityDriver.By.ID, String.valueOf(camera.id))
              .build();
      altdriver.findObject(buttonObjectsParameters).tap();

      AltFindObjectsParameters panelObjectsParameters = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.NAME, "Panel")
              .withCamera(AltUnityDriver.By.ID, String.valueOf(camera.id))
              .build();
      AltWaitForObjectsParameters panelWaitForObjectsParameters = new AltWaitForObjectsParameters
              .Builder(panelObjectsParameters).build();
      AltUnityObject panelElement = altdriver.waitForObject(panelWaitForObjectsParameters);

      Assert.assertTrue(panelElement.isEnabled());
  }
}
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import ro.altom.altunitytester.AltUnityDriver;
import ro.altom.altunitytester.AltUnityObject;
import ro.altom.altunitytester.Commands.FindObject.AltFindObjectsParameters;
import ro.altom.altunitytester.Commands.FindObject.AltWaitForObjectsParameters;

import java.io.IOException;

public class myFirstTest {

  private static AltUnityDriver altdriver;

  @BeforeClass
  public static void setUp() throws IOException {
    AltUnityDriver.setupPortForwarding("ios", "", 13000, 13000);
    altdriver = new AltUnityDriver();
  }

  @AfterClass
  public static void tearDown() throws Exception {
    altdriver.stop();
    AltUnityDriver.removePortForwarding();
  }

  @Test
  public void openClosePanelTest() {

      altdriver.loadScene("Scene 2 Draggable Panel");

      AltFindObjectsParameters altFindObjectsParametersCamera = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.PATH, "//Main Camera")
              .build();
      AltUnityObject camera = altdriver.findObject(altFindObjectsParametersCamera);

      AltFindObjectsParameters closeButtonObjectsParameters = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.NAME, "Close Button")
              .withCamera(AltUnityDriver.By.ID, String.valueOf(camera.id))
              .build();
      altdriver.findObject(closeButtonObjectsParameters).tap();

      AltFindObjectsParameters buttonObjectsParameters = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.NAME, "Button")
              .withCamera(AltUnityDriver.By.ID, String.valueOf(camera.id))
              .build();
      altdriver.findObject(buttonObjectsParameters).tap();

      AltFindObjectsParameters panelObjectsParameters = new AltFindObjectsParameters
              .Builder(AltUnityDriver.By.NAME, "Panel")
              .withCamera(AltUnityDriver.By.ID, String.valueOf(camera.id))
              .build();
      AltWaitForObjectsParameters panelWaitForObjectsParameters = new AltWaitForObjectsParameters
              .Builder(panelObjectsParameters).build();
      AltUnityObject panelElement = altdriver.waitForObject(panelWaitForObjectsParameters);

      Assert.assertTrue(panelElement.isEnabled());
  }
}

Have ADB installed and added in PATH Environment Variables (check this article for more information on ADB) for Android and IProxy for iOS.

Use the following static methods (from the AltUnityAndroidPortForwarding class) in your test file:

  • forward_port_device (self, local_port = 13000, device_port = 13000, device_id = “”)

  • remove_forward_port_device (self, port = 13000, device_id = “”)

  • remove_all_forwards (self):

Example test file:

# -*- coding: UTF-8

import os
import unittest
import sys
import json
import time
from altunityrunner import *


class MyFirstTest(unittest.TestCase):
    altdriver = None

    @classmethod
    def setUpClass(cls):
        androidPortForwarding = AltUnityAndroidPortForwarding()
        androidPortForwarding.forward_port_device()

        cls.altdriver = AltUnityDriver()

    @classmethod
    def tearDownClass(cls):
        cls.altdriver.stop()

        androidPortForwarding = AltUnityAndroidPortForwarding()
        androidPortForwarding.remove_forward_port_device()

    def test_open_close_panel(self):
        self.altdriver.load_scene('Scene 2 Draggable Panel')

        self.altdriver.find_object(By.NAME, "Close Button").tap()
        self.altdriver.find_object(By.NAME, "Button").tap()

        panelElement = self.altdriver.wait_for_object(By.NAME, "Panel")
        self.assertTrue(panelElement.enabled)


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(MyFirstTest)
    result = unittest.TextTestRunner(verbosity=2).run(suite)
    sys.exit(not result.wasSuccessful())

Use the following static methods (from the AltUnityiOSPortForwarding class) in your test file:

  • forward_port_device (local_port = 13000, device_port = 13000, device_id = “”)

  • kill_iproxy_process (pid) // pid is returned by forward_port_device

  • kill_all_iproxy_process()

Example test file:

# -*- coding: UTF-8

import os
import unittest
import sys
import json
import time
from altunityrunner import *


class MyFirstTest(unittest.TestCase):
    altdriver = None
    iProxyProcessID = -1

    @classmethod
    def setUpClass(cls):
        iOSPortForwarding = AltUnityiOSPortForwarding()
        cls.iProxyProcessID = iOSPortForwarding.forward_port_device()

        cls.altdriver = AltUnityDriver()

    @classmethod
    def tearDownClass(cls):
        cls.altdriver.stop()

        iOSPortForwarding = AltUnityiOSPortForwarding()
        iOSPortForwarding.kill_iproxy_process(cls.iProxyProcessID)

    def test_open_close_panel(self):
        self.altdriver.load_scene('Scene 2 Draggable Panel')

        self.altdriver.find_object(By.NAME, "Close Button").tap()
        self.altdriver.find_object(By.NAME, "Button").tap()

        panelElement = self.altdriver.wait_for_object(By.NAME, "Panel")
        self.assertTrue(panelElement.enabled)


if __name__ == '__main__':
    suite = unittest.TestLoader().loadTestsFromTestCase(MyFirstTest)
    result = unittest.TextTestRunner(verbosity=2).run(suite)
    sys.exit(not result.wasSuccessful())

Note

The default port on which the AltUnity Server is running is 13000. Port can be changed when making a new game build or make use of port forwarding if needed.

Connect to AltUnity server running inside the game

There are multiple scenarios on how to connect to the AltUnity Server running inside a game:

  1. Connect to the game running on the same machine as the test code

  2. Connect to the game running on a USB connected device by using Port Forwarding.

  3. Connect to the device running the game by using an IP address

  4. Connect to multiple devices running the game by using Port Forwarding.

  5. Connect to multiple builds of the application running on the same device

Connect to the game running on the same machine as the test code

port forwarding case 1

In this case Port Forwarding is not needed as both the game and tests are using localhost (127.0.0.1) connection and the default 13000 port.

Connect to the game running on a USB connected device

If the device running the game is connected through a USB connection, commands sent to localhost port 13000 can be automatically forwarded to the device.

port forwarding case 2

In this scenario you can use Port Forwarding to enable AltUnity Driver to connect to the device via localhost.

Check Port Forwarding for more details about Port Forwarding and Setup Port Forwarding section on how to make the setup.

Connect to the device running the game by using an IP address

port forwarding case 3

You can connect directly through an IP address if the altUnity server port is available and the IP address is reachable. It is recommended to use Port Forwarding since IP addresses could change and would need to be updated more frequently.

The following command can be used to connect to the altUnity server inside the game:

altUnityDriver = new AltUnityDriver ("deviceIp", 13000); 
altUnityDriver = new AltUnityDriver ("deviceIp", 13000, ";", "&", true);  
cls.altdriver = AltUnityDriver(TCP_IP='deviceIp', TCP_PORT=13000)

Connect to multiple devices running the game

port forwarding case 4

For two devices you have to do the same steps above, by connecting through port forwarding twice.

So, in the end, you will have:

  • 2 devices, each with one AltUnity Server

  • 1 computer with two AltUnity Drivers

Then, in your tests, you will send commands from each of the two AltUnity Drivers.

The same happens with n devices, repeat the steps n times.

Connect to multiple builds of the application running on the same device

If you want to run two builds on the same device you will need to change the AltUnity Server Port.

For example, you will build a game with AltUnity Server running on Server Port 13001 and another one that runs on Server Port 13002.

port forwarding case 5

Then in your tests you will need to instantiate two AltUnity server drivers for each of the Server Ports.

Important

On mobile devices, AltUnity Driver can only interact with a single game at a time and the game needs to be in focus.

On Android/iOS only one application is in focus at a time so you need to switch (in code) between the applications if using two drivers at the same time. This applies even when using split screen mode.

You can change the port for your game build from the AltUnityTesterEditor window inside your Unity project.

altUnity Server Settings

Note

After you have done the Server Port forwarding or connected to the AltUnity driver directly, you can use it in your tests to send commands to the server and receive information from the game.