Pull to refresh

Poco — UI автоматизация мобильных игр на основе Python в рамках AirTest IDE

Reading time 7 min
Views 10K

Сегодня мы поговорим о втором главном фреймворке для автоматизации UI, который называется Poco. Poco использует Python и здесь уже не обойтись без написания кода, но давайте сначала рассмотрим для чего он применяется, когда стоит к нему обращаться и как это всё выглядит.


Данная статья является финальной из серии про AirTest IDE. Первую, обзорную, работу можно найти по данной ссылке, а вторую, где рассказывается про фреймворк распознавания изображений, можно найти здесь.


Poco — фреймворк UI автоматизации игр использующий Python в рамках AirTest IDE с возможностью комбинирования функциональности с их же Image Recognition фреймворком (AirTest). Стоит упомянуть, что у AirTest IDE есть поддержка и других языков (JS,Lua,C#,Java), но дальнейшие примеры будут на Python, т.к. этот язык считается основным.


Основные элементы взаимодействия выглядят следующим образом:


image


Подразумевается, что Poco будет использоваться в тех местах, где не справляется AirTest, но, как сами разработчики замечают, вы можете написать все тесты используя только Poco и скорость прогона их будет значительно выше, но тогда вам нужно знать Python хотя бы на базовом уровне.


Ознакомление и подключение Poco-SDK к вашей игре


Чтобы начать использовать Poco вам нужно ознакомиться с poco-sdk integration guide и установить нужный вам драйвер с соответствующей страницы. На данный момент поддерживаются следующие игровые движки: Unity3D, Android native apps, OSX apps, Windows apps, cocs2dx-lua, cocs2dx-js, Egret, NetEase Internal Engines. Также разработчики дают возможность сделать свой собственный драйвер и предоставляют документацию с описанием этой возможности — Implementation Guide. В официальной документации попадаются упоминания Unreal Engine, но большинство из них идут рука об руку с фразой "Coming soon...", так что нельзя сказать наверняка, когда появится его поддержка.
После ознакомления с общей информацией и дальнейшими действиями вам нужно скачать нужный драйвер, после распаковки положить его в папку проекта и подключить скрипт Poco Manager. К примеру для Unity предлагается добавить Poco Manager как скрипт к одному из основных объектов главной сцены, в частности — Main Camera. После этого необходимо скомпилировать игру и запустить её на поддерживаемом AirTest IDE устройстве и операционной системе.


Подключение игры к AirTest IDE и ваши первые тесты


Для простоты и наглядности дальнейших объяснений я буду использовать пример с официальной демо игрой написанную на Unity, которую предоставляют сами разработчики AirTest IDE. Есть 2 варианта: для Windows и для Android, но я остановлюсь на версии для Windows. К слову, лучше использовать Windows 7, т.к. на Windows 10 мной выявлено странное поведение скриптов, в частности некорректное определение местоположения элементов на экране при использовании некоторых команд. Один и тот же код работал некорректно на Windows 10 и корректно на 7. Будем ждать, когда данная досадная оплошность будет исправлена в будущих обновлениях.


image


Откройте демо игру и дождитесь загрузки стартового экрана. Откройте AirTest IDE. В окне Devices в правой части рабочего layout выберите окно с игрой при помощи кнопки Search Window в разделе "Windows App Connection". Окно с игрой "встроится" в панель и расширится, чтобы соответствовать размеру окна с игрой. Здесь мы сталкиваемся с первой проблемой — невозможность изменить размер окна до нужного нам. Если размер панели и можно изменить, то незначительно и это зависит от размера окна с игрой. К примеру я не сталкивался с такой проблемой при использовании мобильных устройств в портретном режиме.


После подключении игры вам нужно дать AirTest IDE знать, что вы будете использовать Poco для работы с определенным игровым движком. Для этого в левом нижнем углу экрана используйте окно Poco Assistant (если его там нету, то используйте Windows -> Default Layout для восстановления всех панелей по умолчанию) и в выпадающем списке выберите нужный игровой движок, к примеру Unity. Ну и завершающий штрих — согласиться с добавлением всего необходимого кода в Script Editor нажав кнопку "Yes" в появившейся желтой плашке. Если все предыдущие этапы прошли успешно, то в окне Poco Assistant появится иерархическое дерево UI элементов текущего экрана вашего приложения. Данная часть Poco Assistant называется Hierarchy viewer (UI Unspector) и отображает она список только тех элементов, которые присутствуют сейчас на экране. Данный список обновляется автоматически, если на экране есть какие-либо изменения, например появление новых элементов после определенных событий (Events).


Пример вышеописанных шагов под спойлером.


Пример подключения игры в AirTest IDE

image


Чтобы взаимодействовать с каким-либо элементом на экране вам нужно знать его UI Path Code. Для этого достаточно дважды нажать на объект в Poco Assistant или нажать на правую кнопку мыши и выбрать соответствующий пункт. В окне Script Editor появится код для обращения к выбранному элементу и вам нужно добавить только способ взаимодействия (функцию) через точку.


Пример заполненного списка элементов в Poco Assistant

image


К примеру, если вам нужно кликнуть на кнопку, которая в иерархии обозначена как "btn_start", то для клика вам нужен будет примерно такой код.


poco("btn_start").click()

Т.е. простейший тест на основе демо игры, который проверяет нажатие кнопок главного экрана Start и Back (из GlobalControl раздела) будет выглядеть следующим образом


# -*- encoding=utf8 -*-
__author__ = "authorName"
from airtest.core.api import *
auto_setup(__file__)

from poco.drivers.unity3d import UnityPoco
poco = UnityPoco()

poco("btn_start").click()
poco("btn_back").click()

Что происходит по факту: программа находит указанный в коде элемент и после обнаружения его местоположения на экране выполняет нужную функцию. Все эти операции и необходимые данные (к примеру местоположение объекта, количество нажатий на него и т.п.) можно найти в отчёте, а сам отчёт можно создать при помощи сочетания клавиш Ctrl+L. Учитывайте, что названия/адреса кнопок берутся из расчета их существования на текущем экране.


Как это всё выглядит в последней на сегодняшний день версии AirTest IDE (1.2.2) можно посмотреть под спойлером.


Обнаружение и использование кнопок при помощи Poco

Обнаружение и нажатие на кнопку Start


Обнаружение и нажатие на кнопку Back на новом экране


Типы элементов


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


Примеры элементов будут приводиться на основе одного из экранов демо игры.


image


Данный пример содержит следующие элементы:


  • Текст — на данном экране содержится 3 его разновидности. Примеры будут спрятаны под спойлерами.

Title example

image


Placeholder example

image


Текст на элементе (кнопке)

image


  • Изображение — на примере выше — звезда.

Image example

image


  • Поле ввода — поле текстового ввода в нашем случае

InputField example

image


  • Кнопка — кнопка Back в нашем примере, но под спойлером будет пример другой кнопки, т.к. Back не полностью влезает во встроенный экран

Button example

image


  • Node — не уверен как его описать, но, по сути, это контейнер элементов.

Node example

image


Раскрытое дерево всех элементов из примера выше выглядит следующим образом
image


И ещё немного о кодинге


На данный момент AirTest IDE предоставляет 34 команды для взаимодействия с элементами. Их список отображается автоматически во всплывающем окне после ввода точки после элемента взаимодействия. По непонятной мне причине все команды могут быть вызваны для любого типа элементов. Значит ли это, что все команды могут быть использованы для всех типов элементов — пока не знаю, не было возможности проверить. Для удобства, текущий список можете посмотреть под спойлером.


Список функций для взаимодействия с элементами в Poco
add_post_action_callback
add_pre_action_callback
agent
click
freeze
get_screen_size
long_click
sleep_for_polling_interval
snapshot
wait_for_all
swipe
wait_for_any
wait_stableattr
child
children
click (это не моя опечатка, команда встречается в списке дважды)
drag_to
exists
focus
get_bounds
get_name
get_position
get_size
get_text
invalidate
nodes
offspring
set_text
setattr
sibling
swipe (это не моя опечатка, команда встречается в списке дважды)
wait
wait_for_appearance
wait_for_disappearance

Использование переменных здесь крайне рекомендовано и даже спасает от некоторых проблем. В последствии можно будет обращаться к элементам просто указав имя переменной. Ниже вы можете найти несколько примеров сохранения элемента в переменную и обращение к нему:


Image variable
star = poco("star_single")
if star.exists():
    pos = star.get_position()

Input object variable
input_field = poco("pos_input")
    time.sleep(1)
    input_field.set_text('x={:.02f}, y={:.02f}'.format(*pos))
    time.sleep(3)

Button variable
title = poco('title').get_text()
if title == "Basic test":
    back = poco('btn_back', type='Button')
    back.click()
    back.click()

Выше я упомянул, что переменные могут спасти вас от некоторых неприятностей. В частности, я столкнулся с проблемой в модуле Drag and Drop демо игры. Там содержится 5 звёзд (картинки) и задача игрока перенести их в shell, который находится чуть ниже ряда звёзд. Стоит сразу упомянуть, что проблема возникает при прямом обращении к массиву элементов "star": после перетаскивания элемента в нужное положение, он исчезает. AirTest IDE учитывает только видимые элементы и, следовательно, после того, как перенесённая звезда стала невидимой, код не может обратиться к ней напрямую. При прямом обращении к массиву звёзд он будет переинициализирован, т.к. количество элементов в нём изменилось. Т.е. следующая запись не перенесёт все 5 элементов в shell


poco("playDragAndDrop").child("star")[0].drag_to(poco("shell"))
poco("playDragAndDrop").child("star")[1].drag_to(poco("shell"))
poco("playDragAndDrop").child("star")[2].drag_to(poco("shell"))
poco("playDragAndDrop").child("star")[3].drag_to(poco("shell"))
poco("playDragAndDrop").child("star")[4].drag_to(poco("shell"))

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


stars = poco("playDragAndDrop").child("star")
stars[0].drag_to(poco("shell"))
stars[1].drag_to(poco("shell"))

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


Что же по итогу?


AirTest IDE — это достаточно мощный набор инструментов для тестирования UI в играх и других сложных системах на Windows и мобильных ОС. Обнаружение нужных элементов работает корректно в большинстве случаев, возможность писать тесты "from scratch", поддержка многих языков программирования, достаточно подробная информация о результатах прогона тестов в отчёте, который можно создать средствами самой IDE, а также бесплатность самого комплекса инструментов (напоминаю, что AirTest IDE — это Open-Source приложение) — всё это играет на руку AirTest IDE и является хорошей причиной как минимум попробовать, а как максимум внедрить данный инструмент в вашу систему автоматизации. Стоит учитывать, что хоть AirTest и был разработан для тестирования игр, но он не предназначен для автоматизации геймплея. Airtest IDE прекрасно справляется со "статичными" вещами, например с нахождением определенных элементов на экране, работа с UI элементами, к примеру покупки в игровых магазинах и т.п. С этими задачами данная IDE справляется на отлично и её можно советовать для достаточно простой и надёжной автоматизации ваших приложений с низким порогом входа для новичков в этом деле!


Больше информации по использованию, примеров на базе демо игры, а также саму игру от NetEase вы можете найти на официальной странице разработчиков в разделе Poco Examples and Tutorials.


Если у вас уже есть опыт использования AirTest IDE, то будет очень здорово, если вы поделитесь им в комментариях, а если вы нашли баги, то их баг-репорт можно оставить на соответствующей странице!

Tags:
Hubs:
+2
Comments 0
Comments Leave a comment

Articles