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

การทดสอบ Game Loop ช่วยให้คุณเขียนการทดสอบแบบเนทีฟสำหรับเครื่องมือสร้างเกมได้ จากนั้นเรียกใช้การทดสอบใน Test Lab บนอุปกรณ์ที่เลือก วิธีนี้ช่วยให้คุณไม่ต้องกังวลเกี่ยวกับการเขียนสําหรับ UI หรือเฟรมเวิร์กการทดสอบที่แตกต่างกัน การทดสอบรอบเกมจะจำลองการดําเนินการของผู้เล่นจริง และเมื่อคุณเรียกใช้การทดสอบใน Test Lab จะเป็นการทดสอบที่รวดเร็วและปรับขนาดได้เพื่อยืนยันว่าเกมมีประสิทธิภาพดีสำหรับผู้ใช้

หน้านี้จะแสดงวิธีเรียกใช้การทดสอบ Game Loop จากนั้นดูและจัดการผลการทดสอบในหน้า Test Lab ของคอนโซล Firebase นอกจากนี้ คุณยังปรับแต่งการทดสอบเพิ่มเติมได้ด้วยฟีเจอร์ที่ไม่บังคับ เช่น การเขียนผลการทดสอบที่กำหนดเอง หรือการสิ้นสุดการทดสอบก่อนกำหนด

การทดสอบ Game Loop คืออะไร

ลูปคือการทดสอบแอปเล่นเกมแบบเต็มหรือบางส่วน คุณสามารถเรียกใช้การทดสอบ Game Loop ในพื้นที่บนเครื่องจำลองหรือในชุดอุปกรณ์ในTest Lab การทดสอบ Game Loop ใช้เพื่อดำเนินการต่อไปนี้ได้

  • เล่นเกมของคุณในลักษณะที่ผู้ใช้ปลายทางจะเล่น คุณสามารถเขียนสคริปต์อินพุตของผู้ใช้ ปล่อยให้ผู้ใช้ไม่มีการใช้งาน หรือแทนที่ผู้ใช้ด้วย AI (เช่น หากใช้ AI ในเกมแข่งรถ คุณสามารถให้ AI เป็นผู้ควบคุมอินพุตของผู้ใช้)

  • เรียกใช้เกมที่การตั้งค่าคุณภาพสูงสุดเพื่อดูว่าอุปกรณ์ใดรองรับ

  • ทำการทดสอบทางเทคนิค เช่น การคอมไพล์หลายชิเดอร์ การดำเนินการ และตรวจสอบว่าเอาต์พุตเป็นไปตามที่คาดไว้

ขั้นตอนที่ 1: ลงทะเบียนชุดรูปแบบ URL ที่กำหนดเองของ Test Lab

ก่อนอื่น คุณต้องลงทะเบียนรูปแบบ URL ที่กำหนดเองของ Firebase Test Lab ในแอป โดยทำดังนี้

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

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

  3. ป้อน firebase-game-loop ในช่องรูปแบบ URL นอกจากนี้ คุณยังลงทะเบียนรูปแบบ URL ที่กําหนดเองได้โดยเพิ่มลงในInfo.plistไฟล์การกําหนดค่า<dict>ของโปรเจ็กต์ที่ใดก็ได้ภายในแท็ก <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 (ไม่บังคับ): กำหนดค่าแอปให้ทำงานหลายรอบ

หากแอปของคุณลงทะเบียนชุดรูปแบบ URL ที่กำหนดเองไว้หลายชุดและคุณวางแผนที่จะเรียกใช้ Loop (หรือที่เรียกว่าสถานการณ์) หลายรายการในการทดสอบ คุณต้องระบุ Loop ที่ต้องการเรียกใช้ในแอปเมื่อเปิดตัว

ใน App Delegate ให้ลบล้างเมธอด application(_:open:options:) ดังนี้

SwiftObjective-C
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
}
- (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:).
  }
}

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

SwiftObjective-C
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).
}
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 สําหรับแอป (คุณจะต้องค้นหาไฟล์ในภายหลัง) หากยังไม่ได้ดำเนินการ

  1. ใน Xcode ให้เลือกโปรไฟล์การกําหนดค่าสําหรับแอปเป้าหมาย
  2. จากเมนูแบบเลื่อนลงที่ปรากฏขึ้น ให้คลิกผลิตภัณฑ์ > เก็บ เลือกไฟล์เก็บถาวรล่าสุด แล้วคลิกเผยแพร่แอป
  3. ในหน้าต่างที่ปรากฏขึ้น ให้คลิกการพัฒนา > ถัดไป
  4. ไม่บังคับ: หากต้องการให้บิลด์เร็วขึ้น ให้ยกเลิกการเลือกตัวเลือกสร้างใหม่จากบิตโค้ด แล้วคลิกถัดไป Test Lab ไม่ต้องมีการทำให้เบาหรือสร้างแอปใหม่เพื่อทำการทดสอบ คุณจึงปิดใช้ตัวเลือกนี้ได้
  5. คลิกส่งออก แล้วป้อนไดเรกทอรีที่ต้องการดาวน์โหลดไฟล์ IPA ของแอป

ทำการทดสอบในคอนโซล Firebase

  1. หากยังไม่ได้เปิด ให้เปิดคอนโซล Firebase แล้วสร้างโปรเจ็กต์

  2. ในหน้า Test Lab ของคอนโซล Firebase ให้คลิกทำการทดสอบครั้งแรก > เรียกใช้ Game Loop ของ iOS

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

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

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

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

ทำการทดสอบด้วย gcloud CLI เวอร์ชันเบต้า

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

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

Flag สําหรับการทดสอบ Game Loop
--type

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

--app

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

--scenario-numbers

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

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

--device-model

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

--timeout

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

เช่น

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

ตัวอย่างเช่น คำสั่งต่อไปนี้จะทำการทดสอบ Game 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

หากการทดสอบมีลูปหลายรายการ คุณสามารถระบุลูปที่ต้องการเรียกใช้โดยส่งหมายเลขลูปไปยัง Flag scenario โปรดทราบว่าคุณจะเรียกใช้ลูปได้ครั้งละ 1 รายการเท่านั้นเมื่อทำการทดสอบในเครื่อง เช่น หากต้องการเรียกใช้ลูป 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

สิ้นสุดการทดสอบก่อนกำหนด

โดยค่าเริ่มต้น การทดสอบ Game Loop จะทํางานต่อไปจนกว่าจะหมดเวลา 5 นาที แม้ว่าจะมีการเรียกใช้ลูปทั้งหมดแล้วก็ตาม เมื่อถึงเวลาหมดอายุ การทดสอบจะสิ้นสุดลงและยกเลิกลูปที่รอดำเนินการ คุณสามารถเร่งการทดสอบหรือสิ้นสุดการทดสอบก่อนกำหนดได้โดยเรียกใช้รูปแบบ URL ที่กำหนดเองของ Test Lab firebase-game-loop-complete ใน AppDelegate ของแอป เช่น

SwiftObjective-C
/// End the loop by calling our custom url scheme.
func finishLoop() {
    let url = URL(string: "firebase-game-loop-complete://")!
    UIApplication.shared.open(url)
}
- (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 จะไม่ประมวลผลผลการทดสอบจนกว่าลูปทั้งหมดในการทดสอบจะทำงานเสร็จสิ้น ดังนั้นหากการทดสอบมีลูปหลายรายการที่เขียนเอาต์พุต ให้ตรวจสอบว่าคุณได้เพิ่มลูปเหล่านั้นต่อท้ายไฟล์ผลลัพธ์ที่ไม่ซ้ำกันหรือสร้างไฟล์ผลลัพธ์สำหรับแต่ละลูป วิธีนี้จะช่วยหลีกเลี่ยงการเขียนทับผลลัพธ์จากลูปก่อนหน้า

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

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

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

    SwiftObjective-C
    /// 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.
      }
    }
    
    /// 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];
        }
    }