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

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

מידע על בדיקות של game loop

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

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

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

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

  2. לוחצים על הכרטיסייה מידע ואז מוסיפים סוג כתובת 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:):

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 המותאמת אישית:

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

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

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

/// 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. מכל מקום בקוד של האפליקציה (למשל, נציג האפליקציה), מוסיפים את השורה הבאה:

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

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

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

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

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

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

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

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

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

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

  1. כדי לאמת את חתימת האפליקציה, צריך לבטל את הדחיסה של קובץ ה-ipa ואז להריץ את הפקודה 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.