הרצת בדיקה של Game Loop

יכול להיות שיהיה קשה להפוך את בדיקת המשחקים לאוטומטית כשאפליקציות המשחקים מבוססות על מסגרות UI שונות. בדיקות לולאת משחקים מאפשרות לשלב את הבדיקות המקוריות עם Test Lab ולהריץ אותן בקלות במכשירים נבחרים. במדריך הזה מוסבר איך להכין בדיקת Game Loop להרצה באמצעות Firebase Test Lab.

מידע על בדיקות של לולאת משחקים

מהי בדיקה של לולאת משחקים?

בדיקת Game Loop היא סימולציה של הפעולות של שחקן אמיתי, שמאפשרת לוודא שהמשחק שלכם עובד טוב אצל המשתמשים בצורה מהירה וניתנת להתאמה. לולאת משחק היא הרצה מלאה או חלקית של הבדיקה באפליקציית המשחקים. תוכלו להריץ בדיקה מקומית של לולאת משחקים בסימולטור או בקבוצת מכשירים בTest Lab. ניתן להשתמש בבדיקות של לולאת משחקים כדי:

  • משחקים במשחק כמו שמשתמש קצה היה משחק בו. אפשר לכתוב סקריפט של הקלט של המשתמש, לאפשר למשתמש להיות ללא פעילות או להחליף את המשתמש ב-AI (לדוגמה, אם הטמעת AI במשחק של מרוצי מכוניות, אפשר להגדיר מנהל התקן של AI שיטפל בקלט של המשתמש).
  • כדאי להפעיל את המשחק בהגדרת האיכות הגבוהה ביותר כדי לבדוק אילו מכשירים יכולים לתמוך בה.
  • מריצים בדיקה טכנית, כמו הידור של מספר תוכנות הצללה, ביצוע שלהם ובדיקה שהפלט שמתקבל הוא כצפוי.

שלב 1: רישום הסכימה של כתובות ה-URL בהתאמה אישית של Test Lab

  1. ב-Xcode, בוחרים יעד פרויקט.

  2. לוחצים על הכרטיסייה Info (מידע) ומוסיפים סוג כתובת URL חדש.

  3. בשדה סכמות של כתובות 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:):

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

כשמריצים כמה לולאות בבדיקה, הלולאה הנוכחית מועברת כפרמטר לכתובת ה-URL שמשמש להפעלת האפליקציה. אפשר גם לקבל את מספר הלולאה הנוכחי על ידי ניתוח האובייקט URLComponents שמשמש לאחזור הסכימה של כתובת ה-URL בהתאמה אישית:

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).
        }
    }
}

סיום מוקדם של בדיקה

כברירת מחדל, בדיקת Game Loop ממשיכה לפעול עד שהיא מגיעה לזמן קצוב של חמש דקות, גם אם כל הלולאות בוצעו. כשהזמן יפוג, הבדיקה תסתיים וכל לולאות בהמתנה יבוטלו. אפשר להאיץ את הבדיקה או לסיים אותה מוקדם יותר על ידי קריאה לסכימה של כתובת ה-URL המותאמת אישית של Test Lab firebase-game-loop-complete ב-Appהענקת הגישה. לדוגמה:

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 מסיימת את הלולאה הנוכחית ומפעילה את הלולאה הבאה. כשאין יותר לולאות להפעלה, הבדיקה מסתיימת.

כתיבה של תוצאות בדיקה מותאמות אישית

אתם יכולים להגדיר את בדיקת Game Loop כך שתכתוב תוצאות בדיקה בהתאמה אישית במערכת הקבצים של המכשיר. כך, כשהבדיקה תתחיל, קובצי התוצאות יישמרו ב-Test Lab בספרייה GameLoopsResults במכשיר הבדיקה (שעליכם ליצור בעצמכם). בסיום הבדיקה, Test Lab מעביר את כל הקבצים מהספרייה GameLoopResults לקטגוריה של הפרויקט. כשמגדירים את הבדיקה, חשוב לזכור את הנקודות הבאות:

  • כל קובצי התוצאות יועלמו, ללא קשר לסוג, לגודל או לכמות שלהם.

  • Test Lab לא מעבד את תוצאות הבדיקה עד שכל הלולאות בבדיקה מסתיימות, לכן אם הבדיקה כוללת כמה לולאות שכותבות פלט, חשוב לצרף אותן לקובץ תוצאות ייחודי או ליצור קובץ תוצאות לכל לולאה. כך תוכלו להימנע מחתימה מחדש על תוצאות של לולאה קודמת.

כדי להגדיר את הבדיקה כך שתכתוב תוצאות בדיקה בהתאמה אישית:

  1. בספרייה Documents של האפליקציה, יוצרים ספרייה בשם GameLoopResults.

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

שלב 3: חתימה על האפליקציה

  1. מוודאים שכל הארטיפקטים באפליקציה חתומים. לדוגמה, אפשר לעשות זאת דרך Xcode על ידי ציון הגדרות החתימה, כמו פרופיל הקצאה וזהות. מידע נוסף זמין באתר Apple Codesigning

שלב 4: אריזה של האפליקציה להעלאה

יוצרים קובץ IPA לאפליקציה (צריך לאתר אותו בהמשך).

  1. בתפריט הנפתח שמופיע, לוחצים על מוצר > ארכיון. בוחרים את הגרסה האחרונה שהועברה לארכיון ולוחצים על הפצת האפליקציה.

  2. בחלון שמופיע, לוחצים על Development (פיתוח) > Next (הבא).

  3. אופציונלי: כדי ליצור גרסה מהירה יותר, מבטלים את הבחירה באפשרות Rebuild from Bitcode ולוחצים על Next. כדי להריץ בדיקה ב-Test Lab לא צריך לבצע דילול או לבנות מחדש את האפליקציה, כך שאפשר להשבית את האפשרות הזו בבטחה.

  4. לוחצים על ייצוא ומזינים את ספריית היעד שבה רוצים להוריד את קובץ ה-IPA של האפליקציה.

שלב 5: אימות חתימת האפליקציה

  1. כדי לאמת את חתימה האפליקציה, פותחים את קובץ ה-ipa .zip ומריצים את הפקודה 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 או CLI של gcloud.