ابدأ باختبارات Game Loop لنظام iOS

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

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

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

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

في مفوض التطبيق الخاص بك ، تجاوز 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 ، انقر فوق تشغيل الاختبار الأول> تشغيل حلقة لعبة iOS .

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