Доброго дня всем! Меня зовут Роман Мелкумов, я тестировщик в студии IT Territory. И вот уже более года тестирую мобильную игру Castle Duels, которая сочетает в себе многопользовательские бои и коллекционирование персонажей.
Давайте поговорим про автоматизацию тестирования мобильной игры с помощью Airtest IDE, а также обсудим другие варианты, которые мы использовали, и к чему это привело.
Я не ставлю своей целью познакомить всех желающих с различными вариантами внедрения автотестов, а лишь поделюсь полезной для начинающих автоматизаторов информацией. Если вы уже давно работаете в этой сфере, то, возможно, найдёте для себя мало нового, однако освежите в памяти некоторые полезные знания, а заодно узнаете о некоторых инструментах, которые могут облегчить вам работу. Итак, начинаем!
Предпосылки внедрения автотестов
Когда я пришёл в проект, он был на ранней стадии прототипа. Поскольку команда тестирования уже была достаточно опытная, мы хотели сразу упростить многие задачи, с которыми могли столкнуться в будущем. Главной из них была как раз автоматизация. В прошлых проектах она присутствовала лишь номинально и всегда казалась каким-то громоздким и сложным процессом.
Какие из наших проблем решала автоматизация? В первую очередь мы старались защититься от «человеческого фактора»:
Эффект «замыливания глаза». Прогоняя один и тот же сценарий сотню раз, любой человек устаёт и перестаёт замечать даже очень простые вещи. Представьте, что вам нужно тестировать один и тот же уровень много раз подряд.
Рабочий момент «Нет времени объяснять». Такое случается повсеместно, даже с продвинутой документацией в проекте. Всегда есть фичи, которые сложны для понимания, и если человека, который не знаком, например, с каким-то расчётом или элементом игры впервые посадить проверять соответствующие кейсы, то с вероятностью 99 % у него возникнут вопросы. Можно бесконечно разжёвывать кейсы, составлять F.A.Q., но вопросы будут всё равно.
Моря и океаны кейсов. С каждым патчем количество фич будет неуклонно расти. Многие старые фичи будут меняться (притом неоднократно). И однажды команда столкнётся с очень странным результатов: кейсов станет так много, что их придётся оптимизировать. А как можно это сделать? Есть много ответов, но большинство из них связано с исключением данных кейсов из регресса тем или иным способом. На это можно пойти, но лучше всё-таки не терять в работе тривиальные проверки (приёмочные тесты тут не учитываются; под ними я понимаю именно те проверки, которые проходят в момент сдачи фичи и имеют очень низкий приоритет).
Определившись с проблемами, которые мы хотим решить, начали думать о способах решения. Для этого выделили цели, к которым следует планомерно идти:
Увеличение покрытия с помощью автотестов. Главное предназначение автотестов — снижение нагрузки на тестировщиков во время регрессионного тестирования. Поэтому нужно было качественно повысить уровень автоматизации настолько, чтобы ручные тестировщики справлялись с задачами без оглядки на рутинные проверки.
Простота и наглядность. Под этим подразумевалось сразу несколько важных аспектов:
Чтобы обучение новых специалистов происходило быстро, нужен был инструмент(ы), снижающий сложность проверок.
Чтобы любой кейс легко читался и его мог бы редактировать любой специалист из команды, который сосредоточен на работе с автотестами.
Многоплатформенность. В большинстве случаев поддерживается работа под Android, причём как на физических устройствах, так и на эмуляторах. С iOS всё гораздо сложнее, чем может показаться на первый взгляд. Но поскольку мы хотели выпустить игру на обеих платформах, то планировали запускать автотесты и под iOS.
Определившись с целями, мы начали искать инструменты, которые могли бы помочь нам в нашем нелёгком деле.
Какие проекты мы использовали и к чему это привело
Unity Test Framework (UTF). Мы обратили на него внимание в первую очередь, потому что фреймворк поставляется с Unity.
Интерфейс знаком всем, кто уже имел удовольствие работать с Unity, и не представляет сложностей. Интеграция с кодом также достаточно простая, для этого используется Assembly Definition, и после этого вы можете ссылаться на методы, которые написаны другими специалистами.
Фреймворк позволяет проводить модульное тестирование, что должно быть особенно интересно программистам, которые только-только написали свой код, например в Edit Mode. Также можно запускать сценарные проверки при помощи Play Mode. Также у UTF достаточно неплохая документация.
Но, к сожалению, после некоторого изучения мы решили, что с нашими текущими возможностями он не сможет решить большинство проблем. Написание кейсов может занимать достаточно много времени и в них будет сложно ориентироваться новичкам в автотестах. Финальным аккордом стало то, что фреймворк мог косвенно повлиять на сборку рабочих билдов. Поэтому мы решили оставить его для юнит-тестов.
AltUnityTools. Этот инструмент, сразу показался нам достаточно интересным, но с ним произошла занятная история. При работе с UTF мы сразу начали заниматься самописным инструментом, который бы покрыл все наши текущие нужды в автотестах. Получилось так, что мы частично повторили функциональность, которую предлагает AltUnity.
К достоинствам инструмента можно отнести гибкую настройку кейсов, поддержку разных языков программирования, возможность сборки под разные операционные системы и достаточно обширную документацию. Но есть также и проблемы, такие как невозможность выйти за пределы проекта, например, если вам нужно покинуть игру для работы с интерфейсом системы, на которой происходит тестирование.
Интерфейс инструмента интуитивно понятный. Можно собрать версию под нужную платформу прямо из Unity (без перехода в дополнительные окна инспектора), или собирать конкретные сцены, чтобы прогнать на них кейсы. Инструмент подойдёт всем, кто работает с Unity. Мы же решили, что будем использовать его в будущих проектах.
Testify (наш самописный инструмент для Unity). Его мы и начали разрабатывать, чтобы покрыть тот необходимый минимум проверок, который был необходим при начале работ. Testify работает непосредственно с иерархией проекта, позволяет быстро и без долгого обучения начать писать простые UI-тесты.
Как видите, проверки в кейсе выставляются через определённые шаги. В них настраивается то, что будет происходить в игре в текущий момент. Например, нажатие на кнопку, скролл окна или проверка наличия элемента. Можно построить автотест как это будет необходимо, а также повторить действие сколько угодно раз. Для настройки мы также используем словари, в которых указываем, какие значения должны быть получены в результатеитоге проверки.
Однако, как показала практика, этого инструмента оказалось недостаточно, потому что есть проверки, которые требуют взаимодействия с тестируемой системой. Поэтому мы продолжили поиск, попутно разрабатывая кейсы в самописном инструменте.
Airtest. Инструмент разработан китайской компанией, гигантом NetEase. На Хабре есть серия статей, в которых подробно описан принцип работы Airtest IDE, так что я пробегусь только по основным фичам и расскажу, как их можно применить на практике и с чем можно столкнуться. Ну, и отвечу на главный вопрос: полезен ли оказался этот инструмент для достижения наших целей?
Вдохновившись статьями, мы решили попробовать. Этот проект содержит в себе четыре фреймворка, и я вкратце расскажу о каждом из них. Напомню, что Airtest предназначен для автоматизированного UI-тестирования игр.
Условно интерфейс можно поделить на пять основных элементов (не считая шапки):
Первое и основное, если вы будете использовать только Airtest, — панель быстрых команд (также известная как фреймворк распознавания изображений). С её помощью можно быстро настроить сценарии с изображениями и сделать assert’ы в нужных местах.
Панель иерархии Poco пригодится для работы с иерархией вашего проекта или нативной иерархией системы, в которой будет проходить тестирование.
Редактор скриптов позволяет писать скрипты без использования сторонних сред для работы с кодом.
Панель логов отражает взаимодействие Airtest-скриптов с вашим приложением. Тут будут появляться ошибки и результаты прохождения шагов и сценариев.
И последняя, но не менее важная панель — подключения устройств. Она сочетает в себе ряд инструментов для работы с подключёнными устройствами.
Разобравшись с основным интерфейсом, поговорим о двух встроенных фреймворках, первый из которых Airtest (в будущем, для избежания путанницы, я буду называть его «фреймворк для распознавания изображений»). Его работу, можно описать двумя основными тезисами: использует Image Thresholding и работает со встроенными командами.
Распознавание изображений происходит через сравнение интенсивности пикселей, также известное как Image Thresholding. Самому интенсивному пикселю присваивается чёрный цвет, а наименее интенсивному — белый. На изображении выше показан экран во время этого процесса, но в ходе работы берётся скриншот лишь одного элемента.
Работая в Airtest без Poco вы будете, в основном, фотографировать игровой элемент и взаимодействовать с ним. На изображении выше представлены метаданные скриншота, которые записываются при работе с ним. Посмотреть их можно через расширенное представление внутри Airtest.
Если подвести промежуточный итог, то можно выделить следующее:
В скриншот должен попадать только один нужный игровой элемент. Делать скриншот, в котором присутствуют несколько элементов — плохая практика.
Для быстрого форматирования скриншота отлично подойдёт встроенный редактор — Image Editor.
Лучше сразу воздержаться от скриншотов текста, они могут плохо распознаваться или даже не совпадать с текущей локализацией в игре.
Сначала лучше познакомиться с тем, как работают action-типы для Android-устройств. По умолчанию они могут быть выключены, но могут пригодиться для проверок на различных устройствах. Как это выглядит в интерфейсе программы:
Use Javacap — применяется при работе с эмулятором, если тот отображается в виде чёрного окна.
Use ADB Orientation — смена ориентации устройства через ADB.
Use ADB Touch — нажатие на экран через ADB.
Init Device — применяется для автоматизации настройки Android-устройства, например для автоматического запуска сервиса Poco или включения ввода через Yosemite. Но сейчас поддерживаются только устройства с китайским языком и не все версии Android. Также на некоторых «китайцах» (OPPO/VIVO) нужно отдельно ставить приложение для работы с этим инструментом. Подробности здесь (текст на китайском).
Нужно сразу разобраться с тем, как и где вы будете хранить изображения, потому что на каждый сценарий приходится достаточно много картинок, которые занимают место, могут «побиться» при переносе и так далее.
Поскольку фреймворк записывает позицию и разрешение экрана, тест на другом телефоне иногда может сбоить.
Мы столкнулись с тем, что одинаковые изображения и изображения элементов в разных состояниях распознаются некорректно. Всему виной, видимо, процесс Image Thresholding.
Перейдём к Poco Assistant. Он позволяет взаимодействовать с иерархией вашего проекта через интерфейс Airtest IDE. Poco поддерживает фактически все современные движки и легко встраивается в проект. В Unity, например, можно просто встроить скрипт в MainCamera и можно в Airtest IDE работать с иерархией вашего приложения. Также для Unity поддерживаются различные типы GUI (ugui, ngui, fairy gui).
Poco легко комбинируется с фреймворком распознавания изображений, поэтому можно сочетать проверки со скриншотами и с проверками, использующими иерархию. Также очень удобно работать с функциями «Заморозка сцены» и «Запись действий», позволяющими использовать даже те элементы, которые работают в динамичных сценах в игре.
Как показано на последней иллюстрации, выбрав нужный движок вы сразу увидите все параметры, к которым можно впоследствии обратиться. Например, у кнопки FightButton нам пока интересно только имя.
Далее благодаря простому коду мы можем нажать на кнопку в игре. Это избавляет нас от необходимости делать скриншоты, а также от зависимости от разрешения экрана и координат кнопки. Далее мы можем создавать тесты с помощью иерархии.
На что следует обратить внимание при работе с Poco после запуска:
Сразу выберите нужный игровой движок, он подгрузит необходимые библиотеки Poco и позволит с ними взаимодействовать.
Помните про различные форматы списков в играх: где-то подгружается всё сразу, а где-то по мере прокрутки. Если это не учесть, то вы обратитесь к элементу сцены, который ещё не появился в игре, и ваш тест не будет пройден.
Достоинство Airtest IDE в том, что можно писать скрипты во встроенном редакторе. Но, как показала практика, лучше использовать всё-таки профильные редакторы.
Для работы не нужно ничего дополнительно устанавливать, кроме среды для вашего языка (мы пишем преимущественно на Python).
Если представить, что мы разобрались со структурой двух описанных выше фреймворков и написали нужные нам автотесты, то следующим шагом будет прогон кейсов на устройствах или в эмуляторах. С Android всё очень просто и понятно: для корректной работы нужно поставить Airtest, Python, ADB и JavaScript, включить на устройстве отладку по USB, и аппарат готов к работе. Нужно лишь подключить к компьютеру и обновить список устройств в Airtest IDE. Но что делать, если вам нужно тестировать на iOS-устройствах? Тут есть несколько вариантов.
Первый вариант:
iOS Tagent — это переработанный WebDriverAgent, который вы можете знать по Appium. Он разработан компанией Facebook, когда Apple решила перейти на XCUITest. Подробнее про него можно прочитать здесь. iOS Tagent не поставляется вместе с Airtest, но его можно скачать из официального репозитория проекта на Github. По своему опыту сразу подскажу, что лучше настроить именно WebDriverAgent от Facebook, потому что он работает намного лучше версии, переработанной NetEase.
Через xCode нужно настроить несколько параметров WebDriverAgent, связанных с подписыванием и сборкой. Если необходимо рассказать подробнее, то напишите, пожалуйста, в комментариях, я сделаю отдельную статью.
После успешной установки вы сможете использовать автотесты на iOS-устройствах. Однако собирать нужно под все доступные устройства. Работает это через iproxy, также необходимо настроить usbmuxd.
С какими проблемами мы столкнулись:
Корректно подключается только одно устройство, то есть ферму использовать не получится. Пока что мы не нашли решение.
Нужно собирать WebDriverAgent под разные устройства. Это занимает некоторое время и результат не всегда успешный, бывают разные ошибки, которые приходится решать в Xcode.
При сборке WebDriverAgent под старые устройства может возникнуть проблема с запуском из-за разрешений. Помогает сборка и запуск через терминал.
Второй вариант:
iOS Development Bridge (IDB). Этот проект тоже разработан Facebook в 2019 году. Он предназначен для автоматизации действий на iOS-устройствах и в симуляторах. Подробнее можно ознакомиться тут.
IDB позволяет устанавливать и запускать iOS-приложения. Для работы нужно подключить устройство или запустить эмулятор и командой idb list-targets найти нужное устройство. Например: idb launch com.apple.Maps.
IDB повторяет часть возможностей libimobiledevice, но зато можно устанавливать и запускать устройства, а также использовать оба инструмента в связке.
Из недостатков можно отметить, что не все приложения на arm-64 работают в эмуляторах и нельзя просто так запустить приложение, потому что в настройках устройства нужно дать разрешение. Но это общая болячка у обоих способов.
Перейдём к отчетности после проверок на устройствах. После прогона тестов Airtest автоматически генерирует достаточно подробный отчёт, который хранится в корневой директории фреймворка, но по желанию файл можно раздать коллегам для изучения. В отчёте подробно описано прохождение сценария, вплоть до картинки с указанием, где и когда был сделан клик. Также тут можно отфильтровать шаги и выбрать только сбои.
Единственная проблема, которая не позволяет отчёту быть идеальным — журналирование. Пишутся лишь те журналы, в которых показано взаимодействие Airtest с игрой. А если вам нужны отдельные журналы, в том числе с фильтрацией, то придётся их делать отдельно.
Подведение итогов
Благодаря внедрению сразу двух инструментов наши возможности по написанию автотестов расширились. Airtest поможет тем, у кого в проекте много UI-элементов. Также в этом фреймворке есть функциональность Multi-device runner для работы с большим количеством устройств. К недостаткам можно отнести очень долгие свайпы в игре, которые пока непонятно как ускорить. Также некоторую проблему составляет языковой барьер: большая часть документации переведена на английский, однако встречаются форумы и фрагменты документации на китайском.
Airtest и AltUnity Tester, как альтернатива самописным инструментам, это достаточно простые инструменты для автоматизации. Естественно, в ходе работы приходится самостоятельно что-нибудь допиливать, но это стоит того. Ведь в результате вы разгружаете коллег, сильно ускоряете регрессионное тестирование и повышаете качество своего проекта.