Может быть сложно автоматизировать тестирование игр, когда игровые приложения построены на разных платформах пользовательского интерфейса. Тесты Game Loop позволяют интегрировать собственные тесты с Test Lab и легко запускать их на выбранных вами устройствах. В этом руководстве описывается, как подготовить тест Game Loop для запуска с помощью Firebase Test Lab.
О тестах Game Loop
Что такое тест Game Loop?
Тест Game Loop имитирует действия реального игрока, чтобы быстро и масштабируемо убедиться, что ваша игра хорошо работает для ваших пользователей. Цикл — это полное или частичное выполнение теста в игровом приложении. Вы можете запустить тест Game Loop локально на симуляторе или на наборе устройств в Test Lab. Тесты Game Loop можно использовать для:
- Пройдите через свою игру так, как в нее будет играть конечный пользователь. Вы можете либо запрограммировать ввод пользователя, позволить пользователю бездействовать, либо заменить пользователя ИИ (например, если вы внедрили ИИ в гоночную игру, вы можете назначить ИИ-водителя ответственным за ввод пользователя). .
- Запустите игру с максимальным качеством, чтобы узнать, какие устройства ее поддерживают.
- Запустите технический тест, например, скомпилируйте несколько шейдеров, выполните их и убедитесь, что результат соответствует ожидаемому.
Шаг 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).
}
}
}
Завершить тест досрочно
По умолчанию тест Game Loop продолжает работать до тех пор, пока не истечет пятиминутный тайм-аут, даже если все циклы были выполнены. Когда тайм-аут достигнут, тест завершается и отменяет все ожидающие циклы. Вы можете ускорить свой тест или завершить его раньше, вызвав настраиваемую схему 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 Codesigning.
Шаг 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 .