Сегодня на примере Unity игры, мы разберем как писать автоматизацию для мобильных игр. Хочется показать то, что написание нестандартных тестов не всегда так сложно как кажется, конечно это требует определенные навыки и инструментарий.

В данный момент я мог бы посоветовать две тулы для автоматизации игр: AltTester [Github] и AutoPlay [Github]

В данном туториале мы будет использовать AutoPlay, в основном конечно потому-что этот тул писал я, версия на гитхабе не самая последняя, но планирую это скоро исправить. таргет девайс - Android, для IOS все идентично в плане написания тестов, только отличается сборка тестируемого билда

Сборка тестируемого билда

В качестве подопытного мы будем использовать Tower Defense Template, который доступен в Unity store. Скачиваем и разворачиваем, тут проблем быть не должно.

Далее нам надо скачать AutoPlay гитхаба. На данном этапе нам нужен AutoPlay Unity Plugin

После того как все скачано, Просто копируем папку AutoPlay в папку Assets(или Assets/Plugins). Unity обновит проект самостоятельно.

Плагин добавлен в проект
Плагин добавлен в проект

Далее нам нам надо сделать так чтоб наш плагин активировался при запуске нашего приложения, и позволял тестам взаимодействовать с ним. Самый просто способ это добавить наш плагин как игровой объект на сцену, для этого ищем долго-живущий объект и аттачимся в него.

new GameObject("Automation").AddComponent<AutoPlay.Unity.StartPlay>().transform.parent = transform.parent; 

Выглядеть это будет так:

Далее мы стандартным образом мы собираем наш билд, и уже после запуска в верхнем левом углу приложения должна появиться надпись AutoPlay.

Написание тестов. Шаг 1 - Инспектор

Качаем AutoPlay Java Client. Инструкция на wiki. Запускаем.

Подключаем Android по USB (usb debugging должен быть включен), или же просто запускаем Android Simulator.

Для открытия инспектора нам надо сделать 4 действия:

  • Выбрать Андроид.

  • В выпадающем списке выбрать наш девайс.

  • Указать путь к нашему APK файлу который мы собрали в предыдущем шаге.

  • Нажать кнопку инспектора.

После недолгой паузы в течении которой мы понаблюдаем процесс установки и запуска нашего приложения, мы наконец увидим окно инспектора. В нем мы можем пройтись по всему дереву элементов в нашей игре, попутно наблюдая информацию об элементах.

Написание тестов. Шаг 2 - Тесты

В этом шаге мы напишем простой тест с использованием Selenium и JAVA + Serenity(уж очень я люблю его синтаксический сахар).Вообще можно писать тест на любом языке который поддерживается селениумом, любой QA Automation знакомый с селениумом без проблем сможет писать тесты по аналогии с автоматизацией веба.

В первую очередь нам надо переопределить стандартный Selenium Driver, мы хотим расшириться от интерфейс org.openqa.selenium.interactions.HasTouchScreen что даст нам возможность использовать TouchActions.

Полный листинг нашего доработанного под наши нужды Selenium Driver ниже (хочу напомнить что это все тот же чистый Селениум без использования Autoplay).

@Override
public WebDriver newDriver() {
URL remoteAddress = null;
try {
// Это наш AutoPlay rest client
remoteAddress = new URL("http://0.0.0.0:8833/wd/hub");
} catch (MalformedURLException e) {
e.printStackTrace();
}
DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
desiredCapabilities.setPlatform(Platform.MAC);
desiredCapabilities.setJavascriptEnabled(true);
desiredCapabilities.setCapability("version","");
desiredCapabilities.setCapability("udid","");
    return new SwipeableWebDriver(remoteAddress, desiredCapabilities);
}

private static class SwipeableWebDriver extends RemoteWebDriver implements HasTouchScreen, TakesScreenshot {
private RemoteTouchScreen touch;
    public SwipeableWebDriver(URL remoteAddress, DesiredCapabilities desiredCapabilities) {
        super(remoteAddress, desiredCapabilities);
      	// мы ведь работаем на мобилках
        touch = new RemoteTouchScreen(getExecuteMethod());
    }

    public TouchScreen getTouch()    {
        return touch;
    }

		// получение и преоброзование скриншота, например если мы хотим добовлять их репорты
    @Override
    public &lt;X&gt; X getScreenshotAs(OutputType&lt;X&gt; target) throws WebDriverException {
        String screen = execute(DriverCommand.SCREENSHOT).getValue().toString();
        return target.convertFromBase64Png(screen);
    }
}</code></pre><p>Где единственно что нас связывает с клиентом AutoPlay эта строка:</p><pre><code class="java">new URL("http://0.0.0.0:8833/wd/hub");</code></pre><p>Далее мы напишем просто тест на селениуме, вот примерные степы:</p><ul><li><p>Ожидаем запуск игры</p></li><li><p>Жмем выбрать уровень</p></li><li><p>Выбираем уровень - 3</p></li><li><p>Расставляем башни</p></li><li><p>Запускам волну</p></li><li><p>Ждем пока пойдут танки и мы накопим достаточно денег для установки дальнейших башен</p></li><li><p>Ставим Ракетницу на все деньги</p></li><li><p>Финиш</p></li></ul><p>Чуть ниже листенинг для работы с кнопками</p><pre><code class="java">// Ждем пока тест не найдет кнопку выбора уровня, 

// id мы взяли с инспектора (картинка есть чуть выше)
@FindBy(id = "Level_Select")
private WebElementFacade btnLevelSelect;
public void waitStartPageAppears(){
btnLevelSelect.shouldBeVisible();
}
public void clickSelectLevel(){
btnLevelSelect.click();
}

Как видите ничего сложного, нашли элемент, проверили что он виден - тапнули по нему.

Но что если нам надо сделать операцию чуть посложнее например установить башню, вот листининг:

@FindBy(id = "ConfirmButton")
private WebElementFacade btnConfirm;
@FindBy(xpath = "//*[@ID='TowerBuildButton_Clone__index1']//Button")
private WebElementFacade towerMachineGun;
// index - номер платформы,
// placement - номер ячейки
public void placeMachineGun(int index, int placement) {
towerMachineGun.click(); // выбрали башню для установки
		// сначала строим локатор для платформы
    String grid = String.format("PlacementGrid_index%s", index);
		// строим локатор для ячейки
    String place = String.format("PlacementTileMobile_Clone__index%s", placement);
    // строим Xpath локатор
		String socket = String.format("//*[@ID='%s']//*[@ID='%s']",grid,place);

		// ставим башню
    WebElement pl = getDriver().findElement(By.xpath(socket));
    pl.click();

		// подтверждаем
    btnConfirm.waitUntilVisible();
    btnConfirm.click();
}

Кто хочет изучить более подробно на гитхабе Autoplay есть примеры уже написаных тестов.

Теперь соберем все это в тест и наконец посмотрим как это работает.

Вот так будет выглядеть тест:

@Test
public void DemoTowerDefense(){
player.atStartPage.waitStartPageAppears();
player.atStartPage.clickSelectLevel();
    player.atLevelSelect.verifyLevelSelectAppears();
    player.atLevelSelect.openLevel(3);

    player.atBattlePage.verifyBattlePageAppears();

    player.atBattlePage.placeMachineGun(0, 293);
    player.atBattlePage.placeMachineGun(0, 319);
    player.atBattlePage.placeMachineGun(1, 257);
    player.atBattlePage.placeMachineGun(1, 217);
    player.atBattlePage.clickStartWave();

    player.atBattlePage.waitForEnergy(12);
    player.atBattlePage.placeRocket(0, 285);
  	....</code></pre><p>Запускаем, для этого делаем уже привычные нам действия: запустили Autoplay, выбрали билд, девайс, нажали старт.</p><p>Запуск тестов выглядит вполне привычно для тех кто работает c Unit фреймворками.</p><p>А вот и демонстрация что у нас получилось:</p><iframe id="62e2414e9c344d33ecf9772b" src="https://embedd.srv.habr.com/iframe/62e2414e9c344d33ecf9772b" class="embed_video embed__content" allowfullscreen="true"></iframe><p>На этом на сегодня все и до скорых встреч.</p><p></p>

Запускаем, для этого делаем уже привычные нам действия: запустили Autoplay, выбрали билд, девайс, нажали старт.

Запуск тестов выглядит вполне привычно для тех кто работает c Unit фреймворками.

А вот и демонстрация что у нас получилось:

На этом на сегодня все и до скорых встреч.

Комментарии (1)


  1. Furrial
    03.08.2022 17:04

    Какая это версия селениума?