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

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

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

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

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

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

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

الخطوة 4 : حزم التطبيق الخاص بك للتحميل

أنشئ ملف IPA لتطبيقك (ستحتاج إلى تحديد موقعه لاحقًا).

  1. من القائمة المنسدلة التي تظهر، انقر فوق المنتج > الأرشيف . حدد أحدث أرشيف، ثم انقر فوق توزيع التطبيق .

  2. في النافذة التي تظهر، انقر فوق التطوير > التالي .

  3. اختياري: للحصول على إصدار أسرع، قم بإلغاء تحديد خيار إعادة الإنشاء من 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 .