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

בדיקות Game Loop מאפשרות לכם לכתוב בדיקות שמותאמות למנוע המשחק שלכם, ואז להריץ אותן ב-Test Lab במכשירים שתבחרו. כך לא צריך לדאוג לגבי כתיבה לממשקי משתמש או למסגרות בדיקה שונות. בדיקת Game Loop מדמה את הפעולות של שחקן אמיתי, וכשמריצים אותה ב-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. בשדה סכמות של כתובות 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 (אופציונלי): מגדירים את האפליקציה כך שתריץ כמה לולאות

אם לאפליקציה יש כמה סכימות של כתובות URL מותאמות אישית שרשומות, ואתם מתכננים להריץ כמה לולאות (תרחישים) בבדיקה, אתם צריכים לציין אילו לולאות אתם רוצים להריץ באפליקציה בזמן ההפעלה.

ב-app delegate, מבטלים את השיטה 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).
        }
    }
}

שלב 3: יצירה והרצה של בדיקה

אחרי שרושמים את סכימת כתובת ה-URL המותאמת אישית של Test Lab, אפשר להריץ את הבדיקה במסוף Firebase או באמצעות gcloud beta CLI. אם עדיין לא עשיתם זאת, צרו קובץ IPA לאפליקציה (תצטרכו לאתר אותו בהמשך).

הרצת בדיקה במסוף Firebase

  1. במסוף Firebase, עוברים אל DevOps & Engagement (DevOps ומעורבות) > Test Lab.

  2. לוחצים על Run Your First Test > Run an iOS Game Loop.

  3. בקטע Upload App, לוחצים על Browse ובוחרים את קובץ ה-IPA של האפליקציה (אם עדיין לא עשיתם את זה, צרו קובץ IPA לאפליקציה).

  4. (אופציונלי) אם רוצים להריץ כמה לולאות (תרחישים) בו-זמנית או לבחור לולאות ספציפיות להרצה, מזינים את מספרי הלולאות בשדה Scenarios.

    לדוגמה, כשמזינים את הערך 1-3, 5, Test Lab מריץ את הלולאות 1, 2, 3 ו-5. כברירת מחדל (אם לא מזינים שום דבר בשדה Scenarios), הכלי Test Lab מריץ רק את הלולאה 1.

  5. בקטע Devices, בוחרים מכשיר פיזי אחד או יותר שרוצים לבדוק בו את האפליקציה, ולוחצים על Start Tests.

הרצת בדיקה באמצעות ה-CLI של gcloud בגרסת בטא

  1. אם עדיין לא עשיתם זאת, הגדירו את סביבת ה-SDK המקומית של gcloud, ואז התקינו את רכיב הבטא של gcloud.

  2. מריצים את הפקודה gcloud beta firebase test ios run ומשתמשים בדגלים הבאים כדי להגדיר את ההרצה:

דגלים לבדיקות Game Loop
--type

חובה: מציין את סוג הבדיקה ב-iOS שרוצים להריץ. אפשר להזין את סוגי הבדיקות xctest (ברירת המחדל) או game-loop.

--app

חובה: נתיב מוחלט (Google Cloud Storage או מערכת קבצים) לקובץ ה-IPA של האפליקציה. הדגל הזה תקף רק כשמריצים בדיקות של Game Loop.

--scenario-numbers

הלולאות (שנקראות גם תרחישים) שרוצים להריץ באפליקציה. אפשר להזין לולאה אחת, רשימה של לולאות או טווח של לולאות. ברירת המחדל היא לולאה אחת.

לדוגמה, --scenario-numbers=1-3,5 מריץ את הלולאות 1, 2, 3 ו-5.

--device-model

המכשיר הפיזי שבו רוצים להריץ את הבדיקה (כאן אפשר לראות באילו מכשירים אפשר להשתמש).

--timeout

משך הזמן המקסימלי שבו רוצים להריץ את הבדיקה. אפשר להזין מספר שלם שמייצג את משך הזמן בשניות, או מספר שלם וספירה שמייצגים את משך הזמן ביחידת זמן ארוכה יותר.

לדוגמה:

  • ‫--timeout=200 מאלץ את הבדיקה להסתיים כשהיא מגיעה ל-200 שניות.
  • הפקודה --timeout=1h מאלצת את הבדיקה להסתיים אחרי שעה אחת.

לדוגמה, הפקודה הבאה מריצה בדיקת 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

מידע נוסף על ה-CLI של gcloud מופיע במאמרי העזרה.

הרצת בדיקה באופן מקומי

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

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

סיום הבדיקה לפני הזמן

כברירת מחדל, בדיקת Game Loop ממשיכה לפעול עד שהיא מגיעה לזמן קצוב לתפוגה של חמש דקות, גם כשכל הלולאות בוצעו. כשהזמן הקצוב לתפוגה מסתיים, הבדיקה מסתיימת וכל הלולאות הממתינות מבוטלות. כדי לזרז את הבדיקה או לסיים אותה מוקדם יותר, אפשר להפעיל את סכימת כתובת ה-URL המותאמת אישית של 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 מסיימת את הלולאה הנוכחית ומריצה את הלולאה הבאה. כשהלולאות מסתיימות, הבדיקה מסתיימת.

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

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

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

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

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

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

  2. בכל מקום בקוד של האפליקציה (למשל, ב-app delegate), מוסיפים את הקוד הבא:

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