بدء استخدام اختبارات حلقة الألعاب لأجهزة iOS

باستخدام اختبارات Game Loop، يمكنك كتابة اختبارات أصلية لمحرك اللعبة ثم تنفيذها في Test Lab على الأجهزة التي تختارها. بهذه الطريقة، لن يكون عليك القلق بشأن الكتابة لإطارات عمل مختلفة لاختبار واجهة المستخدم. يحاكي اختبار "حلقة الألعاب" إجراءات لاعب حقيقي، وعند تشغيله على Test Lab، فإنه يوفر طريقة سريعة وقابلة للتطوير للتحقّق من أنّ لعبتك تعمل بشكل جيد للمستخدمين.

توضّح لك هذه الصفحة كيفية إجراء اختبار "حلقة الألعاب"، ثم عرض نتائج الاختبار وإدارتها في صفحة Test Lab ضمن وحدة تحكّم Firebase. يمكنك أيضًا تخصيص اختباراتك بشكل أكبر باستخدام ميزات اختيارية، مثل كتابة نتائج اختبار مخصّصة أو إنهاء الاختبار مبكرًا.

ما هو "اختبار حلقة الألعاب"؟

تمثّل التكرار الحلقي تجربة كاملة أو جزئية للاختبار على لعبتك على الأجهزة الجوّالة. يمكنك إجراء اختبار حلقة الألعاب محلّيًا على جهاز محاكاة أو على مجموعة من الأجهزة في Test Lab. يمكن استخدام اختبارات "حلقة الألعاب" لإجراء ما يلي:

  • شغِّل لعبتك كما يفعل المستخدم النهائي. يمكنك إما كتابة نص يدخِله المستخدم، أو السماح له بالبقاء غير نشِط لفترة قصيرة، أو استبدال المستخدم بالذكاء الاصطناعي (على سبيل المثال، إذا استخدمت الذكاء الاصطناعي في لعبة سباق السيارات، يمكنك توجيه سائق يعمل بالذكاء الاصطناعي إلى المعلومات التي يُدخلها المستخدم).

  • شغِّل لعبتك بأعلى إعدادات الجودة لمعرفة الأجهزة التي يمكنها تشغيلها.

  • يمكنك إجراء اختبار فني، مثل تجميع عدّة أدوات تصفية ضوئية وتنفيذها والتحقّق من أنّ النتيجة على النحو المتوقّع.

الخطوة 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 المخصَّصة المسجَّلة وكنت تخطِّط لتشغيل حلقات متعدّدة (المعروفة أيضًا باسم سيناريوهات) في الاختبار، عليك تحديد التكرارات التي تريد تشغيلها في تطبيقك في وقت الإطلاق.

في صفحة التفويض في تطبيقك، يمكنك إلغاء طريقة 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 التجريبية. أنشئ ملف IPA لتطبيقك إذا لم يسبق لك إجراء ذلك (ستحتاج إلى تحديد موقعه لاحقًا).

إجراء اختبار في وحدة تحكّم Firebase

  1. افتح وحدة تحكّم Firebase وأنشِئ مشروعًا إذا لم يسبق لك ذلك.

  2. في صفحة Test Lab ضمن وحدة التحكّم Firebase، انقر على إجراء اختبارك الأول > تشغيل حلقة ألعاب iOS.

  3. في قسم تحميل التطبيق، انقر على تصفّح، ثم اختَرملف IPA لتطبيقك (أنشئ ملف IPA لتطبيقك إذا لم يسبق لك ذلك).

  4. اختياري: إذا أردت تنفيذ تكرارات متعددة (أي سيناريوهات) في وقت واحد أو اختيار حلقات تكرار معيّنة لتشغيلها، أدخِل أرقام التكرار في الحقل سيناريوهات.

    على سبيل المثال، عند إدخال "1-3 و5"، تُجري Test Lab التكرارات 1 و2 و3 و5. تلقائيًا (إذا لم تُدخل أي شيء في حقل السيناريوهاتTest Lab لا يُشغِّل سوى حلقة 1.

  5. في قسم الأجهزة، اختَر جهازًا فعليًا واحدًا أو أكثر تريد اختبار تطبيقك عليه، ثمّ انقر على بدء الاختبارات.

إجراء اختبار باستخدام واجهة برمجة التطبيقات gcloud التجريبية

  1. اضبط بيئة حزمة gcloud SDK المحلية إذا لم يسبق لك إجراء ذلك، ثم تأكَّد من تثبيت مكوّن gcloud التجريبي.

  2. شغِّل الأمر gcloud beta firebase test ios run واستخدِم علامتَي الالتفاف التاليتَين لضبط عملية التشغيل:

علامات اختبارات حلقة الألعاب
--type

مطلوب: يحدد نوع اختبار iOS الذي تريد إجراؤه. يمكنك إدخال أنواع الاختبار xctest (التلقائي) أو game-loop.

--app

مطلوبة: مسار مطلق (Google Cloud Storage أو نظام الملفات) لملف IPA الخاص بتطبيقك لا تكون هذه العلامة صالحة إلا عند تشغيل اختبارات Game Loop.

--scenario-numbers

الحلقات (المعروفة أيضًا باسم السيناريوهات) التي تريد تنفيذها في تطبيقك: يمكنك إدخال حلقة واحدة أو قائمة أو حلقات أو نطاق من الحلقات. العدد التلقائي للحلقات هو 1.

على سبيل المثال، يُجري --scenario-numbers=1-3,5 الحلقات 1 و2 و3 و5.

--device-model

الجهاز الفعلي الذي تريد إجراء الاختبار عليه (تعرَّف على الأجهزة المتاحة التي يمكنك استخدامها).

--timeout

الحد الأقصى لمدة تنفيذ الاختبار يمكنك إدخال عدد صحيح لتمثيل المدة بالثواني، أو عدد صحيح وتعداد لتمثيل المدة كوحدة زمنية أطول.

على سبيل المثال:

  • تؤدي القيمة --timeout=200 إلى إنهاء الاختبار عند تشغيله لمدة تصل إلى 200 ثانية.
  • تؤدي القيمة --timeout=1h إلى إنهاء الاختبار بعد مرور ساعة.

على سبيل المثال، ينفِّذ الأمر التالي اختبار حلقة الألعاب الذي ينفّذ التكرارات الحلقية 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.

إذا كان الاختبار يتضمّن عدة حلقات، يمكنك تحديد الحلقة التي تريد تنفيذها من خلال تمرير رقم الحلقة إلى العلامة 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

إنهاء اختبار مبكرًا

يستمر اختبار "حلقة الألعاب" تلقائيًا في التشغيل إلى أن يصل إلى مهلة مدتها خمس دقائق، حتى بعد تنفيذ جميع الحلقات. عند انقضاء المهلة، ينتهي الاختبار ويلغي أي تكرارات معلّقة. يمكنك تسريع الاختبار أو إنهائه مبكرًا من خلال استدعاء مخطّط عنوان 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 لكتابة نتائج اختبار مخصّصة في نظام ملفات جهازك. بهذه الطريقة، عندما يبدأ الاختبار، يخزِّن 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];
        }
    }