Android وiOS للمختبِرين
Android وiOS هما نظاما التشغيل اللذان يُطرح عليهما كل تطبيق جوال تقريباً. تطوّر Google نظام Android على نواة مفتوحة المصدر وتطرحه شركات مصنّعة كثيرة على أجهزتها، لكل منها طبقة نظام خاصة؛ أما iOS فتطوّره Apple ولا يعمل إلا على أجهزتها. والمتطلب مثل «يمسح المستخدم رمز QR للدفع» واحد على المنصتين، لكن نظام التشغيل هو الذي يقرر كيف يُطلب إذن الكاميرا، وماذا تفعل إيماءة الرجوع، وكيف يصل البناء (Build) إلى المختبِرين والمستخدمين، وأي إصدارات النظام ما زالت مستخدمة.
يعلّمك هذا الدرس الفروق الأربعة بين المنصتين التي تغيّر تصميم الاختبار أكثر من غيرها: الأذونات، والتنقل للخلف، والمتاجر، وإصدارات النظام، ثم العدّة التي تستخدمها على كل منصة لتثبيت بناءات الاختبار وقراءة سجلات الجهاز وتسجيل ما رأيته. عامل كل منصة كمنتج مستقل يتشارك المتطلبات مع الآخر، واكتب النتيجة المتوقعة لكل منصة على حدة حيثما كانت المنصة، لا فريقك، هي التي تحدد السلوك.
لماذا يهم
نادراً ما تكون العيوب التي تظهر على منصة واحدة فقط في منطق الأعمال الذي تتشاركه المنصتان، بل تظهر حيث يلتقي التطبيق بنظام التشغيل: إذن رُفض على iOS ويظل التطبيق يطلبه، أو ضغطة رجوع في Android تتخطى خطوة التأكيد، أو بناء يتصرف بطريقة مختلفة على إصدار نظام لم يثبّته الفريق قط، أو إصدار توقفه مراجعة المتجر قبل يوم من الإطلاق.
أما للمختبِر، فمعرفة قواعد المنصة تحوّل السيناريوهات الغامضة إلى نتائج متوقعة دقيقة. فعبارة «اختبر الأذونات» تصبح حالة اختبار محددة لكل حالة إذن على كل منصة، و«افحص التنقل للخلف» تصبح قائمة شاشات وإيماءات لكل منها وجهة متوقعة. كما تخبرك بما يمكنك التحكم فيه من جهاز الاختبار وما تقرره المنصة وحدها، فتبلّغ عن العيوب إلى الجهة الصحيحة.
Android وiOS من مقعد المختبِر
يعمل Android (من Google) على أجهزة من شركات مصنّعة كثيرة. فنواة النظام مفتوحة المصدر، وتضيف الشركات المصنّعة طبقاتها الخاصة، ويمكن تثبيت التطبيقات من Google Play أو من متاجر أخرى أو مباشرةً من ملف APK، ولهذا يتسلّم المختبِرون عادةً نسخ التصحيح (Debug Builds) على شكل ملفات. وتوفّر المنصة فعل رجوع على مستوى النظام كله، ونموذج أذونات وقت التشغيل (Runtime Permissions)، وانتشاراً واسعاً جداً لإصدارات النظام والعتاد.
أما iOS (من Apple) فلا يعمل إلا على أجهزة iPhone، مع iPadOS على أجهزة iPad. تتحكم Apple في العتاد والنظام وأدوات البناء (Xcode، الذي يحتاج إلى جهاز Mac) وقناة التوزيع الرئيسية، وهي App Store (ولا يُسمح بمتاجر تطبيقات بديلة إلا في بعض المناطق، مثل الاتحاد الأوروبي). وتصل التطبيقات إلى المختبِرين عبر TestFlight أو عبر ملفات تعريف (Provisioning Profiles) مرتبطة بأجهزة مسجّلة. ولا يوجد زر رجوع في النظام، والموارد المحمية مثل الكاميرا والموقع تحتاج إلى غرض مُعلن، ويصدر إصدار iOS الجديد لكل الأجهزة المدعومة في اليوم نفسه.
ما يبقى ثابتاً هو كل ما تعلمته سابقاً: المتطلبات وتقنيات تصميم الاختبار وتقارير الأخطاء. وما يتغير هو المرجع الذي تحكم به على سلوك المنصة. والفروق الأربعة أدناه تغطي معظم حالات الاختبار الخاصة بالمنصة، ويزوّدك القسم الأخير بأدوات التثبيت والفحص والتسجيل على كل منصة؛ أما أحجام الأجهزة ومصفوفة الأجهزة فموضوع الدرس التالي.
- الأذونات: كيف يسأل النظام وكم مرة، وماذا يحدث بعد الرفض.
- التنقل للخلف: هل يملك النظام أم التطبيق فعل «الرجوع»، وماذا تعني كل إيماءة.
- المتاجر: كيف يصل البناء إلى المختبِرين ثم إلى المستخدمين، وما الذي يفحصه المتجر.
- إصدارات النظام: كم إصداراً مستخدماً في الوقت نفسه، وما الذي يغيّر السلوك بينها.
- العدّة: كيف يصل البناء إلى الجهاز، وأي إعدادات المطوّر تفيد، وأين السجلات وتقارير التعطّل.
Android
نواة مفتوحة المصدر، وشركات أجهزة كثيرة، وتطبيقات من Google Play وغيره
- من يطرحه:
- Google وشركات مصنّعة كثيرة، لكل منها طبقة نظام خاصة
- الأذونات:
- حوار وقت التشغيل؛ يمكن السؤال مجدداً بعد رفض واحد ويصمت بعد رفضين؛ منح «هذه المرة فقط»
- التنقل للخلف:
- زر رجوع أو إيماءة من النظام في كل شاشة؛ الرجوع في الجذر يغادر التطبيق
- الوصول إلى المختبِرين والمستخدمين:
- ملف APK يُثبَّت مباشرةً؛ مسارات Play الداخلية والمغلقة والمفتوحة؛ طرح مرحلي
- إصدارات النظام:
- إصدارات كثيرة تبقى لسنوات؛ يعتمد السلوك على النظام وعلى مستوى API المستهدف
- إعدادات المطوّر:
- خيارات المطوّر: تصحيح USB، و«عدم الاحتفاظ بالأنشطة»، و«إظهار النقرات»، وحد معدل التنزيل؛ والتحكم في الشبكة في المحاكي
- السجلات وتقارير التعطّل:
- adb logcat وadb bugreport مع آثار ANR؛ ومعدلا التعطّل وANR في Android vitals
iOS
جهة واحدة للعتاد والنظام وأدوات البناء والمتجر
- من يطرحه:
- Apple وحدها: أجهزتها وأدواتها (Xcode على Mac) ومتجرها
- الأذونات:
- حوار نظام واحد لكل مورد ثم الإعدادات فقط؛ نص الغرض إلزامي
- التنقل للخلف:
- لا رجوع من النظام: زر رجوع التطبيق، وسحب الحافة، وسحب الأوراق لأسفل
- الوصول إلى المختبِرين والمستخدمين:
- بناءات TestFlight تنتهي صلاحيتها؛ مراجعة App Store؛ إصدار مرحلي على سبعة أيام
- إصدارات النظام:
- إصدار واحد يصل إلى كل الأجهزة المدعومة في اليوم نفسه؛ بعض التغييرات تنتظر إعادة البناء بحزمة SDK الجديدة
- إعدادات المطوّر:
- «وضع المطوّر» لتشغيل بناءات التطوير؛ وNetwork Link Conditioner للشبكات البطيئة أو الفاقدة للحزم
- السجلات وتقارير التعطّل:
- تطبيق Console وXcode على Mac؛ سجلات التعطّل على الجهاز وفي Organizer؛ مراقب النظام (Watchdog) بدل ANR
القواعد وفق إصدارات المنصتين الحالية؛ اقرأ تغييرات السلوك في كل إصدار نظام جديد.
الأذونات: حوار واحد وقاعدتان مختلفتان
على المنصتين يحتاج المورد المحمي (الكاميرا والموقع والميكروفون وجهات الاتصال والصور والإشعارات) إلى موافقة المستخدم عبر حوار نظام لا يستطيع التطبيق تنسيقه ولا تخطّيه. والفرق في التسلسل. في Android تُطلب الأذونات في وقت التشغيل منذ Android 6.0؛ ويمكن للتطبيق أن يسأل مجدداً بعد الرفض الأول، لكن منذ Android 11 يجعل الرفض الثاني النظام يتوقف عن عرض الحوار، فعلى التطبيق أن يوفّر طريقاً إلى الإعدادات. وأضاف Android 11 أيضاً منح «هذه المرة فقط» للموقع والميكروفون والكاميرا، وأضاف Android 12 الموقع التقريبي، وجعل Android 13 نشر الإشعارات إذناً من أذونات وقت التشغيل. كما يمكن لنظام Android أن يعيد ضبط أذونات تطبيق لم يُستخدم منذ شهور.
أما في iOS فيعرض النظام حوار كل إذن مرة واحدة. وبعد الرفض لا يستطيع التطبيق عرضه مجدداً أبداً؛ فعلى المستخدم تغيير الإعداد في تطبيق «الإعدادات»، وعلى التطبيق أن يشرح ذلك. والموارد مثل الكاميرا والميكروفون والموقع والصور وجهات الاتصال تحتاج إلى نص غرض (Purpose String) في إعدادات التطبيق (مثل NSCameraUsageDescription)؛ وإذا كان مفقوداً فشل الوصول وقد يتعطّل التطبيق، وترفض مراجعة App Store البناء. ويضيف الموقع خيار «السماح مرة واحدة»، الذي تنتهي صلاحيته عندما يتوقف استخدام التطبيق فيمكن للتطبيق أن يسأل مجدداً لاحقاً، ومفتاح الموقع الدقيق؛ ويمكن قصر الصور على عناصر مختارة، وكانت الإشعارات تحتاج إلى إذن دائماً، ويحتاج التتبع عبر التطبيقات إلى طلب App Tracking Transparency المنفصل.
وتغيير إذن من الإعدادات والتطبيق في الخلفية قد يُنهي عملية التطبيق: فينهيها Android عند إلغاء إذن، وينهيها iOS عند تغيير كثير من إعدادات الخصوصية، مثل الكاميرا، منحاً أو إلغاءً. فتكون العودة إلى التطبيق عندئذٍ بدء تشغيل بارداً (Cold Start)، أي يُشغَّل التطبيق من جديد في عملية جديدة، ويجب أن يستعيد موضع المستخدم. ويسرد الدليل المصاحب لسيناريوهات اختبار تطبيقات الجوال سيناريوهات الأذونات العامة؛ وقواعد المنصة أعلاه تعطيك النتيجة المتوقعة لكل منها.
- اطلب في السياق: يجب أن يظهر الحوار عند استخدام الميزة، بعد شرح قصير، لا عند أول تشغيل.
- الرفض: تتراجع الميزة بسلاسة مع رسالة واضحة وزر «فتح الإعدادات» يعمل؛ ولا حلقة من الحوارات.
- المنح لاحقاً من الإعدادات: تعمل الميزة عند العودة دون إعادة تثبيت.
- الامتثال للمتجر: يطابق السبب الذي يقدّمه التطبيق لكل إذن ما تفعله الميزة (نص الغرض في iOS؛ وفي Google Play الإقرار المطلوب للأذونات الحساسة مثل الموقع في الخلفية)؛ فالمراجعون في المتجرين يرفضون الشروح الغامضة أو المفقودة.
مثال تطبيقي: إذن الكاميرا في مسار الدفع برمز QR
المتطلب: «في شاشة الدفع، يضغط المستخدم «مسح» ويوجّه الكاميرا إلى رمز QR الخاص بالتاجر. وإذا كانت الكاميرا غير متاحة، يمكنه إدخال رمز التاجر يدوياً». يطرح الفريق الميزة نفسها على Android وiOS. وفيما يلي سلوك الأذونات الذي يتوقعه المختبِر من كل منصة، وهو ما يصبح عمود النتيجة المتوقعة في حالات الاختبار.
- TC-1 (المنصتان): تثبيت جديد، اضغط «مسح»: ورقة شرح ثم حوار النظام؛ امنح الإذن: تفتح الكاميرا ضمن المسار نفسه.
- TC-2 (Android 11 فأحدث): ارفض مرة واضغط «مسح» مجدداً: يظهر حوار النظام مرة أخرى؛ ارفض ثانيةً واضغط «مسح» للمرة الثالثة: لا حوار، ويعرض التطبيق خيار الإدخال اليدوي وزر «فتح الإعدادات» الذي يصل إلى صفحة أذونات التطبيق.
- TC-3 (iOS): ارفض مرة واضغط «مسح» مجدداً: لا حوار من النظام؛ يعرض التطبيق الإدخال اليدوي و«فتح الإعدادات»؛ امنح الإذن من الإعدادات وعد: أُعيد تشغيل التطبيق و«مسح» تفتح الكاميرا.
- TC-4 (Android 11 فأحدث): اختر «هذه المرة فقط»، ادفع، اترك التطبيق مدة، ثم عد واضغط «مسح»: يظهر الحوار مجدداً بدلاً من إخفاق صامت.
- TC-5 (المنصتان): ألغِ إذن الكاميرا من الإعدادات وشاشة الدفع مفتوحة، ثم عد: يُعاد تشغيل التطبيق بسلامة دون تعطّل، وتُستعاد حالة الدفع المعلّقة أو تُلغى بوضوح.
- TC-6 (المنصتان): مع رفض الإذن، يُكمل إدخال الرمز اليدوي عملية دفع، فلا يعطّل الرفض هدف العمل أبداً.
Camera permission for "Scan a QR code to pay"
Permission state Android 11+ iOS
--------------------------------------------------------------------------------------
Never asked system dialog on request system dialog on request
Denied once, asked again dialog shown again no dialog: route to Settings
Denied twice, asked again no dialog: route to Settings no dialog: route to Settings
"Only this time" granted expires soon after leaving not offered for the camera
Revoked in Settings while open process ends, relaunch process ends, relaunch
Purpose text explain before the dialog NSCameraUsageDescriptionالمتاجر والإصدارات وإصدارات النظام
ينشر Google Play التطبيق من حزمة Android App Bundle، ويوفّر مسارات اختبار داخلية ومغلقة ومفتوحة قبل الإنتاج، وطرحاً مرحلياً (Staged Rollout) إلى نسبة من المستخدمين يمكن إيقافه، وتقرير ما قبل الإطلاق الذي يشغّل البناء على مجموعة أجهزة ويبلّغ عن الأعطال. وخارج Play يمكن تثبيت ملف APK مباشرةً، وتُباع بعض الأجهزة دون خدمات Google أصلاً. أما App Store فيأخذ بناءً مرفوعاً من Xcode؛ ويوزّعه TestFlight على ما يصل إلى 100 مختبِر داخلي و10,000 مختبِر خارجي (تنتهي صلاحية البناء بعد 90 يوماً، ويمرّ أول بناء يُرسَل إلى المختبِرين الخارجيين بمراجعة تجريبية)، وتفحص مراجعة App Store بناء الإنتاج، ويوزّع الإصدار المرحلي (Phased Release) التحديث على سبعة أيام ويمكن إيقافه مؤقتاً. ولا يعيد أي من المتجرين المستخدمين الذين حدّثوا إلى البناء السابق: فتوقف الطرح أو تعلّقه وتنشر بناءً مُصلَحاً برقم نسخة أعلى.
يفحص المتجران الصفحة التعريفية مقابل التطبيق: إعلانات الخصوصية (قسم «أمان البيانات» في Play، وتسميات «خصوصية التطبيق» في App Store)، والأسباب المقدَّمة للأذونات، ولقطات الشاشة، والميزات التي يستطيع المراجع الوصول إليها فعلاً. ورفض المراجعة عيب في الإصدار، لذا اختبر الصفحة التعريفية ومسار المراجع داخل التطبيق قبل التقديم، بما في ذلك حساب الاختبار الذي سيستخدمه المراجع.
وتتصرف إصدارات النظام بطريقة مختلفة على المنصتين. يعرّف Android إصداراته بمستوى API (فنظام Android 15 هو API 35)؛ وتصل التحديثات إلى الأجهزة عبر الشركات المصنّعة، فتبقى عدة إصدارات مستخدمة لسنوات. ويعلن تطبيقك أدنى إصدار يُثبَّت عليه (minSdkVersion) والإصدار الذي يتبنّى سلوكه (targetSdkVersion)؛ ويشترط Google Play هدفاً حديثاً، ورفعه يفعّل تغييرات السلوك لتطبيقك، مما يجعل رفع الهدف حدثاً يستدعي الاختبار. أما في iOS فتطرح Apple إصداراً واحداً لكل الأجهزة المدعومة في اليوم نفسه، دون شركة مصنّعة وسيطة، مع نسخة تجريبية عامة كل صيف؛ وتعلن التطبيقات هدف نشر (Deployment Target)، وبعض تغييرات السلوك لا تسري إلا بعد إعادة بناء التطبيق بحزمة SDK الجديدة، فإصدار Xcode الجديد حدث يستدعي الاختبار أيضاً.
- مسار التثبيت: اختبر البناء الذي سيحصل عليه المستخدمون (مسار المتجر أو TestFlight)، لا نسخة التصحيح من المطور فقط.
- مسار التحديث: ثبّت نسخة الإنتاج السابقة واستخدمها ثم حدّث؛ يجب أن تبقى البيانات والجلسات.
- مجموعة الأنظمة: أحدث إصدار ونسخته التجريبية، وأقدم إصدار مدعوم، وطبقات الشركات المصنّعة التي تحمل معظم حركة مستخدميك؛ وتكشف أدوات التحليلات ولوحات المتاجر وتقارير التعطّل أي إصدارات النظام تصل فعلاً، أما سلاسل User-Agent في حركة الويب فأقل فائدة، لأن Chrome على Android وSafari منذ iOS 26 يعلنان إصدار نظام مُجمَّداً (يحوّل الدرس التالي هذا إلى مصفوفة).
- التحديث الإجباري: عندما يتوقف الخادم عن دعم نسخة قديمة، يجب أن يقول التطبيق ذلك ويربط إلى المتجر؛ ويوفّر Android أيضاً تحديثات داخل التطبيق.
جرّبها: مولّد الاختبار الزوجي (Pairwise) جرّبها: محلّل User-Agent
عدّة المختبِر على كل منصة
أما الاختبار على محاكي Android (Emulator) أو محاكي iOS (Simulator) أو جهاز حقيقي فقرار من استراتيجية الأجهزة يغطيه دليل اختبار الجوال؛ ويفترض هذا القسم أن لديك بناءً وجهازاً أو محاكياً واحداً على الأقل لكل منصة. في Android العدّة هي adb (جسر تصحيح Android، ضمن أدوات منصة SDK)، وتُستخدم عبر USB بعد تفعيل «خيارات المطوّر» (Developer Options) بالنقر على رقم البناء سبع مرات في الإعدادات وتشغيل «تصحيح أخطاء USB». ويُثبَّت ملف APK بالأمر adb install؛ أما حزمة Android App Bundle (AAB) فلا تُثبَّت مباشرةً، فاطلب ملف APK شاملاً (Universal)، أو ابنِ من الحزمة ملفات APK للجهاز بأداة bundletool، أو ارفعها إلى «مشاركة التطبيقات الداخلية» (Internal App Sharing) في Play التي تعيد رابط تثبيت. وتحمل مسارات الاختبار في Play مرشحي الإصدار الموقّعين تماماً كالإنتاج.
وفي iOS يصل البناء إلى جهاز حقيقي عبر TestFlight (دعوة أو رابط عام)، أو بناءً للتطوير أو مخصصاً (Ad Hoc) يسرد ملف تعريفه المعرّف الفريد للجهاز (UDID) ويُثبَّت من نافذة «Devices and Simulators» في Xcode؛ ومنذ iOS 16 يحتاج تشغيل بناء موقّع للتطوير إلى تشغيل «وضع المطوّر» (Developer Mode) في «الخصوصية والأمن». ويُدار محاكي iOS من جهاز Mac بالأمر xcrun simctl: تثبيت تطبيق، أو فتح رابط عميق، أو إعادة ضبط إذن، أو تسجيل الشاشة. وثمة نوعان من إعدادات المطوّر يستحقان مكاناً في كل خطة اختبار. الأول «عدم الاحتفاظ بالأنشطة» (Don’t keep activities) في Android، الذي يدمّر كل شاشة لحظة مغادرتها، فيكشف ضياع حالة النماذج والتعطّل عند العودة. والثاني إبطاء الشبكة (Network Throttling): إذ يحاكي Network Link Conditioner في iOS (في الإعدادات ثم «المطوّر»، ويظهر بعد استخدام الجهاز مع Xcode) الشبكةَ البطيئة أو الفاقدة للحزم أو المتعطّلة، وتضبط عناصر التحكم في الشبكة في محاكي Android نوع شبكة أبطأ أو إشارة ضعيفة أو انقطاع اتصال البيانات، وتضيف إصدارات Android الحديثة أيضاً حداً لمعدل تنزيل الشبكة (Network download rate limit) في خيارات المطوّر على الجهاز الحقيقي.
السجلات هي دليلك. يكتب Android كل شيء في logcat: لكل سطر وقت ومعرّف عملية وأولوية من V (مفصّل) إلى F (قاتل) ووسم (Tag)؛ ويبثّه الأمر adb logcat، ويقصره الخيار --pid على تطبيقك، ويجمع adb bugreport السجلات الكاملة مع آثار ANR في ملف مضغوط واحد للمطور. وANR (التطبيق لا يستجيب) هو حوار «لا يستجيب» الذي يعرضه Android عندما يبقى الخيط الرئيسي (Main Thread) للتطبيق، وهو الذي يرسم الشاشة ويعالج النقرات، محجوباً، مثلاً نحو خمس ثوانٍ دون معالجة الإدخال. ويتابع Play معدلي التعطّل وANR في Android vitals، حيث يُعدّ معدل التعطّل الملحوظ للمستخدم فوق 1.09% أو معدل ANR فوق 0.47% سلوكاً سيئاً قد يقلّل ظهور التطبيق في Google Play. أما iOS فيحتفظ بسجل موحّد تقرؤه مباشرةً في تطبيق Console على جهاز Mac والجهاز موصول، أو في وحدة تحكم Xcode عندما يشغّل Xcode التطبيق. وتبقى سجلات التعطّل (ملفات .ips) على الجهاز في الإعدادات ثم «الخصوصية والأمن» ثم «التحليلات والتحسينات» ثم «بيانات التحليلات»، ويجمع Organizer في Xcode سجلات التعطّل المُحلَّلة رمزياً (Symbolicated)، أي التي تُرجمت فيها عناوين الذاكرة إلى أسماء الدوال، من مستخدمي TestFlight وApp Store الذين يشاركونها. وليس في iOS حوار ANR: فمراقب النظام (Watchdog) يُنهي التطبيق الذي يحجب الخيط الرئيسي أو يبدأ ببطء شديد، ويظهر ذلك في سجل التعطّل برمز الاستثناء 0x8badf00d.
- حالات الإذن بأمر واحد:
adb shell pm grantوpm revokeفي Android (والإلغاء يُنهي عملية التطبيق كما في الإعدادات)، وsimctl privacy grantوrevokeوresetفي محاكي iOS؛ وليس فيsimctl privacyخدمة للكاميرا، فحالات الكاميرا مثل المثال التطبيقي تحتاج إلى iPhone حقيقي؛ أما «لم يُطلب» على جهاز حقيقي فتعني إزالة التثبيت وإعادته. - تسجيل الشاشة:
adb shell screenrecordأو المسجّل المدمج في الإعدادات السريعة (Android 11 فأحدث)، مع تفعيل «إظهار النقرات» (Show taps) في خيارات المطوّر ليظهر كل نقر؛ ومسجّل مركز التحكم في iOS، أو QuickTime على جهاز Mac عبر الكابل، أوsimctl io recordVideoفي المحاكي. - أرفق بكل عيب خاص بالمنصة: مقتطف logcat أو تقرير الخطأ في Android، وسجل التعطّل أو مقتطف Console في iOS، وتسجيل الإيماءة أو الحوار. ويستطيع مختبِرو TestFlight أيضاً إرسال لقطة شاشة مع تعليق من داخل التطبيق التجريبي.
- التقاط logcat طويل، وسطوره تحمل معرّف العملية لا اسم حزمة تطبيقك؛ وتعبير نمطي يُبقي فقط سطور معرّف عملية تطبيقك ذات الأولويات W وE وF يحوّله إلى مرفق مقروء.
# Android (adb from the SDK platform tools; USB debugging on)
adb devices # the phone is listed as "device"
adb install -r app-debug.apk # install or update the build
adb shell pm grant com.example.pay android.permission.CAMERA
adb shell pm revoke com.example.pay android.permission.CAMERA
adb logcat --pid=$(adb shell pidof -s com.example.pay) # your running app only
adb bugreport bugreport.zip # full logs and ANR traces
adb shell screenrecord /sdcard/scan.mp4 # Ctrl+C stops it; then:
adb pull /sdcard/scan.mp4
# iOS Simulator (xcrun simctl, from Xcode on a Mac)
xcrun simctl install booted Pay.app
xcrun simctl privacy booted reset location com.example.pay # back to "never asked"
xcrun simctl openurl booted "pay://scan"
xcrun simctl io booted recordVideo scan.mp4أخطاء شائعة
- كتابة نتيجة متوقعة واحدة للمنصتين حيث تحدد المنصة السلوك، فتُعلَّم حالة iOS «ارفض ثم اسأل مجدداً» فاشلةً لأن الحوار لم يظهر.
- اختبار الأذونات على المسار السعيد فقط (المنح عند أول طلب) دون الرفض والرفض الثاني و«هذه المرة فقط» والإلغاء من الإعدادات.
- فحص التنقل للخلف بزر الرجوع على الشاشة فقط في Android دون الإيماءة، أو عدم السحب من الحافة أبداً في iOS.
- اختبار نسخة التصحيح من المطور فقط على أجهزة بقيت على النظام الذي جاءت به، فلا يُختبر أبداً بناء المتجر أو TestFlight الذي يتسلّمه المستخدمون، ولا أحدث نظام ولا نسخته التجريبية ولا أقدم إصدار مدعوم.
- الإبلاغ عن قاعدة منصة على أنها عيب في التطبيق، مثل أن iOS لا يعرض حوار الإذن مرتين، بدلاً من الإبلاغ عن غياب الطريق إلى الإعدادات.
- الإبلاغ عن تعطّل أو تجمّد دون سجل الجهاز، فيضطر المطور إلى التخمين: أرفق سطور logcat أو تقرير الخطأ مع آثار ANR في Android، وسجل التعطّل من الجهاز أو Xcode في iOS.
من منظور ضمان الجودة
في فريق حقيقي يغطي المختبِر المنصتين حتى عندما ينقسم المطورون إلى مجموعة Android ومجموعة iOS. أثناء صقل المتطلبات، اسأل عن كل ميزة تمسّ مورداً محمياً أو التنقل أو الإصدار: ما السلوك المتوقع على كل منصة، ومن قرره. سجّل الإجابات نتائج متوقعة خاصة بكل منصة، واحتفظ بقائمة فحص قصيرة للمنصة (حالات الأذونات، والرجوع في كل شاشة، ومسارا التثبيت والتحديث، وإصدارات النظام) يمرّ بها كل إصدار.
احتفظ بجهاز Android وجهاز iOS على الأقل على أحدث نظام وجهاز على أقدم إصدار مدعوم، وثبّت كل نسخة تجريبية جديدة من النظام على جهاز احتياطي فور نشرها. وفي تقرير الخطأ اذكر المنصة وإصدار النظام والجهاز ونوع البناء (تصحيح، مسار داخلي، TestFlight، إنتاج) وحالة الإذن أو الإيماءة بالضبط، وأرفق مقتطف logcat أو سجل التعطّل وتسجيلاً قصيراً للشاشة؛ فهذا ما يتيح للمطور إعادة إنتاج عيب خاص بالمنصة في دقائق.
تمرين عملي
اكتب حالات اختبار خاصة بكل منصة لميزة «المتاجر القريبة»
يضيف تطبيق تجزئة ميزة «المتاجر القريبة مني»: يطلب تبويب «القريبة» إذن الموقع ويعرض المتاجر مرتبة حسب المسافة. وإذا كان الموقع غير متاح، يمكن للمستخدم كتابة اسم المدينة. اكتب حالات اختبار الأذونات لنظامي Android وiOS مع النتيجة المتوقعة لكل منصة، ثم أضف فحوص التنقل للخلف لتبويب «القريبة» وشاشة تفاصيل المتجر.
اختم بسؤالين عن الإصدار تطرحهما قبل إرسال البناء إلى المتجرين.
- اسرد حالات الإذن على كل منصة: لم يُطلب، ومُنح، ورُفض مرة، ورُفض مرتين (Android)، و«هذه المرة فقط» (Android) أو «السماح مرة واحدة» (iOS)، والدقيق أو التقريبي (iOS، وAndroid 12 فأحدث)، وأُلغي من الإعدادات.
- لكل حالة، اكتب السلوك المتوقع لتبويب «القريبة»، بما فيه البديل بكتابة المدينة.
- اكتب ما يجب أن يفعله الرجوع (إيماءة Android وزره، وسحب الحافة وزر الرجوع في iOS) في تبويب «القريبة» وفي شاشة تفاصيل متجر فُتحت منه.
- دوّن سؤالي الإصدار.
- اكتب الأوامر التي تضع التطبيق في كل حالة إذن على جهاز Android وعلى محاكي iOS دون التنقل في الإعدادات.
إظهار الإجابة النموذجية
الأذونات في Android: أول ضغطة على «القريبة»: شرح قصير ثم حوار النظام بخياري الدقيق والتقريبي و«هذه المرة فقط»؛ التقريبي: تُرتَّب القائمة حسب المسافة مع ملاحظة أن الدقة أقل؛ الرفض مرة: تسأل الزيارة التالية مجدداً؛ الرفض مرتين: لا حوار، ويعرض التبويب حقل المدينة وزر «فتح الإعدادات»؛ «هذه المرة فقط»: تعمل الآن وتسأل مجدداً في زيارة لاحقة؛ الإلغاء من الإعدادات أثناء فتح التبويب: يُعاد تشغيل التطبيق ويُفتح التبويب على حقل المدينة دون تعطّل.
الأذونات في iOS: أول ضغطة: شرح ثم حوار النظام بخيارات «السماح مرة واحدة» و«السماح أثناء استخدام التطبيق» و«عدم السماح» ومفتاح الدقة؛ «السماح مرة واحدة»: تعمل في هذه الجلسة وتسأل مجدداً عند التشغيل التالي؛ «عدم السماح»: يعرض التبويب حقل المدينة و«فتح الإعدادات»، ولا يعود حوار النظام أبداً؛ إيقاف مفتاح الدقة: تُرتَّب القائمة حسب المسافة مع ملاحظة أن الدقة أقل؛ المنح من الإعدادات ثم العودة: تُرتَّب القائمة حسب المسافة دون إعادة تثبيت، حتى لو أُعيد تشغيل التطبيق في الأثناء؛ الإلغاء من الإعدادات والتطبيق في الخلفية: عند العودة يعرض التبويب حقل المدينة دون تعطّل.
التنقل للخلف في Android: في شاشة تفاصيل المتجر يعود الرجوع و«لأعلى» كلاهما إلى قائمة «القريبة» عند موضع التمرير نفسه؛ وفي تبويب «القريبة» (تبويب جذري) يغادر الرجوع التطبيق أو يعود إلى التبويب السابق حسب القاعدة المتفق عليها، ولا يصل إلى شاشة فارغة أبداً؛ وبعد رابط عميق إلى متجر، يذهب «لأعلى» إلى قائمة «القريبة» ويعود الرجوع إلى حيث أتى المستخدم. وفي iOS: لشاشة التفاصيل زر رجوع ويعمل سحب الحافة؛ ويحتفظ تبويب «القريبة» بسجله الخاص عندما يبدّل المستخدم التبويبات ويعود.
سؤالا الإصدار: هل يطابق نص غرض الموقع في الصفحة التعريفية وداخل التطبيق الميزة (المتاجر القريبة فقط، دون تتبع في الخلفية)؟ وعلى أي إصدارات نظام وأي بناء (مسار داخلي، TestFlight) سيُختبر مرشح الإصدار قبل التقديم؟
الأوامر في Android: adb uninstall com.example.retail ثم adb install -r app.apk يعطي «لم يُطلب»؛ وadb shell pm grant com.example.retail android.permission.ACCESS_COARSE_LOCATION مع ACCESS_FINE_LOCATION يعطي الموقع الدقيق، والتقريبي وحده يعطي الموقع التقريبي؛ وadb shell pm revoke يعطي الإلغاء ويُنهي عملية التطبيق؛ أما «رُفض مرة» و«رُفض مرتين» و«هذه المرة فقط» فتصل إليها بالإجابة عن الحوار نفسه. وفي محاكي iOS: xcrun simctl privacy booted reset location com.example.retail يعيد «لم يُطلب»، وgrant location أو revoke location يضبطان حالتي المنح والرفض؛ أما «السماح مرة واحدة» ومفتاح الدقة فيُضبطان بالإجابة عن الحوار؛ وعلى iPhone حقيقي لا يتغير الإذن إلا من الإعدادات أو بإعادة التثبيت.
أسئلة شائعة
هل أحتاج إلى جهاز Mac لاختبار تطبيقات iOS؟
لتشغيل تطبيق على iPhone تحتاج إلى بناء أُنتج بـ Xcode على جهاز Mac، ويوزَّع عادةً عبر TestFlight أو ملف تعريف. ولا يحتاج المختبِر إلى Mac لتثبيت بناء TestFlight على جهاز واختباره، لكن البناء نفسه يُنتَج بـ Xcode على macOS، في جهاز Mac لدى الفريق أو في خدمة بناء سحابية، ومحاكي iOS لا يعمل إلا على macOS.
لماذا لا يعرض iOS حوار الإذن مجدداً بعد أن رفضته؟
هذه قاعدة المنصة: يعرض iOS حوار كل إذن مرة واحدة. وعلى التطبيق أن يكتشف حالة الرفض ويشرح ما ينقص ويوفّر طريقاً إلى تطبيق «الإعدادات». والعيب الذي تبلّغ عنه هو غياب الطريق إلى الإعدادات أو تعطّله، لا غياب الحوار.
هل يمكن اختبار تطبيق Android دون Google Play؟
نعم. يمكن تثبيت ملف APK للتصحيح أو الإصدار مباشرةً على جهاز أو محاكي، وهكذا تُسلَّم معظم نسخ الاختبار. لكن قبل الإصدار اختبر أيضاً البناء القادم من مسار اختبار في Play، لأن التوقيع وملفات APK التي يولّدها Play من حزمة التطبيق وميزات Play مثل التحديثات داخل التطبيق وفحوص السلامة تتصرف بطريقة مختلفة عن ملف APK المثبّت يدوياً.
هل رفض مراجعة المتجر عيب؟
عامله كعيب: فهو يعطّل الإصدار. وأسبابه المعتادة تعطّل على جهاز المراجع، أو ميزة لا يستطيع المراجع الوصول إليها، أو نص غرض إذن غامض، أو صفحة تعريفية لا تطابق التطبيق. واختبار مسار المراجع والصفحة التعريفية قبل التقديم يمنع معظمها.
المراجع
- Certified Tester Mobile Application Testing (CT-MAT)منهج ISTQB التخصصي لاختبار تطبيقات الجوال: أنواع التطبيقات وتحديات الأجهزة والمنصات وأنواع الاختبار والأدوات.
- Core app quality guidelinesمعايير Google الأساسية لجودة تطبيقات Android — التجربة المرئية والوظائف والأداء والخصوصية والأمان — مع الاختبارات المستخدمة للتحقق منها.
- Test apps on Androidإرشادات Android الرسمية للاختبار: أنواع الاختبارات ونطاقاتها، والاختبارات المحلية مقابل المُجهَّزة على الجهاز، وأفضل الممارسات.
- Android vitalsمقاييس جودة التطبيقات التي يجمعها Google Play من أجهزة المستخدمين — ومنها معدّلا الأعطال وعدم الاستجابة (ANR) كما يلحظهما المستخدم ضمن المؤشرات الأساسية — وحدود السلوك السيئ التي تؤثر في ظهور التطبيق.
تدرّب بأدوات متقن
عرّف الحالات والأحداث، ثم ولّد جدول الانتقالات واختبارات الانتقالات الصالحة/غير الصالحة وتغطية 0-switch/1-switch.
ولّد حالات اختبار منظّمة (المعرّف والعنوان والشروط المسبقة والخطوات والنتيجة المتوقّعة والأولوية) من وصف الميزة وقائمة الحقول.
ولّد سيناريوهات اختبار عالية المستوى تغطي الجوانب الوظيفية والسلبية والأمنية وسهولة الاستخدام والتوافق لأي ميزة.
ولّد أصغر مجموعة اختبارات زوجية (all-pairs) من المعاملات وقيمها.
تحليل سلاسل User-Agent إلى المتصفح والإصدار والمحرك ونظام التشغيل ونوع الجهاز مع كشف الروبوتات.
اختبر التعابير النمطية مباشرةً مع إبراز التطابقات ومجموعات الالتقاط ومعاينة الاستبدال.
للتعمّق أكثر
- اختبار تطبيقات الجوال: دليل عملياستراتيجية الأجهزة: المحاكيات والأجهزة الحقيقية ومزارع الأجهزة
- سيناريوهات اختبار تطبيقات الجوالأذونات وقت التشغيل: المنح والرفض والسحب
- سيناريوهات اختبار تطبيقات الجوالالتثبيت والتحديث وإلغاء التثبيت وإعادة التثبيت
- اختبار تطبيقات الجوال: دليل عمليإرشادات جودة المنصات والجاهزية للمتجر
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.