باستخدام اختبارات حلقة الألعاب، يمكنك كتابة اختبارات أصلية لمحرك لعبتك ثم تشغيلها في Test Lab على الأجهزة التي تختارها. بهذه الطريقة، لن تحتاج إلى القلق بشأن الكتابة لأُطر عمل مختلفة لواجهة المستخدم أو الاختبار. يحاكي اختبار حلقة الألعاب إجراءات اللاعب الحقيقي، وعند تشغيله على Test Lab، يوفّر طريقة سريعة وقابلة للتوسّع للتحقّق من أنّ لعبتك تعمل بشكل جيد للمستخدمين.
توضّح لك هذه الصفحة كيفية إجراء اختبار حلقة الألعاب، ثم عرض نتائج الاختبار وإدارتها في صفحة "Test Lab" ضمن وحدة تحكّم "Firebase". يمكنك أيضًا تخصيص اختباراتك بشكل أكبر باستخدام ميزات اختيارية، مثل كتابة نتائج اختبار مخصّصة أو إنهاء الاختبار مبكرًا.
ما هو اختبار حلقة الألعاب؟
الحلقة هي تشغيل كامل أو جزئي للاختبار على لعبة على الأجهزة الجوّالة. يمكنك إجراء اختبار حلقة الألعاب محليًا على محاكي أو على مجموعة من الأجهزة في Test Lab. يمكن استخدام اختبارات "حلقة الألعاب" لإجراء ما يلي:
شغِّل لعبتك كما لو كنت مستخدمًا نهائيًا. يمكنك إما كتابة نص برمجي لإدخال المستخدم، أو ترك المستخدم في وضع عدم النشاط، أو استبدال المستخدم بذكاء اصطناعي (على سبيل المثال، إذا نفذت الذكاء الاصطناعي في لعبة سباق سيارات، يمكنك وضع سائق ذكاء اصطناعي مسؤول عن إدخال المستخدم).
شغِّل لعبتك بأعلى إعدادات الجودة لمعرفة الأجهزة التي يمكنها تشغيلها.
إجراء اختبار فني، مثل تجميع عدة برامج تظليل وتنفيذها والتأكّد من أنّ النتيجة مطابقة للتوقعات
الخطوة 1: تسجيل مخطّط عنوان URL المخصّص لـ "Test Lab"
أولاً، عليك تسجيل مخطّط عنوان URL المخصّص لـ "Firebase Test Lab" في تطبيقك:
في Xcode، اختَر هدف المشروع.
انقر على علامة التبويب معلومات، ثم أضِف نوع عنوان URL جديدًا.
في حقل مخطّطات عناوين 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 <UIApplicationOpenURLOptionsKey, id> *)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 beta CLI. أنشِئ ملف IPA لتطبيقك إذا لم يسبق لك ذلك (ستحتاج إلى تحديد موقعه لاحقًا).
إجراء اختبار في وحدة تحكّم Firebase
في وحدة تحكّم Firebase، انتقِل إلى DevOps & Engagement > Test Lab.
انقر على إجراء الاختبار الأول > تشغيل حلقة ألعاب iOS.
في قسم تحميل التطبيق، انقر على تصفُّح، ثم اختَر ملف IPA الخاص بتطبيقك (إذا لم يسبق لك ذلك، أنشِئ ملف IPA لتطبيقك).
(اختياري) إذا أردت تشغيل عدة تكرارات حلقية (تُعرف أيضًا باسم السيناريوهات) في وقت واحد أو اختيار تكرارات حلقية معيّنة لتشغيلها، أدخِل أرقام التكرارات الحلقية في حقل السيناريوهات.
على سبيل المثال، عند إدخال
1-3, 5، يشغّل Test Lab الحلقات1و2و3و5. وفقًا للإعدادات التلقائية (إذا لم تُدخل أي بيانات في حقل السيناريوهات)، لن يشغّل Test Lab سوى التكرار1.في قسم الأجهزة، اختَر جهازًا فعليًا واحدًا أو أكثر تريد اختبار تطبيقك عليه، ثم انقر على بدء الاختبارات.
إجراء اختبار باستخدام gcloud beta CLI
إذا لم يسبق لك ذلك، اضبط بيئة حزمة تطوير البرامج (SDK) المحلية لـ gcloud، ثم تأكَّد من تثبيت مكوّن gcloud التجريبي.
شغِّل الأمر
gcloud beta firebase test ios runواستخدِم العلامات التالية لضبط عملية التشغيل:
| علامات اختبارات "حلقة الألعاب" | |
|---|---|
--type
|
مطلوب: يحدِّد نوع اختبار iOS الذي تريد إجراؤه. يمكنك إدخال نوعَي الاختبار |
--app
|
مطلوب: المسار المطلق (Google Cloud Storage أو نظام الملفات) لملف IPA الخاص بتطبيقك. لا تكون هذه العلامة صالحة إلا عند إجراء اختبارات "حلقة الألعاب". |
--scenario-numbers
|
الحلقات (المعروفة أيضًا باسم السيناريوهات) التي تريد تشغيلها في تطبيقك. يمكنك إدخال حلقة واحدة أو قائمة أو حلقات أو نطاق من الحلقات. القيمة التلقائية للتكرار هي 1.
على سبيل المثال، يشغّل |
--device-model
|
الجهاز الفعلي الذي تريد إجراء الاختبار عليه (يمكنك الاطّلاع على الأجهزة المتاحة التي يمكنك استخدامها). |
--timeout
|
الحدّ الأقصى لمدة الاختبار يمكنك إدخال عدد صحيح لتمثيل المدة بالثواني، أو عدد صحيح وتعداد لتمثيل المدة كوحدة زمنية أطول. على سبيل المثال:
|
على سبيل المثال، يشغّل الأمر التالي اختبار حلقة الألعاب الذي ينفّذ الحلقات 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=1xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2xcrun 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) {}];
}
يُنهي اختبار "حلقة الألعاب" الحلقة الحالية وينفّذ الحلقة التالية. وعندما لا يكون هناك المزيد من التكرارات لتشغيلها، ينتهي الاختبار.
كتابة نتائج اختبار مخصّصة
يمكنك ضبط اختبار "حلقة الألعاب" لكتابة نتائج اختبار مخصّصة في نظام ملفات جهازك. بهذه الطريقة، عند بدء الاختبار، يخزّن Test Lab ملفات النتائج في دليل GameLoopsResults على جهاز الاختبار (الذي يجب إنشاؤه بنفسك). عند انتهاء الاختبار، ينقل Test Lab
جميع الملفات من الدليل GameLoopResults إلى حزمة مشروعك. يُرجى مراعاة ما يلي عند إعداد الاختبار:
يتم تحميل جميع ملفات النتائج بغض النظر عن نوع الملف أو حجمه أو كميته.
لا يعالج Test Lab نتائج الاختبار حتى تنتهي جميع الحلقات في الاختبار من العمل، لذلك إذا كان الاختبار يتضمن حلقات متعددة تكتب المخرجات، فتأكد من إلحاقها بملف نتيجة فريد أو إنشاء ملف نتيجة لكل حلقة. بهذه الطريقة، يمكنك تجنب الكتابة فوق النتائج من حلقة سابقة.
لإعداد الاختبار لكتابة نتائج اختبار مخصّصة:
في دليل
Documentsالخاص بتطبيقك، أنشئ دليلاً باسمGameLoopResults.من أي مكان في رمز تطبيقك (على سبيل المثال، مفوّض التطبيق)، أضِف ما يلي:
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]; } }