เริ่มต้นใช้งานการทดสอบ Game Loop สำหรับ iOS

การทดสอบ 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 ที่กำหนดเองในแอปโดยทำดังนี้

  1. ใน Xcode ให้เลือกเป้าหมายของโปรเจ็กต์

  2. คลิกแท็บ Info แล้วเพิ่มประเภท URL ใหม่

  3. ในช่องรูปแบบ 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 &lt;UIApplicationOpenURLOptionsKey, id&gt; *)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

  1. ในคอนโซล Firebase ให้ไปที่ DevOps และการมีส่วนร่วม > Test Lab

  2. คลิก Run Your First Test > Run an iOS Game Loop

  3. ในส่วนอัปโหลดแอป ให้คลิกเลือก แล้วเลือกไฟล์ IPA ของแอป (หากยังไม่ได้ดำเนินการ ให้ สร้างไฟล์ IPA สำหรับแอป)

  4. (ไม่บังคับ) หากต้องการเรียกใช้หลาย Loop (หรือที่เรียกว่าสถานการณ์) พร้อมกันหรือเลือก Loop ที่ต้องการเรียกใช้ ให้ป้อนหมายเลข Loop ในช่องสถานการณ์

    เช่น เมื่อป้อน 1-3, 5 Test Lab จะเรียกใช้ Loop 1 2 3 และ 5 โดยค่าเริ่มต้น (หากคุณไม่ป้อนอะไรลงในช่อง สถานการณ์) Test Lab จะเรียกใช้ Loop 1 เท่านั้น

  5. ในส่วนอุปกรณ์ ให้เลือกอุปกรณ์จริงอย่างน้อย 1 เครื่องที่ต้องการทดสอบแอป แล้วคลิกเริ่มการทดสอบ

เรียกใช้การทดสอบด้วย gcloud beta CLI

  1. หากยังไม่ได้ดำเนินการ ให้กำหนดค่าสภาพแวดล้อม gcloud SDK ในเครื่อง แล้วตรวจสอบว่าได้ติดตั้ง คอมโพเนนต์ gcloud beta แล้ว

  2. เรียกใช้คำสั่ง gcloud beta firebase test ios run และใช้แฟล็กต่อไปนี้เพื่อกำหนดค่าการเรียกใช้

แฟล็กสำหรับการทดสอบ Game Loop
--type

บังคับ: ระบุประเภทการทดสอบ iOS ที่ต้องการเรียกใช้ คุณสามารถป้อน ประเภทการทดสอบ xctest (ค่าเริ่มต้น) หรือ game-loop

--app

บังคับ: เส้นทางแบบสัมบูรณ์ (Google Cloud Storage หรือ ระบบไฟล์) ไปยังไฟล์ IPA ของแอป แฟล็กนี้ใช้ได้เฉพาะเมื่อ เรียกใช้การทดสอบ Game Loop

--scenario-numbers

Loop (หรือที่เรียกว่าสถานการณ์) ที่ต้องการเรียกใช้ในแอป คุณสามารถป้อน Loop เดียว รายการ Loop หรือช่วงของ Loop Loop เริ่มต้นคือ 1

เช่น --scenario-numbers=1-3,5 จะเรียกใช้ Loop 1, 2, 3 และ 5

--device-model

อุปกรณ์จริงที่ต้องการเรียกใช้การทดสอบ (ดูอุปกรณ์ที่ใช้ได้ ที่คุณใช้ได้)

--timeout

ระยะเวลาสูงสุดที่ต้องการให้การทดสอบทำงาน คุณสามารถป้อนจำนวนเต็มเพื่อ แสดงระยะเวลาเป็นวินาที หรือป้อนจำนวนเต็มและการแจงนับเพื่อแสดงระยะเวลาเป็นหน่วยเวลาที่ยาวขึ้น

เช่น

  • --timeout=200 จะบังคับให้การทดสอบสิ้นสุดเมื่อทำงานครบ 200 วินาที
  • --timeout=1h จะบังคับให้การทดสอบสิ้นสุดเมื่อทำงานครบ 1 ชั่วโมง

ตัวอย่างเช่น คำสั่งต่อไปนี้จะเรียกใช้การทดสอบ 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=1
xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2
xcrun 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 ก่อนหน้า

วิธีตั้งค่าการทดสอบให้เขียนผลการทดสอบที่กำหนดเอง

  1. สร้างไดเรกทอรีชื่อ GameLoopResults ในไดเรกทอรี Documents ของแอป

  2. เพิ่มโค้ดต่อไปนี้จากที่ใดก็ได้ในโค้ดของแอป (เช่น ผู้รับมอบสิทธิ์ของแอป)

    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];
        }
    }