У всех есть какое-то представление о франшизе World of Tanks. Но, как правило, оно «снаружи» (пользовательское) и общее. А что, если посмотреть изнутри, и рассмотреть какие-то очень конкретные вопросы? Скажем, на каком языке пишут тесты для мобильной World of Tanks Blitz, и по каким причинам выбрали его?
Студия разработки мобильных «танков» MS-1 компании Wargaming присутствовала на нашей конференции Heisenbug, и там мы позадавали такие вопросы Дмитрию Сычеву — Lead QA Automation в World of Tanks Blitz. А теперь решили для Хабра сделать и текстовую версию этого небольшого разговора.
— Дмитрий, привет! Ты работаешь над проектом World of Tanks Blitz — для начала расскажи, что это.
Дмитрий: Наша студия разработки MS-1 занимается производством мобильных игр. Я работаю над World of Tanks Blitz, в июне этому проекту исполнилось 6 лет. Он представляет собой кроссплатформенный мультиплеерный танковый шутер. Сердцем игры является сервер. Там происходит вся бизнес-логика, расчет очередей, расчет урона и т.д. Клиент игры написан на C++ и использует in-house движок.
— Мобильные игры запускают на куче разных устройств, у них совершенно разные процессоры (в том числе и старые), и так далее. Весь этот зоопарк надо тестировать — как вы это делали и делаете?
Дмитрий: При разработке игры остро встал вопрос о тестах производительности. Нам нужно было точно знать, помещаемся ли мы в ограниченные бюджеты по памяти и можем ли выдать играбельный FPS.
На тот момент вопрос был решен таким образом:
Teamcity (CI)
Основная цель использования TeamCity – формирование очереди тестов, установка и запуск их на соответствующих устройствах, сбор тестовых данных, формирование и рассылка отчётов всем заинтересованным. За очередь отвечает сама CI, а все остальные задачи лежат на скриптах, написанных на Python, и вспомогательном софте, запускаемом этими скриптами.
MongoDB
Тесты, собирающие какие-то метрики, во время выполнения сохраняют данные в базе, на основе которых в последующем формируются отчёты.
Lua
Все тесты были написаны на Lua, движок которой работал прямо в игре. Для связи скриптов на Lua с кодом игры использовалась прослойка SWIG. Код тестов интегрировался в сам архив с игрой, и при наличии определённого файла конфигурации в документах запускалось исполнение определённого сценария. По окончании выполнения сценария, либо при возникновении ошибки, приложение закрывалось и инициировался сбор тестовых данных.
У этого подхода были как плюсы, так и минусы. Явным плюсом было то, что Lua — один из самых легковесных и быстрых языков по сравнению с тем же Python или JavaScript. Однако при его использовании выявилось несколько недостатков.
Про один из них я могу рассказать историю. Когда я только пришел работать в команду, на языке Lua еще не работал, как и многие — он далеко не самый популярный. Но я подумал, что это интересный вызов. Одним из моих первых заданий было написать несколько тестов на Lua. Я сделал это, дальше нужно было протестировать их на устройствах, посмотреть, все ли правильно работает. Нашел несколько проблем, и мне надо было их продебажить. Спросил у своих коллег, как мне это сделать, и тут оказалось, что отладка в Lua — больной вопрос. Обычно все обкладывают логами и смотрят, что и где пошло не так.
Кроме этого, язык Lua влияет на потребление памяти. Это приходилось учитывать в результатах автотестов производительности.
А отдельного упоминания заслуживает непосредственно написание кода на Lua. Многое тут зависит от писателя, однако есть ограничение для все: нативно не предоставлена возможность писать классы. Наиболее ярко это проявлялось при написании мультиплеерных тестов — это боль.
Можно подумать, что не все так плохо, но вот, что под капотом.
Поэтому людей, желающих обучаться писать на этом языке, было, мягко говоря, немного.
В итоге мы пришли к тому, что надо что-то менять. Улучшать нашу систему.
Вначале мы пошли по неправильному пути. Сначала мы решили все отрефакторить, вынести фреймворк отдельно, тесты отдельно, ввести объекты (пытаться их писать), но это оказалось тоже не очень удобно. И было принято решение полностью пересмотреть концепцию. Когда мы поставили перед собой такую цель, у нас было поставлено три основных задачи.
Первая — тесты должны писаться быстро, легко и удобно, и они должны быть на языке, который люди хотят изучать.
Вторая — удобное написание мультиплеерных тестов.
Третья — универсальность нашего фреймворка. При разработке игры используется много дополнительных инструментов, которые помогают художникам, артистам, рендеру быстро разрабатывать свои фичи. Эти инструменты тоже развиваются и их тоже надо тестировать. И начал подниматься вопрос, что автоматизировать их тоже было бы неплохо.
Мы ставили перед собой три этих задачи.
И языком был выбран Python: сам фреймворк у нас написан на Python, в целом в проекте Python используется достаточно широко, и те же мануальные тестировщики были с ним уже более-менее знакомы.
В качестве ядра нашего фреймворка сначала мы рассматривали вариант использовать REST API, то есть использовать в качестве сервера наш клиент игры, а в качестве клиента наши тесты. Однако в этом решении был один большой минус. Нам не хватало динамики. Мы хотели получать ивенты с игры, чтобы нам не приходилось на каждый необходимый ивент слать запрос и получать ответы.
Мы нашли другое решение, которое нам понравилось. Мы решили использовать websocket. Это тоже по сути сервер-клиент, сервер поднимается в движке игры при старте клиента, а клиентом являются тесты. И там мы можем как делать запросы, так и подписываться на ивенты, и ждать каких-то ивентов от игры. Мы написали прототип, попробовали, и нам все понравилось. Поэтому мы решили использовать такую схему.
Получился следующий вариант:
Многие могут задать вопрос: а как вообще произвести переход между решениями? У вас есть тесты на Lua, вы хотите их сделать на Python и использовать websocket. А автоматизированное тестирование — это такая штука, которая нужна каждый день, каждую версию. Тесты должны быть непрерывными и постоянными.
Мы нашли следующее решение: написали на первое время обертку, которая вызывала Lua-тест, как питоновский. Со временем, когда тесты переводились на Python, Lua уходил, и на данный момент мы полностью избавились от него. Больше мы его не используем. Сейчас я могу рассказать, какие преимущества мы получили.
— Хорошо. Как я понял, вы сейчас полностью перешли на websocket и полностью перешли с Lua на Python, который у вас де-факто стандарт, в том числе в QA Automation в компании. Какие результаты вы в итоге получили? Если сравнивать старые и новые решения, что стало лучше, а что хуже?
Дмитрий: На данный момент все тесты пишутся на Python. Мы смогли написать достаточно удобный фреймворк, который позволяет человеку с минимальным знанием Python писать тесты. Вот пример того же мультиплеерного теста:
Появилась возможность параметризировать тесты для быстрого изменения запуска (например, при дебаге):
При написании теста есть подсказки, некоторые вещи прописывать не нужно, так как они автоматизированы. Как пример: у нас есть такая сущность как Screen Manager. SM — это класс, который разруливает простейшие переходы между экранами, чтобы эти переходы не приходилось постоянно писать самому. Внутри SM определены зависимости между экранами, те прописано как можно перейти с одного экрана на другой. Когда в тесте мы обращаемся к экрану, который указан в зависимостях, SM определяет, на каком экране сейчас находимся и как можно перейти на экран, к которому мы обратились.
Появилась возможность запускать несколько клиентов игры на одном устройстве и тестировать мультиплеерные тесты быстрее. Также можно эмулировать запуск мобильных устройств на десктопе, что помогает при разработке UI тестов, зависящих от разрешения экрана.
В конце концов, сейчас тесты можно дебажить, причем это можно делать как локально, так и прямо на устройстве, при желании можно работать даже через браузер.
— Насколько я понимаю, у вас довольно развесистая инфраструктура, и в Wargaming десятки самых разных проектов. Существует ли какая-то стандартизация на уровне всей компании? Для автотестов в основном используется Python — это характерно, наверное, не только для вашей команды, а в целом практика для всей компании?
Наверняка есть команда, которая занимается инфраструктурами тестирования, и у них есть очень много разных наработок (мониторинги, биндинги, логи и все, что угодно). Удалось ли с помощью перехода на Python получить все эти плюшки, или вы довольно независимо все это делаете?
Дмитрий: В Wargaming много проектов, но они действуют достаточно распределенно. Потому что на разных проектах — разные требования. Я могу провести такую аналогию: для нашего проекта, когда заводились автотесты, изначально одним из важных условий было то, что это должны были быть UI-автотесты. То есть мы должны делать действия так же, как и юзеры, используя UI-элементы.
А в «больших» World of Tanks используется другой принцип: там проверяется главная логика игры, используется botnet. То есть внутри игры находятся танки, они делают какие-то действия, и проверяются их взаимодействия. Насколько я знаю, это происходит даже без визуализации игры. То есть сам клиент в полномасштабном режиме не запускается.
Проекты достаточно специфичны, у каждого свои требования. Поэтому нет стандартизации в этом плане. Хотя и у нас тесты написаны на Python, и на «больших» танках тесты написаны на Python, но сама концепция абсолютно разная. С другой стороны, как я говорил, мы закладывали универсальность нашей схемы, и предполагается, что мы будем использовать наш фреймворк для автоматизации других проектов нашей мобильной студии. На данный момент у нас разрабатывается игра на движке Unreal 4, и сейчас мы изучаем вопрос по интеграции нашего фреймворка для автотестов этой игры. В World of Tanks Blitz у нас используется in-house движок, который написан полностью с нуля в нашей студии, а в той игре используется Unreal Engine. То есть это два абсолютно разных движка, но мы будем использовать наши автотесты и там, и там.
— На Heisenbug было много людей, которые занимаются автоматизацией тестирования. Далеко не все из них занимаются автоматизацией тестирования в области мобильных устройств и, тем более, мобильных игр. В чем самая главная специфика QA Automation человека в вашей области и вообще в мобилках и конкретно в мобильных играх?
Дмитрий: Я считаю, что основная специфика автоматизированного тестирования в разработке мобильных игр — это кроссплатформенность. При разработке фреймворка нужно учитывать, что работать нужно с несколькими платформами, которые могут очень сильно отличаться.
И второе — это производительность. Тестирование производительности. Для мобильных девайсов очень важно, чтобы ваша игра шла без лагов, без затупов и прочего. Нужно сразу учитывать, как вы будете тестировать производительность. Это два основных момента, на которые нужно железобетонно обращать внимание, потому что без них я не представляю себе надежное автотестирование.
— Дмитрий, мы с тобой поговорили про тестирование клиентской части, а как у вас обстоят дела с бэкендом, с нагрузочным тестированием вашего сервера?
Дмитрий: Мы сделали такую штуку как Cloud Client. Это клиент игры, но без визуализации. И в качестве нагрузочного тестирования мы можем создавать до 500000 клиентов игры и заходить ими на сервер. Таким образом мы «ранним» сервер при большом количестве клиентов какое-то время, а далее анализируем логи с сервера на наличие проблем.
— Это, наверное, требует создания некоторой инфраструктуры?
Дмитрий: Естественно. Этот вопрос у нас уже сейчас решается. На данный момент у нас запуск всех автотестов идет с помощью CI-инструмента Team City. Он устанавливает игры на девайс, запускает тесты, регулирует очереди, потом собирает тестовые данные и отправляет заинтересованным людям. Но так как наши тесты подразумевают очень много разных конфигураций запуска, ими пользуются очень много людей, как оказалось, не для всех просто этим пользоваться. Поэтому мы сейчас работаем над тем, что делаем наш портал, на котором будет очень много интересных вещей. Будет реализован запуск тестов в удобном виде. То есть любой человек сможет выбрать то, что он хочет запустить, и это будет запущено на девайсах. Мы туда переводим все отчеты.
На данный момент мы просто формируем html-страницы с графиками, с результатами, со статусами тестов и рассылаем их. А сейчас вся эта информация будет на портале в динамическом виде. Можно будет не только посмотреть текущий запуск, а отсортировать это по дате или по типу или пулу устройств. Это будет удобно для отображения. Если говорить о нагрузочном тестировании, то на портале будет отдельная вкладка для нагрузочного тестирования, где в удобном виде можно будет все посмотреть. Это будет наш кастомный инструмент. Потому что задач ставится перед ним много, и каким-то одним инструментом решить их не получится. Поэтому мы будем развивать свой портал.
— Есть системы (JIRA, TeamCity, Allure), которые позволяют с помощью разных плагинов добиваться примерно того, о чем ты рассказываешь. Почему Allure не подходит для решения такой задачи?
Дмитрий: Allure используется именно для красивого отображения данных. Однако TeamCity это уже CI-инструмент, который используется для запуска тестов, у него стоят абсолютно другие цели. Нам необходимо поддерживать и работу с Allure, и работу с TeamCity, причем как-то сделать удобной работу с TeamCity.
Но это подразумевает поддержку и развитие нескольких инструментов одновременно. А мы можем в одном месте сделать все, так как мы хотим. Ничто не мешает нам на портале прикрутить библиотеки для построения графиков в Allure или еще чем-то другом. В зависимости от того, что нам требуется, мы можем использовать разные вещи. Для отображения больших массивов данных по профайлингу нашей игры (мы используем профайлинг перед тестированием производительности и собираем большое количество данных) удобно работать в BigQuery в Data Studio. Мы будем это использовать, данные уже туда отсылаются. Мы можем в нужном виде их представить, а на портале просто предоставить удобный переход для отображения этих данных. Это не мешает использовать тот же Allure или что-то другое. Просто это все будет сосредоточено в одном месте, удобном для пользователя.
— Дмитрий, спасибо большое за интервью!
khroman
Спасибо