باستخدام اختبارات حلقة الألعاب، يمكنك كتابة اختبارات متوافقة مع محرك اللعبة، ثم تشغيلها في 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، انتقِل إلى عمليات تطوير البرامج وإشراك المستخدمين > Test Lab.
انقر على إجراء اختبارك الأول > تنفيذ حلقة الألعاب على iOS.
في قسم تحميل التطبيق، انقر على استعراض، ثم اختَر ملف IPA الخاص بتطبيقك (إذا لم يسبق لك ذلك، أنشئ ملف IPA لتطبيقك).
(اختياري) إذا أردت تشغيل عدة حلقات (تُعرف أيضًا باسم سيناريوهات) في الوقت نفسه أو اختيار حلقات معيّنة لتشغيلها، أدخِل أرقام الحلقات في حقل السيناريوهات.
على سبيل المثال، عند إدخال
1-3, 5، تنفّذ Test Lab الحلقات1و2و3و5. تلقائيًا (في حال عدم إدخال أي قيمة في حقل السيناريوهات)، لا يتم تنفيذ Test Lab إلا في الحلقة1.في قسم الأجهزة، اختَر جهازًا فعليًا واحدًا أو أكثر تريد اختبار تطبيقك عليه، ثم انقر على بدء الاختبارات.
إجراء اختبار باستخدام gcloud beta CLI
إذا لم يسبق لك إجراء ذلك، عليك إعداد بيئة gcloud SDK المحلية، ثم التأكّد من تثبيت مكوّن 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 Labfirebase-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]; } }