게임 루프 테스트를 사용하면 게임 엔진에 기본으로 테스트를 작성한 다음 선택한 기기의 Test Lab에서 테스트를 실행할 수 있습니다. 이렇게 하면 다양한 UI를 작성하거나 프레임워크를 테스트할 필요가 없습니다. 게임 루프 테스트는 실제 플레이어의 동작을 시뮬레이션하며, Test Lab에서 실행 시 빠르고 확장 가능한 방법으로 게임이 사용자에게 제대로 작동하는지 확인할 수 있습니다.
이 페이지에서는 게임 루프 테스트를 실행한 후 Firebase Console의 Test Lab 페이지에서 테스트 결과를 보고 관리하는 방법을 보여줍니다. 또한 커스텀 테스트 결과 작성 또는 조기에 테스트 종료와 같은 선택적 기능으로 테스트를 추가로 맞춤설정할 수 있습니다.
게임 루프 테스트란 무엇인가요?
루프는 게임 앱에서 테스트를 전체 또는 부분 실행합니다. 시뮬레이터에서 로컬로 또는 기기의 Test Lab에서 게임 루프 테스트를 실행할 수 있습니다. 게임 루프 테스트를 사용하여 다음을 수행할 수 있습니다.
최종 사용자가 플레이하는 것과 같은 방식으로 게임을 진행합니다. 사용자 입력을 스크립트로 작성하거나, 사용자를 자리 비움 상태로 두거나, 사용자를 AI로 대체할 수 있습니다. 예를 들어 이미 구현된 AI가 존재하는 자동차 경주 게임의 경우 사용자 입력을 AI 운전자로 손쉽게 대체할 수 있습니다.
최고 품질 설정으로 게임을 실행하여 어떤 기기에서 해당 설정을 지원하는지 확인합니다.
여러 셰이더를 컴파일하고 실행하며 예상대로 출력되는지 확인하는 등 기술 테스트를 실행합니다.
1단계: Test Lab의 커스텀 URL 스키마 등록
먼저 앱에 Firebase Test Lab 커스텀 URL 스키마를 등록해야 합니다.
Xcode에서 프로젝트 대상을 선택합니다.
정보 탭을 클릭한 다음 새 URL 유형을 추가합니다.
URL 스키마 필드에
firebase-game-loop
를 입력합니다. 커스텀 URL 스키마를<dict>
태그 내에서 프로젝트의Info.plist
구성 파일에 추가하여 등록할 수도 있습니다.<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단계(선택사항): 여러 루프를 실행하도록 앱 구성
앱에 여러 개의 커스텀 URL 스키마가 등록되어 있고 테스트에서 여러 루프(일명 시나리오)를 실행하려는 경우 시작 시 앱에서 실행할 루프를 지정해야 합니다.
앱 대리자에서 application(_:open:options:)
메서드를 재정의합니다.
Swift
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
}
Objective-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에 매개변수로 전달됩니다. 커스텀 URL 스키마를 가져오는 데 사용되는 URLComponents
객체를 파싱하여 현재 루프 번호를 가져올 수도 있습니다.
Swift
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).
}
Objective-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).
}
}
}
3단계: 테스트 만들기 및 실행
Test Lab의 커스텀 URL 스키마를 등록한 후 Firebase Console 또는 gcloud 베타 CLI에서 테스트를 실행할 수 있습니다. 아직 앱의 IPA 파일을 생성하지 않았다면 나중에 찾을 수 있도록 파일을 생성해야 합니다.
Firebase Console에서 테스트 실행
아직 만들지 않았다면 Firebase Console을 열고 프로젝트를 만듭니다.
Firebase Console의 Test Lab 페이지에서 첫 번째 테스트 실행 > iOS 게임 루프 실행을 클릭합니다.
앱 업로드 섹션에서 찾아보기를 클릭한 다음 앱의 IPA 파일을 선택합니다. 아직 앱의 IPA 파일을 생성하지 않았다면 생성해야 합니다.
선택사항: 한 번에 여러 루프(일명 시나리오)를 실행하거나 실행할 특정 루프를 선택하려면 시나리오 필드에 루프 번호를 입력합니다.
예를 들어 '1-3, 5'를 입력하면 Test Lab에서 루프 1, 2, 3, 5를 실행합니다. 시나리오 필드에 아무것도 입력하지 않으면 기본적으로 Test Lab은 루프 1만 실행합니다.
기기 섹션에서 앱을 테스트할 하나 이상의 실제 기기를 선택한 다음 테스트 시작을 클릭합니다.
gcloud 베타 CLI로 테스트 실행
아직 로컬 gcloud SDK 환경을 구성하지 않았다면 gcloud 베타 구성요소를 설치해야 합니다.
gcloud beta firebase test ios run
명령어를 실행하고 다음 플래그를 사용하여 실행을 구성합니다.
게임 루프 테스트용 플래그 | |
---|---|
--type
|
필수: 실행할 iOS 테스트 유형을 지정합니다. 테스트 유형 |
--app
|
필수: 앱의 IPA 파일에 대한 절대 경로(Google Cloud Storage 또는 파일 시스템)입니다. 이 플래그는 게임 루프 테스트를 실행할 때만 유효합니다. |
--scenario-numbers
|
앱에서 실행할 루프(일명 시나리오)입니다. 하나의 루프, 루프 목록, 루프 범위를 입력할 수 있습니다. 기본 루프는 1입니다.
예를 들어 |
--device-model
|
테스트를 실행할 실제 기기입니다(사용할 수 있는 가용 기기 확인). |
--timeout
|
테스트를 실행할 최대 기간입니다. 초 단위로 기간을 나타내는 정수를 입력하거나 기간을 더 긴 단위로 나타내는 정수 및 열거 값을 입력할 수 있습니다. 예를 들면 다음과 같습니다.
|
예를 들어 다음 명령어는 iPhone 8 Plus에서 루프 1, 4, 6, 7, 8을 실행하는 게임 루프 테스트를 실행합니다.
gcloud beta firebase test ios run --type game-loop --app path/to/my/App.ipa --scenario-numbers 1,4,6-8 --device-model=iphone8plus
gcloud CLI에 대한 자세한 내용은 참조 문서를 확인하세요.
로컬에서 테스트 실행
로컬에서 테스트를 실행하려면 시뮬레이터에서 게임 앱을 로드하고 다음을 실행합니다.
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://
instruments -s devices
명령어를 실행하여 시뮬레이터의 UDID를 찾을 수 있습니다.시뮬레이터가 하나만 실행되는 경우 SIMULATOR_UDID 대신 특수 문자열
"booted"
를 입력합니다.
테스트에 여러 루프가 포함된 경우 루프 번호를 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
조기에 테스트 종료
기본적으로 게임 루프 테스트는 모든 루프가 실행되더라도 제한 시간인 5분이 될 때까지 계속 실행됩니다. 제한 시간에 도달하면 테스트가 종료되고 대기 중인 루프가 취소됩니다. 앱의 AppDelegate에서 Test Lab의 커스텀 URL 스키마 firebase-game-loop-complete
를 호출하여 테스트 속도를 높이거나 조기에 종료할 수 있습니다. 예를 들면 다음과 같습니다.
Swift
/// End the loop by calling our custom url scheme.
func finishLoop() {
let url = URL(string: "firebase-game-loop-complete://")!
UIApplication.shared.open(url)
}
Objective-C
- (void)finishLoop {
UIApplication *app = [UIApplication sharedApplication];
[app openURL:[NSURL URLWithString:@"firebase-game-loop-complete://"]
options:@{}
completionHandler:^(BOOL success) {}];
}
게임 루프 테스트는 현재 루프를 종료하고 다음 루프를 실행합니다. 실행할 루프가 더 이상 없으면 테스트가 종료됩니다.
커스텀 테스트 결과 작성
게임 루프 테스트를 구성하여 커스텀 테스트 결과를 기기의 파일 시스템에 작성할 수 있습니다. 이렇게 하면 테스트 실행이 시작되면 Test Lab에서 결과 파일을 테스트 기기의 GameLoopsResults
디렉터리에 저장합니다(직접 만들어야 함). 테스트가 끝나면 Test Lab에서 모든 파일을 GameLoopResults
디렉터리에서 프로젝트 버킷으로 이동합니다. 테스트를 설정할 때 다음 사항에 유의하세요.
모든 결과 파일은 파일 형식, 크기 또는 수량에 관계없이 업로드됩니다.
Test Lab은 테스트의 모든 루프가 완료될 때까지 테스트 결과를 처리하지 않으므로 테스트에 출력을 쓰는 여러 루프가 포함된 경우 루프를 고유한 결과 파일에 추가하거나 루프마다 결과 파일을 만들어야 합니다. 이렇게 하면 이전 루프의 결과를 덮어쓰지 않게 됩니다.
커스텀 테스트 결과를 작성하도록 테스트를 설정하려면 다음 안내를 따르세요.
앱의
Documents
디렉터리에GameLoopResults
라는 디렉터리를 만듭니다.앱 코드의 모든 위치(예: 앱 대리자)에서 다음을 추가합니다.
Swift
/// 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. } }
Objective-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]; } }