Автоматизировать тестирование игр может быть сложно, если игровые приложения созданы на разных платформах пользовательского интерфейса. Тесты Game Loop позволяют интегрировать собственные тесты с Test Lab и легко запускать их на выбранных вами устройствах. В этом руководстве описывается, как подготовить тест Game Loop для запуска с помощью Firebase Test Lab .
О тестах игрового цикла
Что такое тест Game Loop?
Тест Game Loop имитирует действия реального игрока, чтобы убедиться, что ваша игра работает хорошо для ваших пользователей, быстро и масштабируемо. Цикл – это полный или частичный запуск теста игрового приложения. Тест Game Loop можно запустить локально на симуляторе или на наборе устройств в Test Lab . Тесты игрового цикла можно использовать для:
- Проходите игру так, как в нее играл бы конечный пользователь. Вы можете либо запрограммировать ввод пользователя, либо позволить пользователю бездействовать, либо заменить пользователя ИИ (например, если вы реализовали ИИ в автогоночной игре, вы можете поручить ИИ-драйверу отвечать за ввод пользователя). .
- Запустите игру с настройками самого высокого качества, чтобы узнать, какие устройства ее поддерживают.
- Запустите технический тест, например скомпилируйте несколько шейдеров, запустите их и проверьте, что выходные данные соответствуют ожиданиям.
Шаг 1. Зарегистрируйте собственную схему URL-адресов Test Lab
В Xcode выберите цель проекта.
Откройте вкладку «Информация» , затем добавьте новый тип URL-адреса .
В поле «Схемы URL-адресов» введите
firebase-game-loop
. Вы также можете зарегистрировать собственную схему URL-адресов, добавив ее в файл конфигурацииInfo.plist
вашего проекта в любом месте тега<dict>
:<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLName</key> <string></string> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLSchemes</key> <array> <string>firebase-game-loop</string> </array> </dict> </array>
Теперь ваше приложение настроено для запуска теста с помощью Test Lab .
Шаг 2. При необходимости настройте свое приложение.
Запустить несколько циклов
Если вы планируете запускать несколько циклов (так называемых сценариев) в своем тесте, вы должны указать, какие циклы вы хотите запускать в своем приложении во время запуска.
В делегате вашего приложения переопределите метод application(_:open:options:)
:
Быстрый
func application(_app: UIApplication,
open url: URL
options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
let components = URLComponents(url: url, resolvingAgainstBaseURL: true)!
if components.scheme == "firebase-game-loop" {
// ...Enter Game Loop Test logic to override application(_:open:options:).
}
return true
}
Цель-C
- (BOOL)application:(UIApplication *)app
openURL:(NSURL *)url
options:(NSDictionary <UIApplicationOpenURLOptionsKey, id> *)options {
if ([url.scheme isEqualToString:(@"firebase-game-loop")]) {
// ...Enter Game Loop Test logic to override application(_:open:options:).
}
}
Когда вы запускаете несколько циклов в тесте, текущий цикл передается в качестве параметра URL-адресу, используемому для запуска приложения. Вы также можете получить текущий номер цикла, проанализировав объект URLComponents
используемый для получения пользовательской схемы URL-адресов:
Быстрый
if components.scheme == "firebase-game-loop" {
// Iterate over all parameters and find the one with the key "scenario".
let scenarioNum = Int(components.queryItems!.first(where: { $0.name == "scenario" })!.value!)!
// ...Write logic specific to the current loop (scenarioNum).
}
Цель-C
if ([url.scheme isEqualToString:(@"firebase-game-loop")]) {
// Launch the app as part of a game loop.
NSURLComponents *components = [NSURLComponents componentsWithURL:url
resolvingAgainstBaseURL:YES];
for (NSURLQueryItem *item in [components queryItems]) {
if ([item.name isEqualToString:@"scenario"]) {
NSInteger scenarioNum = [item.value integerValue];
// ...Write logic specific to the current loop (scenarioNum).
}
}
}
Завершить тест досрочно
По умолчанию тест игрового цикла продолжает выполняться до тех пор, пока не истечет время ожидания в пять минут, даже если все циклы выполнены. По истечении времени ожидания тест завершается и все ожидающие циклы отменяются. Вы можете ускорить тестирование или завершить его раньше, вызвав собственную схему URL-адресов Test Lab firebase-game-loop-complete
в AppDelegate вашего приложения. Например:
Быстрый
/// End the loop by calling our custom url scheme.
func finishLoop() {
let url = URL(string: "firebase-game-loop-complete://")!
UIApplication.shared.open(url)
}
Цель-C
- (void)finishLoop {
UIApplication *app = [UIApplication sharedApplication];
[app openURL:[NSURL URLWithString:@"firebase-game-loop-complete://"]
options:@{}
completionHandler:^(BOOL success) {}];
}
Тест Game Loop завершает текущий цикл и выполняет следующий цикл. Когда циклов для выполнения больше не остается, тест завершается.
Напишите результаты пользовательского теста
Вы можете настроить тест Game Loop для записи результатов пользовательского теста в файловую систему вашего устройства. Таким образом, когда тест запускается, Test Lab сохраняет файлы результатов в каталоге GameLoopsResults
на вашем тестовом устройстве (который вы должны создать самостоятельно). По завершении теста Test Lab перемещает все файлы из каталога GameLoopResults
в корзину вашего проекта. При настройке теста помните следующее:
Все файлы результатов загружаются независимо от типа, размера или количества файлов.
Test Lab не обрабатывает результаты теста до тех пор, пока не завершится выполнение всех циклов теста, поэтому, если ваш тест включает в себя несколько циклов, записывающих выходные данные, обязательно добавьте их в уникальный файл результатов или создайте файл результатов для каждого цикла. Таким образом, вы можете избежать перезаписи результатов предыдущего цикла.
Чтобы настроить тест для записи пользовательских результатов теста:
В каталоге
Documents
вашего приложения создайте каталог с именемGameLoopResults
.В любом месте кода вашего приложения (например, в делегате приложения) добавьте следующее:
Быстрый
/// Write to a results file. func writeResults() { let text = "Greetings from game loops!" let fileName = "results.txt" let fileManager = FileManager.default do { let docs = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) let resultsDir = docs.appendingPathComponent("GameLoopResults") try fileManager.createDirectory( at: resultsDir, withIntermediateDirectories: true, attributes: nil) let fileURL = resultsDir.appendingPathComponent(fileName) try text.write(to: fileURL, atomically: false, encoding: .utf8) } catch { // ...Handle error writing to file. } }
Цель-C
/// Write to a results file. - (void)writeResults:(NSString *)message { // Locate and create the results directory (if it doesn't exist already). NSFileManager *manager = [NSFileManager defaultManager]; NSURL* url = [[manager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; NSURL* resultsDir = [url URLByAppendingPathComponent:@"GameLoopResults" isDirectory:YES]; [manager createDirectoryAtURL:resultsDir withIntermediateDirectories:NO attributes:nil error:nil]; // Write the result message to a text file. NSURL* resultFile = [resultsDir URLByAppendingPathComponent:@"result.txt"]; if ([manager fileExistsAtPath:[resultFile path]]) { // Append to the existing file NSFileHandle *handle = [NSFileHandle fileHandleForWritingToURL:resultFile error:nil]; [handle seekToEndOfFile]; [handle writeData:[message dataUsingEncoding:NSUTF8StringEncoding]]; [handle closeFile]; } else { // Create and write to the file. [message writeToURL:resultFile atomically:NO encoding:NSUTF8StringEncoding error:nil]; } }
Шаг 3. Подпишите свое приложение
Убедитесь, что все артефакты в приложении подписаны. Например, вы можете сделать это через Xcode, указав параметры подписи, такие как профиль обеспечения и удостоверение. Дополнительную информацию см. в разделе: Разработка кода Apple.
Шаг 4. Упакуйте приложение для загрузки.
Создайте файл IPA для вашего приложения (вам нужно будет найти его позже).
В появившемся раскрывающемся меню нажмите «Продукт» > «Архив» . Выберите самый последний архив, затем нажмите «Распространить приложение» .
В появившемся окне нажмите Разработка > Далее .
Необязательно: Чтобы ускорить сборку, снимите флажок «Перестроить из биткода» , затем нажмите «Далее» . Test Lab не требует прореживания или перестройки вашего приложения для запуска теста, поэтому вы можете безопасно отключить эту опцию.
Нажмите «Экспорт» , затем укажите каталог, в который вы хотите загрузить IPA-файл вашего приложения.
Шаг 5. Проверьте подпись приложения.
- Проверьте подпись приложения, разархивировав файл .ipa, а затем запустив
codesign --verify --deep --verbose /path/to/MyApp.app
, где «MyApp» — это имя приложения в разархивированной папке (различно для каждого проекта). ). Ожидаемый результат:MyApp.app: valid on disk
.
Шаг 6. Запустите тест локально.
Вы можете запустить тест локально, чтобы проверить его поведение, прежде чем запускать его с помощью Test Lab . Чтобы протестировать локально, загрузите игровое приложение в симуляторе и запустите:
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://
Вы можете узнать UDID вашего симулятора, выполнив команду
instruments -s devices
.Если запущен только один симулятор, введите специальную строку
"booted"
вместо SIMULATOR_UDID .
Если ваш тест содержит несколько циклов, вы можете указать, какой цикл вы хотите запустить, передав номер цикла флагу scenario
. Обратите внимание, что при локальном выполнении теста за раз можно запускать только один цикл. Например, если вы хотите запустить циклы 1, 2 и 5, вам необходимо выполнить отдельную команду для каждого цикла:
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=1
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=5
Следующие шаги
Запустите тест с помощью консоли Firebase или интерфейса командной строки gcloud .