Catch up on highlights from Firebase at Google I/O 2023. Learn more

قم بإجراء اختبار Game Loop

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

حول اختبارات Game Loop

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

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

  • قم بتشغيل اللعبة الخاصة بك حيث سيلعبها المستخدم النهائي. يمكنك إما كتابة إدخال المستخدم ، أو السماح للمستخدم بالتوقف عن العمل ، أو استبدال المستخدم بـ 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).
        }
    }
}

أنهِ الاختبار مبكرًا

بشكل افتراضي ، يستمر اختبار Game Loop في العمل حتى يصل إلى مهلة خمس دقائق ، حتى عندما يتم تنفيذ جميع الحلقات. عند الوصول إلى المهلة ، ينتهي الاختبار ويلغي أي حلقات معلقة. يمكنك تسريع اختبارك أو إنهائه مبكرًا عن طريق استدعاء مخطط عنوان URL المخصص الخاص بـ Test Lab's 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 ، ثم انقر فوق التالي . لا يتطلب 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 أو gcloud CLI .