ابدأ مع اختبارات Game Loop لنظام التشغيل iOS

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

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

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

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

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

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

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

الخطوة 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:) :

سويفت

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

الخطوة 3: إنشاء الاختبار وتشغيله

بعد تسجيل نظام عنوان URL المخصص لـ Test Lab، يمكنك تشغيل الاختبار في وحدة تحكم Firebase أو باستخدام gcloud beta CLI . إذا لم تكن قد قمت بذلك بالفعل، فقم بإنشاء ملف IPA لتطبيقك (ستحتاج إلى تحديد موقعه لاحقًا).

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

  1. إذا لم تكن قد قمت بذلك بالفعل، فافتح وحدة تحكم Firebase وقم بإنشاء مشروع.

  2. في صفحة Test Lab بوحدة تحكم Firebase، انقر فوق Run Your First Test > Run an iOS Game Loop .

  3. في قسم تحميل التطبيق ، انقر فوق تصفح ، ثم حدد ملف IPA الخاص بتطبيقك (إذا لم تكن قد قمت بذلك بالفعل، فقم بإنشاء ملف IPA لتطبيقك).

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

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

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

قم بإجراء اختبار باستخدام gcloud beta CLI

  1. إذا لم تكن قد قمت بذلك بالفعل، فقم بتكوين بيئة gcloud SDK المحلية، ثم تأكد من تثبيت مكون gcloud beta .

  2. قم بتشغيل الأمر gcloud beta firebase test ios run واستخدم العلامات التالية لتكوين التشغيل:

أعلام لاختبارات Game Loop
--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 يفرض على اختبارك الإنهاء عندما يستمر لمدة تصل إلى ساعة.

على سبيل المثال، يقوم الأمر التالي بتشغيل اختبار 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 .

إذا كان الاختبار الخاص بك يحتوي على حلقات متعددة، فيمكنك تحديد الحلقة التي تريد تشغيلها عن طريق تمرير رقم الحلقة إلى علامة 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 الخاص بتطبيقك. على سبيل المثال:

سويفت

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