قد يكون من الصعب إجراء اختبارات تلقائية للألعاب عندما يتم إنشاء تطبيقات الألعاب على أُطر عمل مختلفة لواجهة المستخدم. تتيح لك اختبارات "حلقة الألعاب" دمج اختباراتك الأصلية مع Test Lab وتشغيلها بسهولة على الأجهزة التي تختارها. يوضّح هذا الدليل كيفية إعداد اختبار "حلقة الألعاب" لتشغيله باستخدام Firebase Test Lab.
لمحة عن اختبارات "حلقة الألعاب"
ما هو اختبار حلقة الألعاب؟
يحاكي اختبار "حلقة الألعاب" إجراءات لاعب حقيقي للتحقّق من أنّ لعبتك تعمل بشكل جيد للمستخدمين بطريقة سريعة وقابلة للتوسّع. الحلقة هي تشغيل كامل أو جزئي للاختبار على لعبتك على الأجهزة الجوّالة. يمكنك إجراء اختبار "حلقة الألعاب" محليًا على محاكي أو على مجموعة من الأجهزة في Test Lab. يمكن استخدام اختبارات "حلقة الألعاب" لإجراء ما يلي:
- شغِّل لعبتك كما لو كنت مستخدمًا نهائيًا. يمكنك إمّا كتابة نص برمجي لإدخال المستخدم، أو ترك المستخدم في وضع عدم النشاط، أو استبدال المستخدم بذكاء اصطناعي (على سبيل المثال، إذا نفّذت الذكاء الاصطناعي في لعبة سباق سيارات، يمكنك وضع سائق ذكاء اصطناعي مسؤولاً عن إدخال المستخدم).
- شغِّل لعبتك بأعلى إعدادات الجودة لمعرفة الأجهزة التي يمكنها تشغيلها.
- إجراء اختبار فني، مثل تجميع عدة برامج تظليل وتنفيذها والتحقّق من أنّ النتيجة مطابقة للتوقعات
الخطوة 1: تسجيل مخطّط عنوان URL المخصّص لتطبيق "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: ضبط إعدادات تطبيقك (اختياري)
تشغيل تكرارات متعددة
إذا كنت تخطط لتشغيل عدة تكرارات (المعروفة أيضًا باسم السيناريوهات) في الاختبار، فيجب عليك تحديد التكرارات التي تريد تشغيلها في تطبيقك في وقت الإطلاق.
في مفوَّض تطبيقك، يمكنك إلغاء طريقة 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).
}
}
}
إنهاء اختبار قبل موعده
يستمر اختبار حلقة الألعاب تلقائيًا إلى أن تنتهي مهلة الخمس دقائق، حتى بعد تنفيذ جميع الحلقات. عند الوصول إلى المهلة، ينتهي الاختبار ويلغي أي حلقات معلقة. يمكنك تسريع
الاختبار أو إنهاؤه مبكرًا من خلال استدعاء مخطّط عنوان 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]; } }
الخطوة 3: توقيع تطبيقك
تأكَّد من توقيع جميع العناصر في التطبيق. على سبيل المثال، يمكنك إجراء ذلك من خلال Xcode من خلال تحديد إعدادات التوقيع مثل ملف التعريف والهوية. لمزيد من المعلومات، يُرجى الاطّلاع على: توقيع الرموز من Apple
الخطوة 4: تجميع تطبيقك في حزمة لتحميله
أنشِئ ملف IPA لتطبيقك (ستحتاج إلى تحديد موقعه لاحقًا).
من القائمة المنسدلة التي تظهر، انقر على المنتج > أرشفة. اختَر أحدث أرشيف، ثم انقر على توزيع التطبيق (Distribute App).
في النافذة التي تظهر، انقر على التطوير > التالي.
انقر على تصدير (Export)، ثم أدخِل الدليل الذي تريد تنزيل ملف IPA الخاص بتطبيقك فيه.
الخطوة 5: التحقّق من توقيع التطبيق
- تحقَّق من توقيع التطبيق من خلال فك ضغط ملف .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=1xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=2xcrun simctl openurl SIMULATOR_UDID firebase-game-loop://?scenario=5
الخطوات التالية
يمكنك إجراء الاختبار باستخدام وحدة تحكّم Firebase أو gcloud CLI.