การทดสอบ Game Loop ช่วยให้คุณเขียนการทดสอบที่มาพร้อมเครื่องในเกมเอนจิน แล้วเรียกใช้การทดสอบเหล่านั้นใน Test Lab บนอุปกรณ์ที่คุณเลือกได้ วิธีนี้จะช่วยให้คุณไม่ต้องกังวลเรื่องการเขียนสำหรับ UI หรือเฟรมเวิร์กการทดสอบที่แตกต่างกัน การทดสอบ Game Loop จะจำลองการดำเนินการของผู้เล่นจริง และเมื่อคุณเรียกใช้การทดสอบใน Test Lab การทดสอบนี้ จะมอบวิธีที่รวดเร็วและปรับขนาดได้เพื่อยืนยันว่าเกมทำงานได้ดี สำหรับผู้ใช้
หน้านี้จะแสดงวิธีเรียกใช้การทดสอบ Game Loop จากนั้นดูและจัดการผลการทดสอบ ในหน้า Test Lab ของคอนโซล Firebase นอกจากนี้ คุณยังปรับแต่งการทดสอบเพิ่มเติมได้ด้วยฟีเจอร์ที่ไม่บังคับ เช่น การเขียนผลการทดสอบที่กำหนดเอง หรือ การสิ้นสุดการทดสอบก่อนกำหนด
การทดสอบ Game Loop คืออะไร
Loop คือการเรียกใช้การทดสอบทั้งหมดหรือบางส่วนในแอปเกม คุณสามารถ เรียกใช้การทดสอบ Game Loop ในเครื่องบนโปรแกรมจำลองหรือบนชุดอุปกรณ์ใน Test Lab การทดสอบ Game Loop สามารถใช้เพื่อดำเนินการต่อไปนี้
เล่นเกมในลักษณะที่ผู้ใช้ปลายทางจะเล่น คุณสามารถเขียนสคริปต์อินพุตของผู้ใช้ ปล่อยให้ผู้ใช้ไม่มีการใช้งาน หรือแทนที่ผู้ใช้ด้วย AI (เช่น หากคุณใช้ AI ในเกมแข่งรถ คุณสามารถให้ AI เป็นผู้ขับแทนอินพุตของผู้ใช้ได้)
เรียกใช้เกมด้วยการตั้งค่าคุณภาพสูงสุดเพื่อดูว่าอุปกรณ์ใดรองรับการตั้งค่านี้
เรียกใช้การทดสอบทางเทคนิค เช่น การคอมไพล์เชเดอร์หลายรายการ การดำเนินการเชเดอร์ และการตรวจสอบว่าเอาต์พุตเป็นไปตามที่คาดไว้
ขั้นตอนที่ 1: ลงทะเบียน URL Scheme ที่กำหนดเองของ Test Lab
ก่อนอื่น คุณต้องลงทะเบียน Firebase Test Lab's URL Scheme ที่กำหนดเองในแอปโดยทำดังนี้
ใน Xcode ให้เลือกเป้าหมายของโปรเจ็กต์
คลิกแท็บ Info แล้วเพิ่มประเภท URL ใหม่
ในช่องรูปแบบ URL ให้ป้อน
firebase-game-loopนอกจากนี้ คุณยังลงทะเบียน URL Scheme ที่กำหนดเองได้โดยเพิ่มรูปแบบดังกล่าวลงในไฟล์การกำหนดค่าของโปรเจ็กต์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 (ไม่บังคับ): กำหนดค่าแอปให้เรียกใช้หลาย Loop
หากแอปของคุณมีการลงทะเบียนรูปแบบ URL ที่กำหนดเองหลายรูปแบบและคุณวางแผนที่จะเรียกใช้หลาย Loop (หรือที่เรียกว่าสถานการณ์) ในการทดสอบ คุณต้องระบุ Loop ที่ต้องการเรียกใช้ในแอปเมื่อเปิดแอป
ในผู้รับมอบสิทธิ์ของแอป ให้ลบล้างเมธอด 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:).
}
}
เมื่อคุณเรียกใช้หลาย Loop ในการทดสอบ ระบบจะส่ง Loop ปัจจุบันเป็นพารามิเตอร์ไปยัง URL ที่ใช้เปิดแอป นอกจากนี้ คุณยังรับหมายเลข Loop ปัจจุบันได้โดยแยกวิเคราะห์ออบเจ็กต์ URLComponents ที่ใช้ดึงข้อมูล URL Scheme ที่กำหนดเอง ดังนี้
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: สร้างและเรียกใช้การทดสอบ
หลังจากลงทะเบียนรูปแบบ URL ที่กำหนดเองของ Test Lab แล้ว คุณจะเรียกใช้การทดสอบ ในFirebaseคอนโซล หรือด้วย gcloud beta CLI ได้ หากยังไม่ได้ดำเนินการ ให้สร้างไฟล์ IPA สำหรับแอป (คุณจะต้องค้นหาไฟล์นี้ในภายหลัง)
เรียกใช้การทดสอบในคอนโซล Firebase
ในคอนโซล Firebase ให้ไปที่ DevOps และการมีส่วนร่วม > Test Lab
คลิก Run Your First Test > Run an iOS Game Loop
ในส่วนอัปโหลดแอป ให้คลิกเลือก แล้วเลือกไฟล์ IPA ของแอป (หากยังไม่ได้ดำเนินการ ให้ สร้างไฟล์ IPA สำหรับแอป)
(ไม่บังคับ) หากต้องการเรียกใช้หลาย Loop (หรือที่เรียกว่าสถานการณ์) พร้อมกันหรือเลือก Loop ที่ต้องการเรียกใช้ ให้ป้อนหมายเลข Loop ในช่องสถานการณ์
เช่น เมื่อป้อน
1-3, 5Test Lab จะเรียกใช้ Loop123และ5โดยค่าเริ่มต้น (หากคุณไม่ป้อนอะไรลงในช่อง สถานการณ์) Test Lab จะเรียกใช้ Loop1เท่านั้นในส่วนอุปกรณ์ ให้เลือกอุปกรณ์จริงอย่างน้อย 1 เครื่องที่ต้องการทดสอบแอป แล้วคลิกเริ่มการทดสอบ
เรียกใช้การทดสอบด้วย gcloud beta CLI
หากยังไม่ได้ดำเนินการ ให้กำหนดค่าสภาพแวดล้อม gcloud SDK ในเครื่อง แล้วตรวจสอบว่าได้ติดตั้ง คอมโพเนนต์ gcloud beta แล้ว
เรียกใช้คำสั่ง
gcloud beta firebase test ios runและใช้แฟล็กต่อไปนี้เพื่อกำหนดค่าการเรียกใช้
| แฟล็กสำหรับการทดสอบ Game Loop | |
|---|---|
--type
|
บังคับ: ระบุประเภทการทดสอบ iOS ที่ต้องการเรียกใช้ คุณสามารถป้อน
ประเภทการทดสอบ |
--app
|
บังคับ: เส้นทางแบบสัมบูรณ์ (Google Cloud Storage หรือ ระบบไฟล์) ไปยังไฟล์ IPA ของแอป แฟล็กนี้ใช้ได้เฉพาะเมื่อ เรียกใช้การทดสอบ Game Loop |
--scenario-numbers
|
Loop (หรือที่เรียกว่าสถานการณ์) ที่ต้องการเรียกใช้ในแอป คุณสามารถป้อน Loop เดียว รายการ Loop หรือช่วงของ Loop Loop เริ่มต้นคือ 1
เช่น |
--device-model
|
อุปกรณ์จริงที่ต้องการเรียกใช้การทดสอบ (ดูอุปกรณ์ที่ใช้ได้ ที่คุณใช้ได้) |
--timeout
|
ระยะเวลาสูงสุดที่ต้องการให้การทดสอบทำงาน คุณสามารถป้อนจำนวนเต็มเพื่อ แสดงระยะเวลาเป็นวินาที หรือป้อนจำนวนเต็มและการแจงนับเพื่อแสดงระยะเวลาเป็นหน่วยเวลาที่ยาวขึ้น เช่น
|
ตัวอย่างเช่น คำสั่งต่อไปนี้จะเรียกใช้การทดสอบ Game Loop ที่ดำเนินการ Loop 1, 4, 6, 7 และ 8 บน iPhone 8 Plus
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://
คุณดู UDID ของโปรแกรมจำลองได้โดยเรียกใช้คำสั่ง
instruments -s devicesหากมีโปรแกรมจำลองที่ทำงานอยู่เพียงโปรแกรมเดียว ให้ป้อนสตริงพิเศษ
"booted"แทน SIMULATOR_UDID
หากการทดสอบมีหลาย Loop คุณสามารถระบุ Loop ที่ต้องการเรียกใช้ได้โดยส่งหมายเลข Loop ไปยังแฟล็ก scenario โปรดทราบว่าคุณเรียกใช้ได้ครั้งละ 1 Loop เท่านั้นเมื่อเรียกใช้การทดสอบในเครื่อง เช่น หากต้องการเรียกใช้ Loop 1, 2 และ 5 คุณต้องเรียกใช้คำสั่งแยกกันสำหรับแต่ละ Loop ดังนี้
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=1xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=5
สิ้นสุดการทดสอบก่อนกำหนด
โดยค่าเริ่มต้น การทดสอบ Game Loop จะทำงานต่อไปจนกว่าจะถึงการหมดเวลา 5 นาที แม้ว่าจะมีการดำเนินการ Loop ทั้งหมดแล้วก็ตาม เมื่อถึงการหมดเวลา การทดสอบจะสิ้นสุดลงและยกเลิก Loop ที่รอดำเนินการ คุณสามารถเร่ง
การทดสอบหรือสิ้นสุดการทดสอบก่อนกำหนดได้โดยเรียกใช้ URL Scheme ที่กำหนดเองของ Test Lab
firebase-game-loop-complete ใน AppDelegate ของแอป เช่น
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) {}];
}
การทดสอบ Game Loop จะสิ้นสุด Loop ปัจจุบันและดำเนินการ Loop ถัดไป เมื่อไม่มี Loop ให้เรียกใช้อีก การทดสอบจะสิ้นสุดลง
เขียนผลการทดสอบที่กำหนดเอง
คุณสามารถกำหนดค่าการทดสอบ Game Loop ให้เขียนผลการทดสอบที่กำหนดเองลงในระบบไฟล์ของอุปกรณ์ได้ วิธีนี้จะช่วยให้เมื่อการทดสอบเริ่มทำงาน Test Lab
จัดเก็บไฟล์ผลการทดสอบไว้ในไดเรกทอรี GameLoopsResults ในอุปกรณ์ทดสอบ (ซึ่งคุณต้องสร้างขึ้นเอง) เมื่อการทดสอบสิ้นสุดลง Test Lab จะย้าย
ไฟล์ทั้งหมดจากไดเรกทอรี GameLoopResults ไปยังบัคเก็ตของโปรเจ็กต์ โปรดคำนึงถึงสิ่งต่อไปนี้เมื่อตั้งค่าการทดสอบ
ระบบจะอัปโหลดไฟล์ผลการทดสอบทั้งหมดโดยไม่คำนึงถึงประเภท ขนาด หรือจำนวนไฟล์
Test Lab จะไม่ประมวลผลผลการทดสอบจนกว่า Loop ทั้งหมดในการทดสอบจะทำงานเสร็จ ดังนั้นหากการทดสอบมีหลาย Loop ที่เขียนเอาต์พุต โปรดตรวจสอบว่าคุณได้ผนวกเอาต์พุตเหล่านั้นเข้ากับไฟล์ผลการทดสอบที่ไม่ซ้ำกัน หรือสร้างไฟล์ผลการทดสอบสำหรับแต่ละ Loop วิธีนี้จะช่วยให้คุณหลีกเลี่ยงการเขียนทับผลการทดสอบจาก Loop ก่อนหน้า
วิธีตั้งค่าการทดสอบให้เขียนผลการทดสอบที่กำหนดเอง
สร้างไดเรกทอรีชื่อ
GameLoopResultsในไดเรกทอรีDocumentsของแอปเพิ่มโค้ดต่อไปนี้จากที่ใดก็ได้ในโค้ดของแอป (เช่น ผู้รับมอบสิทธิ์ของแอป)
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]; } }