سيناريوهات اختبار تطبيقات الجوال
معظم عيوب الجوال لا تظهر حين يتبع المختبِر المسار السعيد على هاتف مشحون بالكامل متصل بشبكة Wi-Fi المكتب. إنها تظهر حين تصل مكالمة أثناء الدفع، وحين يدخل القطار نفقاً، وحين يرفض المستخدم إذن الكاميرا، وحين يُنهي النظام التطبيق في الخلفية، وحين يلتقي تحديثٌ ببيانات كتبها الإصدار السابق. هذا الدليل كتالوج لتلك الظروف، مع ما يجب ملاحظته وكيف تفرض كل ظرف منها على المحاكي أو الجهاز.
استخدمه قائمة فحص عند تصميم اختبارات ميزة على الجوال. أما النظرة الشاملة إلى المجال — أنواع التطبيقات واستراتيجية الأجهزة والأمان والأتمتة — ففي الدليل المحوري لاختبار الجوال؛ وهذه الصفحة تتعمق في السيناريوهات.
كيف تستخدم هذا الكتالوج
كل سيناريو هو ظرف مع ملاحظة: ضع التطبيق في حالة معينة، وطبّق اضطراباً خاصاً بالجوال، وافحص ما يراه المستخدم وشكل البيانات بعد ذلك. حوّل ما ينطبق منها إلى حالات اختبار (Test cases) بشروط مسبقة وخطوات ونتائج متوقعة (يغطي دليل كتابة حالات الاختبار الصيغة). اختر حسب المخاطر: الشاشات التي تحمل مدخلات غير محفوظة، والميزات التي تحتاج الشبكة، والمسارات التي تستخدم الأذونات أو تغادر التطبيق (الدفع، أو تسجيل الدخول عبر تطبيق آخر)، وكل ما يخزّن بيانات محلياً.
يمكن نمذجة دورة حياة التطبيق كآلة حالات (State machine)، وكثير من عيوب الجوال انتقالات خاطئة بين حالاتها. ولأغراض الاختبار يكفي نموذج مبسّط مشترك بين المنصتين من خمس حالات: غير مشغّل، وفي المقدمة، وفي الخلفية، ومعلّق، ومُنهى. ولا تعرّف أيٌّ من المنصتين هذه المجموعة بعينها: فـ«معلّق» (Suspended) مصطلح من iOS، و«مُنهى» يعني موت العملية (Process death)، أي أن يُنهي النظام عملية التطبيق وهو في الخلفية، ثم يعود إليه المستخدم لاحقاً من التطبيقات الأخيرة متوقعاً أن يجد حالته كما تركها. نمذجة الشاشات الحرجة كحالات وأحداث (وصول مكالمة، إرسال التطبيق إلى الخلفية، إنهاء العملية، إعادة فتحه من التطبيقات الأخيرة) تعطيك جدول انتقالات وقائمة واضحة بما اختبرته من انتقالات وما لم تختبره.
| # | من | إلى | الحدث ← ما يجب فحصه |
|---|---|---|---|
| 1 | غير مشغّلالبداية | في المقدمة | تشغيل التطبيق |
| 2 | في المقدمة | في المقدمة | تغيير في الإعدادات (Android): التدوير أو اللغة أو الوضع الداكن أو حجم الخط يعيد إنشاء الشاشة افتراضياً ← النص المكتوب والاختيارات وموضع التمرير والحوارات المفتوحة تبقى |
| 3 | في المقدمة | في الخلفية | إرسال التطبيق إلى الخلفية: ينتقل المستخدم إلى تطبيق آخر، أو يقفل الشاشة، أو يذهب إلى تطبيق بنك أو متصفح |
| 4 | في الخلفية | في المقدمة | يعود المستخدم بعد ثوانٍ أو دقائق أو ساعات ← يُعالَج انتهاء الجلسة، وتظهر الشاشة الصحيحة بالحالة الصحيحة |
| 5 | في الخلفية | معلّق (iOS) | يعلّق النظام التطبيق |
| 6 | معلّق (iOS) | في المقدمة | يعود المستخدم ← الفحوص نفسها كما في العودة من الخلفية |
| 7 | في الخلفية | مُنهى | ينهي النظام العملية لاستعادة الذاكرة؛ ويمكن فرض ذلك بالأمر adb shell am kill |
| 8 | معلّق (iOS) | مُنهى | ينهي النظام العملية لاستعادة الذاكرة |
| 9 | مُنهى | في المقدمة | إعادة الفتح من التطبيقات الأخيرة ← يُعاد بناء الشاشة ويُستعاد ما كتبه المستخدم |
نموذج مبسّط مشترك بين المنصتين لأغراض الاختبار: لا تعرّف أيٌّ منهما هذه الحالات الخمس بعينها، و«معلّق» مصطلح من iOS. وفي Android يُعدّ خيار «عدم الاحتفاظ بالأنشطة» طريقة رخيصة لاكتشاف غياب استعادة الحالة.
ID: MOB-NET-04
Area: Network — connection lost mid-request
Screen: Checkout › Place order
Setup: Signed-in customer, 2 items in cart, Wi-Fi on, mobile data off
Trigger: Tap "Place order", then disable Wi-Fi within one second
Observe: - A clear "no connection" state; no endless spinner
- After reconnecting: exactly one order exists (order list and API)
- Retrying does not charge the card twice
Devices: Tier 1 Android and iOSالتثبيت والتحديث وإلغاء التثبيت وإعادة التثبيت
التحديثات هي المكان الذي تختبئ فيه عيوب ترحيل البيانات (Data migration): تغيّر مخطط قاعدة البيانات المحلية، أو أُعيدت تسمية مفتاح تفضيلات، أو تغيّرت صيغة الرمز المخزّن، أو انتقل ملف مخزّن مؤقتاً. اختبر التحديث من كل إصدار قديم ما زلت تدعمه — واحتفظ بالبناءات القديمة كمخرجات لتتمكن من تثبيتها — وافعل ذلك ببيانات واقعية على الجهاز، لا بتثبيت جديد.
- تثبيت نظيف على أقدم وأحدث إصدار نظام مدعوم؛ وأول تشغيل دون اتصال بالشبكة.
- التثبيت وأول تشغيل على جهاز يكاد لا يملك مساحة تخزين حرة.
- التحديث من الإصدار السابق ومن أقدم إصدار مدعوم مع جلسة مسجّلة، ومسودات، وإجراءات مؤجلة دون اتصال، وإعدادات، وملفات منزّلة — كل شيء يبقى ويظل المستخدم مسجّل الدخول.
- التحديث أثناء تنزيل أو مزامنة في الخلفية.
- التحديث الإجباري: الإصدار الأقدم من الحد الأدنى المدعوم يعرض طلب تحديث واضحاً بدلاً من فشل استدعاءات API.
- إلغاء التثبيت ثم إعادة التثبيت: البيانات المحلية تختفي، وبيانات الخادم تعود، والنسخ الاحتياطي والاستعادة يعملان كما صُمّما. وعلى iOS قد تبقى بعض بيانات Keychain بعد حذف التطبيق، فقرّر واختبر هل تُعامَل إعادة التثبيت كمستخدم جديد.
- مسح بيانات التطبيق (Android) أو تفريغ التطبيق (Offload) على iOS، الذي يُبقي المستندات والبيانات، ثم إعادة التشغيل.
# Android (adb) — examples
adb install shop-3.8.0.apk # old version; now sign in, create drafts, change settings
adb install -r shop-4.0.0.apk # update, keeping app data
adb shell pm clear com.example.shop # clear app data
adb uninstall com.example.shop
# iOS Simulator (xcrun simctl) — examples
xcrun simctl install booted Shop-3.8.app
xcrun simctl install booted Shop-4.0.app # install the new build, then check what data survived
xcrun simctl uninstall booted com.example.shopأذونات وقت التشغيل: المنح والرفض والسحب
يطلب Android الأذونات الخطرة وقت التشغيل (Runtime permissions)، ويسأل iOS في أول مرة يستخدم فيها التطبيق مورداً محمياً، عارضاً نص الغرض الذي كتبه التطبيق. وفي المنصتين يستطيع المستخدم تغيير إجابته لاحقاً من الإعدادات، وتضيف الإصدارات الحديثة خيارات مثل السماح لمرة واحدة فقط أو مشاركة موقع تقريبي بدلاً من الدقيق؛ كما جعل Android الإشعارات إذناً يُطلب وقت التشغيل. يجب أن يعمل التطبيق — أو يتراجع بوضوح — مع كل إجابة.
- المنح عند الطلب الأول: تعمل الميزة فوراً دون إعادة تشغيل التطبيق.
- الرفض: يشرح التطبيق ما الذي لم يعد متاحاً ويعرض طريقاً آخر (كتابة العنوان بدلاً من استخدام الموقع).
- الرفض مجدداً أو «عدم السؤال مرة أخرى»: لا يكرر التطبيق الطلب في حلقة؛ بل يشرح كيف يُفعَّل الإذن من الإعدادات.
- السماح مرة واحدة: تسأل الجلسة التالية من جديد، وتتعامل الميزة مع ذلك.
- الموقع التقريبي أو الوصول المحدود إلى الصور: الميزات التي تحتاج أكثر تقول ذلك بدلاً من الفشل بصمت.
- السحب من الإعدادات والتطبيق في الخلفية. في Android تُنهى عملية التطبيق عند سحب إذن؛ وعند العودة يجب أن يُعاد تشغيل التطبيق بسلاسة على شاشة منطقية.
- يُطلب الإذن في سياقه، عند استخدام الميزة — لا كلها دفعة واحدة عند أول تشغيل — ونص الغرض دقيق.
# Android
adb shell pm grant com.example.shop android.permission.CAMERA
adb shell pm revoke com.example.shop android.permission.CAMERA
# iOS Simulator
xcrun simctl privacy booted grant photos com.example.shop
xcrun simctl privacy booted revoke photos com.example.shop
xcrun simctl privacy booted reset all com.example.shopالمقاطعات ودورة حياة التطبيق
المقاطعة (Interruption) هي أي شيء يُخرج التطبيق من المقدمة أو يغطيه. وأخطرها غير مرئي: فبينما التطبيق في الخلفية قد يُنهي النظام عمليته لاستعادة الذاكرة، وعندما يعود المستخدم يجب أن يعيد التطبيق بناء الشاشة واستعادة ما كتبه. وفي Android يدمّر خيار المطوّرين «عدم الاحتفاظ بالأنشطة» (Don’t keep activities) كل شاشة بمجرد مغادرة المستخدم لها — وهي طريقة رخيصة لاكتشاف غياب استعادة الحالة. كما أن تغييرات الإعدادات مثل التدوير أو اللغة أو الوضع الداكن أو حجم الخط تعيد إنشاء الشاشة افتراضياً في Android.
- مكالمة واردة، مع الرد والرفض، أثناء إدخال نموذج، وتشغيل فيديو، والتسجيل، والدفع.
- إشعارات من تطبيقات أخرى؛ وسحب لوحة الإشعارات أو مركز التحكم في منتصف المسار.
- التبديل إلى تطبيق آخر والعودة بعد ثوانٍ، وبعد دقائق، وبعد عدة ساعات (انتهاء الجلسة).
- قفل الشاشة وفتحها أثناء انتظار رمز OTP أو أثناء عمل مؤقّت.
- يرن منبّه، أو يظهر تحذير انخفاض البطارية؛ ويُفعَّل توفير البطارية أو وضع الطاقة المنخفضة.
- انقطاع سماعات Bluetooth أثناء تشغيل الصوت — يجب أن يتوقف التشغيل مؤقتاً.
- موت العملية: أرسل التطبيق إلى الخلفية، وأنهِ عمليته، وأعد فتحه من التطبيقات الأخيرة.
- الذهاب إلى تطبيقات أخرى والعودة — تطبيق بنك، أو متصفح لتسجيل الدخول أو التحقق 3-D Secure — يعيد المستخدم إلى الشاشة الصحيحة بالحالة الصحيحة.
- تقسيم الشاشة، والصورة داخل الصورة، وطي الجهاز القابل للطي أو فتحه في منتصف المسار.
# Android — force the conditions
adb shell am kill com.example.shop # kill the background process, then reopen from Recents
adb shell dumpsys battery unplug
adb shell dumpsys battery set level 5 # simulate a low battery
adb shell dumpsys battery reset
adb shell dumpsys deviceidle force-idle # put the device into Doze
adb shell dumpsys deviceidle unforce
# Android emulator — incoming call and SMS
adb emu gsm call 5551234
adb emu sms send 5551234 "Your code is 482913"تغيّر الشبكة والعمل دون اتصال والمزامنة
الشبكة على الجوال متغيّر لا ثابت. اختبر الانتقالات وجودة الاتصال، لا حالتي «متصل» و«غير متصل» فقط. وفي التطبيقات التي تعمل دون اتصال، تكون المزامنة (Sync) هي الخطر الأكبر: تغييرات مؤجلة تُرسل مرتين أو بترتيب خاطئ، وتعارضات بين الأجهزة تُحل بصمت، وإجراءات مؤجلة تحت جلسة انتهت في الأثناء.
- من Wi-Fi إلى الشبكة الخلوية والعكس أثناء الرفع والتنزيل والبث.
- تشغيل وضع الطيران وإيقافه في منتصف طلب.
- التشغيل دون اتصال: محتوى مخزّن مع مؤشر واضح لانعدام الاتصال؛ والإجراءات مؤجلة أو معطّلة مع شرح.
- الشبكة البطيئة (زمن استجابة عالٍ وعرض نطاق منخفض): حالات تحميل، ومهل معقولة، ولا إرسال مكرر بسبب النقرات المستعجلة.
- الشبكة المتقطعة (انقطاعات وفقدان حزم): إعادة المحاولة مع تباعد متزايد، ولا سجلات مكررة؛ وطلبات الطلب والدفع متساوية الأثر.
- بوابة الشبكة المقيدة (Captive portal) في فندق أو مطار: متصل لكن دون إنترنت — يتلقى التطبيق صفحة تسجيل دخول HTML بدلاً من JSON، ويجب أن يعرض رسالة شبكة لا خطأ تحليل.
- تعارض دون اتصال: عدّل سجلاً دون اتصال على الجهاز A، وعدّل السجل نفسه متصلاً على الجهاز B، ثم أعد اتصال A — تُطبَّق قاعدة التعارض المتفق عليها وتكون ظاهرة.
- إجراءات مؤجلة تُرسل بعد انتهاء الجلسة دون اتصال؛ وتغيّر ساعة الجهاز أو منطقته الزمنية أثناء انعدام الاتصال.
- تفعيل موفّر البيانات أو تقييد بيانات الخلفية.
# Android
adb shell svc wifi disable # and: enable
adb shell svc data disable # and: enable
# Android emulator — start with a throttled network
emulator -avd Pixel_Test -netspeed edge -netdelay gprs
# iOS — Network Link Conditioner (device Developer settings, or Xcode additional tools for the Mac)
# Server side — point the app at an endpoint that answers slowly or with an error codeجرّبها: محاكي رموز حالة API جرّبها: مولّد استجابات خطأ وهمية
الشاشات والاتجاه والإيماءات والإدخال
- دوّر الجهاز في كل شاشة فيها إدخال: النص المكتوب والاختيارات وموضع التمرير والحوارات المفتوحة تبقى.
- بدّل الوضع الداكن والتطبيق مفتوح؛ وافحص التباين والصور في الوضعين.
- أكبر حجم خط أو أكبر حجم Dynamic Type: لا نص مقصوص أو متداخل، والشاشات الطويلة قابلة للتمرير.
- غيّر حجم العرض في Android؛ واختبر أصغر وأكبر شاشة في مصفوفتك.
- لوحة المفاتيح: النوع الصحيح لكل حقل (رقمي لـ OTP والهاتف، وبريد للبريد الإلكتروني)، والحقل المُركّز عليه وزر الإرسال يبقيان ظاهرين، و«التالي» ينقل التركيز، والتعبئة التلقائية لرمز OTP تعمل حيث تدعمها المنصة.
- الإيماءات: النقر، والنقر المزدوج، والضغط المطوّل، والسحب، والقرص، والجر، والسحب للتحديث؛ والسحب المخصص من الحافة لا يتعارض مع إيماءة الرجوع في النظام.
- النقر السريع المتكرر على أزرار الإرسال لا ينشئ تكرارات.
- من اليمين إلى اليسار (RTL): في العربية ينعكس التخطيط، واتجاهات السحب وأسهم الرجوع منطقية، والنص المختلط عربي ولاتيني يُعرض صحيحاً، والحقول تقبل الأرقام العربية الهندية (٠١٢٣) حيث يسمح التطبيق بها.
# Android
adb shell settings put system font_scale 2.0 # large text (reset with 1.0)
adb shell wm size 1080x2400 # emulate another screen (reset: wm size reset)
adb shell wm density 480 # (reset: wm density reset)
adb shell cmd uimode night yes # dark mode on (no = off)
# iOS Simulator
xcrun simctl ui booted appearance dark
# larger text: raise the text size in the simulator’s Settings appجرّبها: مولّد بيانات الاختبار العربية جرّبها: مولّد بيانات اختبار متعددة اللغات جرّبها: مولّد أرقام هواتف وهمية
البطارية والمعالج والذاكرة والتخزين والبيانات
نادراً ما تُفشل عيوب الموارد اختباراً وظيفياً. إنها تظهر لاحقاً في شكل شكاوى من البطارية، وحوارات «التطبيق لا يستجيب»، وتمرير بطيء، وإنهاء النظام للتطبيق. قِس على أجهزة حقيقية بأدوات تحليل الأداء في المنصتين (محللات Android Studio وXcode Instruments)، وقارن كل إصدار بالإصدار السابق بدلاً من مقارنته برقم مطلق.
- البطارية: جلسة نموذجية مدتها 30 دقيقة على جهاز حقيقي، مقارنة بالإصدار السابق؛ تحديثات الموقع والمستشعرات وأقفال الإيقاظ تتوقف حين يغادر المستخدم الشاشة؛ والعمل في الخلفية يحترم وضع Doze ووضع الطاقة المنخفضة.
- المعالج والعرض: القوائم الطويلة تتمرر بسلاسة على أضعف جهاز مدعوم؛ ولا شيء يستمر في العمل في الخلفية بلا سبب.
- الذاكرة: كرر المسار الرئيسي عشرين مرة وتحقق من عودة الذاكرة إلى خط الأساس؛ وافتح صوراً كبيرة؛ واختبر على أجهزة بذاكرة قليلة.
- التخزين: على جهاز شبه ممتلئ تفشل الكتابة بلطف؛ وللذاكرة المؤقتة حد وتُمسح؛ وحجم التطبيق بعد أسبوع من الاستخدام معقول.
- البيانات: البيانات الخلوية التي تستهلكها جلسة نموذجية؛ والصور بحجم مناسب للشاشة؛ والتنزيلات الكبيرة على الشبكة الخلوية بموافقة المستخدم فقط.
- بدء التشغيل: زمن البدء البارد والدافئ على أضعف جهاز؛ والحرارة أثناء الجلسات الطويلة للكاميرا أو الفيديو أو الخرائط.
# Android — quick measurements
adb shell dumpsys meminfo com.example.shop
adb shell dumpsys gfxinfo com.example.shop # frame rendering stats
adb shell dumpsys batterystats --reset
# ...run the session on battery...
adb shell dumpsys batterystats com.example.shopالإشعارات الفورية
يعبر الإشعار الفوري (Push notification) عدة أنظمة: يسجّل التطبيق لدى خدمة المنصة (Firebase Cloud Messaging على Android وAPNs على iOS)، ويتلقى رمز جهاز (Device token)، ويرسله إلى واجهتك الخلفية، ثم ترسل الواجهة الخلفية الرسائل عبر خدمة المنصة. والفشل في أي نقطة يبدو للمستخدم متشابهاً — لا يصل شيء، أو تُفتح الشاشة الخطأ — فاختبر السلسلة وحالات التطبيق كلاً على حدة.
- رفض إذن الإشعارات: يظل التطبيق يعمل ويعرض بدائل داخله؛ وتُحترم إعدادات الإشعارات الخاصة بالتطبيق.
- الوصول والتطبيق في المقدمة (شريط داخل التطبيق أو تحديث صامت، حسب التصميم)، أو في الخلفية، أو بعد إنهائه.
- النقر يفتح الشاشة الصحيحة بالسجل الصحيح — وكذلك حين يكون المستخدم قد سجّل الخروج، فتُفتح الوجهة بعد تسجيل الدخول.
- سجّل الخروج ثم ادخل بمستخدم آخر: لا تعود إشعارات المستخدم الأول تصل (أُلغي تسجيل الرمز أو أُعيد إسناده).
- إعادة التثبيت أو الاستعادة: تتلقى الواجهة الخلفية الرمز الجديد وتتوقف عن استخدام القديم.
- المحتوى: نص مترجم، وعربية من اليمين إلى اليسار، ونص طويل، ورموز تعبيرية وصور؛ ولا بيانات حساسة ظاهرة على شاشة القفل.
- تُمسح الشارات (Badges)، وتُجمّع الإشعارات، ولقنوات إشعارات Android الأهمية المقصودة.
- تصل الإشعارات المجدولة في الوقت المحلي الصحيح عبر المناطق الزمنية.
# iOS Simulator — deliver a test notification without a server
xcrun simctl push booted com.example.shop order-shipped.apns
# order-shipped.apns
{
"Simulator Target Bundle": "com.example.shop",
"aps": { "alert": { "title": "تم شحن طلبك", "body": "Order A-1042 is on its way" }, "badge": 1 },
"orderId": "A-1042"
}أمثلة على العيوب وما يوضع في تقرير خطأ الجوال
يحتاج تقرير الخطأ على الجوال إلى معلومات بيئة أكثر من تقرير الويب: طراز الجهاز، وإصدار النظام، وإصدار التطبيق ورقم البناء، ونوع الشبكة، والاتجاه، واللغة، وحجم الخط، وحالة الأذونات، وكيف وصل التطبيق إلى تلك الحالة (تثبيت جديد أم تحديث من أي إصدار). أرفق تسجيلاً للشاشة وسجل الجهاز — logcat على Android ووحدة تحكم الجهاز على iOS. ويغطي دليل تقرير الخطأ بقية الصيغة. العناوين أدناه أمثلة توضيحية للعيوب التي يكشفها هذا الكتالوج.
[Android, Pixel] Checkout crashes on resume after process death on the payment step
[iOS] Draft message lost when a phone call arrives while typing
Offline queue sends "Add to cart" twice after switching from Wi-Fi to 4G
Update 4.1 → 4.2: saved addresses missing (local database migration skipped)
"Order shipped" notification opens Home instead of order A-1042 when the app was killed
Location permanently denied: map screen shows an endless spinner and no link to Settings
Font size 200%: "Confirm" button off-screen on the OTP screen and not scrollable
Captive-portal Wi-Fi: app shows "Unexpected token <" instead of a network messageالأسئلة الشائعة
ما أهم سيناريوهات اختبار الجوال؟
إلى جانب الميزات نفسها: التحديث مع ترحيل البيانات، ورفض الأذونات وسحبها، والمقاطعات وموت العملية، وفقدان الشبكة وانتقالاتها، والمزامنة دون اتصال، والنص الكبير والتدوير، والإشعارات الفورية والتطبيق في المقدمة أو في الخلفية أو بعد إنهائه.
كيف أختبر تحديث التطبيق؟
ثبّت بناءً قديماً مدعوماً، وأنشئ بيانات واقعية (جلسة ومسودات وإعدادات وطابور إجراءات دون اتصال)، ثم ثبّت البناء الجديد فوقه وتحقق من بقاء كل شيء ومن بقاء المستخدم مسجّل الدخول. كرر ذلك من أقدم إصدار ما زلت تدعمه.
كيف أحاكي شبكة ضعيفة؟
اخنق سرعة محاكي Android وزمن استجابته، واستخدم Network Link Conditioner على iOS، وبدّل Wi-Fi والبيانات الخلوية أثناء الطلبات، ووجّه التطبيق إلى نقطة نهاية تستجيب ببطء أو برموز خطأ.
كيف أختبر ما يحدث حين يُنهي النظام التطبيق؟
أرسل التطبيق إلى الخلفية في منتصف مهمة، وأنهِ عمليته (adb shell am kill على Android؛ أما خيار «عدم الاحتفاظ بالأنشطة» فهو فحص أخف يدمّر كل شاشة لكنه لا يُنهي العملية)، ثم أعد فتحه من التطبيقات الأخيرة. يجب أن تُستعاد الشاشة وما أدخله المستخدم.
ماذا أفحص في الإشعارات الفورية؟
الوصول في كل حالة للتطبيق، والشاشة التي تُفتح عند النقر، والسلوك عند رفض الإشعارات، وتغيّر الرمز بعد تسجيل الخروج وإعادة التثبيت، والمحتوى المترجم ومن اليمين إلى اليسار، وعدم ظهور بيانات حساسة على شاشة القفل.
كيف أختبر أذونات وقت التشغيل؟
لكل إذن اختبر المنح، والرفض، والرفض الدائم، والمنح لمرة واحدة، والسحب من الإعدادات أثناء عمل التطبيق. يجب أن يستمر التطبيق في العمل أو يشرح بوضوح ما الذي لم يعد متاحاً وكيف يُفعَّل.
المراجع
- Certified Tester Mobile Application Testing (CT-MAT)منهج ISTQB التخصصي لاختبار تطبيقات الجوال: أنواع التطبيقات وتحديات الأجهزة والمنصات وأنواع الاختبار والأدوات.
- Core app quality guidelinesمعايير Google الأساسية لجودة تطبيقات Android — التجربة المرئية والوظائف والأداء والخصوصية والأمان — مع الاختبارات المستخدمة للتحقق منها.
- Test apps on Androidإرشادات Android الرسمية للاختبار: أنواع الاختبارات ونطاقاتها، والاختبارات المحلية مقابل المُجهَّزة على الجهاز، وأفضل الممارسات.
- XCTestإطار Apple لاختبارات الوحدة والأداء والواجهة لمشاريع Xcode على iOS وبقية منصات Apple.
- OWASP Mobile Application Security Verification Standard (MASVS)متطلبات OWASP الأمنية لتطبيقات الجوال، مجمّعة في مجالات ضبط مثل التخزين والتشفير والمصادقة والشبكة والتفاعل مع المنصة.
- Test your app's accessibilityكيف تُختبر إمكانية الوصول في تطبيق Android يدوياً باستخدام TalkBack وغيره، وآلياً بأدوات الاختبار في المنصة.
- Accessibility — Human Interface Guidelinesإرشادات Apple لتصميم إمكانية الوصول في iOS وغيره: VoiceOver والنص الديناميكي والتباين وأهداف اللمس والحركة.
تمرين عملي
صمّم سيناريوهات اختبار الجوال لإثبات التسليم
أنت المختبِر المسؤول عن تطبيق المندوبين لشركة توصيل (مثال خيالي) على Android وiOS. يضيف الإصدار 5.0 خدمة إثبات التسليم (Proof of delivery): عند الباب يصوّر المندوب الطرد، ويكتب العميل رمز التسليم، ثم يرفع التطبيق الاثنين، ولو لاحقاً إن لم تكن هناك تغطية. تعرض المادة أدناه ما أخبرك به مالك المنتج وقائد فريق المندوبين والمطوّرون.
صمّم على الورق اختبارات الجوال الخاصة بمسار إثبات التسليم مستعيناً بكتالوج الدليل: كل سيناريو ظرف تستطيع فرضه مع ملاحظة تستطيع فحصها على الشاشة وفي البيانات. ويساعدك مولّد الاختبار المبني على المخاطر في تقييم مجالات الكتالوج حسب الاحتمالية والأثر. خصّص لذلك 25–30 دقيقة.
تطبيق المندوبين «واصل» (مثال خيالي) لـ Android وiOS، بواجهة عربية وإنجليزية
معرّف الحزمة: com.example.courier
الإصدار في المتاجر اليوم: 4.9. أقدم إصدار مدعوم: 4.6
(الإصدارات الأقدم تعرض طلب تحديث إجبارياً).
يضيف الإصدار 5.0 خدمة «إثبات التسليم» (POD).
مسار إثبات التسليم في شاشة توصيل طلب، مثل الطلب D-5531
1. ينقر المندوب «تم التسليم»، فيقرأ التطبيق موقع GPS (إذن الموقع).
2. يصوّر المندوب الطرد عند الباب بالكاميرا الجديدة داخل التطبيق
(إذن الكاميرا).
3. يكتب العميل على هاتف المندوب رمز التسليم المكوّن من 4 أرقام
الذي وصله في رسالة SMS.
4. ينقر المندوب «تأكيد التسليم»: يرسل التطبيق الصورة والرمز والموقع
عبر POST /api/orders/D-5531/pod، ويصبح الطلب «تم التسليم».
القواعد
القاعدة R1: دون شبكة يُحفظ إثبات التسليم على الهاتف ويُرفع لاحقاً، الأقدم
أولاً. ولا يسجّل الخادم الطلب نفسه مُسلَّماً مرتين أبداً.
القاعدة R2: إن لم يتوفر الموقع يستطيع المندوب التأكيد مع ذلك، ويُعلَّم
الإثبات «بلا موقع» لمنسّق التوزيع.
القاعدة R3: تدوم جلسة المندوب 12 ساعة، ثم يجب أن يسجّل الدخول من جديد.
القاعدة R4: عندما يعيد منسّق التوزيع إسناد طلب، يتلقى المندوب الإشعار
الفوري «أُعيد إسناد الطلب D-5531»، والنقر عليه يفتح قائمة الطلبات.
ما الذي يتغيّر في الإصدار 5.0
- طابور العمل دون اتصال: يحفظ الإصدار 4.x التأكيدات (الحالة فقط) في الجدول
المحلي pending_uploads، وعند أول تشغيل ينقلها الإصدار 5.0 إلى جدول جديد
اسمه pod_queue (الحالة والصورة والرمز والموقع).
- الكاميرا: شاشة كاميرا داخل التطبيق بدلاً من فتح تطبيق الكاميرا في النظام.
من قائد فريق المندوبين
يستخدم المندوبون هواتفهم الشخصية، ويعملون نوبات تصل إلى 12 ساعة، وكثيراً ما
يسلّمون في الأقبية وردهات المصاعد بلا تغطية، ويثبّتون التحديثات أثناء النوبة.
من المطوّرين
«المسار كله ينجح على شبكة Wi-Fi المكتب مع تثبيت جديد للإصدار 5.0».
الأجهزة: هواتف Android وiOS من الفئة الأولى (Tier 1)، ومحاكي Android ومحاكي iOS.- اختر حسب المخاطر: اذكر أيّ علامات الاختيار في الدليل تنطبق على مسار إثبات التسليم (مدخلات غير محفوظة، والشبكة، والأذونات أو مغادرة التطبيق، والبيانات المحلية)، ثم رتّب مجالات الكتالوج وسمِّ المجالات الثلاثة التي تختبرها أولاً مع سبب لكل منها.
- اكتب عشرة سيناريوهات، كلٌّ منها في سطر واحد، بصيغة ظرف مع ملاحظة. غطِّ خمسة مجالات على الأقل من الكتالوج، واربط كل سيناريو بقاعدة (R1–R4) أو بتغيير في الإصدار 5.0 حيث ينطبق ذلك.
- اكتب اثنين منها كاملين بصيغة الكتالوج (
IDوAreaوScreenوSetupوTriggerوObserveوDevices): التحديث من 4.x مع تأكيدات لم تُرفع بعد، وموت العملية في شاشة إثبات التسليم. واذكر الأوامر التي تفرض كل ظرف على محاكي Android. - اكتب الأسئلة التي تتركها المادة مفتوحة، موجّهةً إلى مالك المنتج.
- فشل سيناريو موت العملية. اكتب عنوان تقرير الخطأ وتفاصيل البيئة التي يحتاج إليها، معبّأةً بقدر ما تسمح به المادة.
إظهار الإجابة النموذجية
الاختيار حسب المخاطر. في مسار إثبات التسليم كل العلامات التي يستخدمها الدليل لاختيار السيناريوهات: مدخلات غير محفوظة (الصورة والرمز المكتوب موجودان على الهاتف وحده حتى النقر على «تأكيد التسليم»)، وميزة تحتاج إلى الشبكة (الرفع)، وأذونات (الموقع والكاميرا)، وبيانات مخزّنة محلياً (طابور العمل دون اتصال، الذي ينتقل إلى جدول جديد في الإصدار 5.0). ولا يصغر إلا خطر مغادرة التطبيق، لأن الكاميرا داخل التطبيق تحل محل الذهاب إلى تطبيق الكاميرا في النظام والعودة منه؛ وفي المقابل يجب أن تصمد شاشة الكاميرا الجديدة أمام التدوير والمقاطعات ورفض الإذن. اختبر أولاً الشبكة والعمل دون اتصال والمزامنة، لأن القاعدة R1 هي الوعد الذي تقوم عليه الميزة، والمندوبون يسلّمون بلا تغطية كل يوم؛ والمخاطر هنا إثبات يُرسل مرتين، أو بترتيب خاطئ، أو يعلق حين تنتهي الجلسة قبل الرفع. وثانياً التحديث من 4.x، لأن الطابور يُرحَّل عند أول تشغيل والمندوبين يحدّثون أثناء النوبة، فستحمل الهواتف الحقيقية تأكيدات لم تُرفع لحظة التحديث. وثالثاً المقاطعات وموت العملية (Process death) في شاشة إثبات التسليم، لأن المكالمات والتنقل بين التطبيقات أمر عادي عند الباب، وضياع الصورة والرمز يعني إعادة الخطوات والعميل ينتظر. ثم تأتي أذونات وقت التشغيل (R2 والكاميرا)، والإشعارات الفورية (R4)، والشاشات والإدخال (حقل الرمز، والعربية، والتدوير، والنص الكبير). أما البطارية والبيانات والتخزين فتبقى فحوصاً للإصدار، مثل نوبة كاملة مع رفع الصور عبر الشبكة الخلوية وهاتف شبه ممتلئ، لا أولوية أولى. ولاحظ أن فحص المطوّرين، أي تثبيت جديد على شبكة Wi-Fi المكتب، لا يمرّ بأيٍّ من المجالات الثلاثة الأولى.
السيناريوهات العشرة، الجزء الأول. POD-01 (الشبكة، R1): انقر «تأكيد التسليم» واقطع الاتصال خلال ثانية واحدة. المتوقع: حالة واضحة «بانتظار الرفع» دون مؤشر تحميل لا ينتهي؛ وبعد عودة الاتصال يوجد إثبات تسليم واحد بالضبط للطلب D-5531، ويصبح الطلب «تم التسليم» مرة واحدة (في قائمة الطلبات وفي API). POD-02 (المزامنة، R1): أكّد ثلاثة طلبات في وضع الطيران ثم أعد الاتصال. المتوقع: تُرفع بدءاً بالأقدم، كلٌّ منها مرة واحدة بالضبط، مع الصورة والرمز سليمين، وينخفض عدد الطلبات المنتظرة الذي يراه المندوب إلى صفر. POD-03 (المزامنة والجلسة، R1 وR3): أكّد تسليماً دون اتصال ودع الجلسة تنتهي قبل عودة الاتصال، واطلب بيئة اختبار بجلسة قصيرة بدلاً من انتظار 12 ساعة. المتوقع: يُطلب من المندوب تسجيل الدخول، ويبقى الإثبات المؤجل محفوظاً، فلا يُحذف حين يرفض الخادم الجلسة المنتهية، ثم يُرفع بعد تسجيل الدخول. POD-04 (التحديث، تغيير في الإصدار 5.0): ضع تأكيدين في الطابور دون اتصال في الإصدار 4.9، ثم حدّث إلى 5.0. المتوقع: يبقى المندوب مسجّل الدخول، وينتقل التأكيدان إلى pod_queue ويُرفع كلٌّ منهما مرة واحدة بالضبط؛ وكرر ذلك من 4.6. POD-05 (دورة الحياة، موت العملية): التقط الصورة، واكتب رقمين، وأرسل التطبيق إلى الخلفية، وأنهِ عمليته، وأعد فتحه من التطبيقات الأخيرة. المتوقع: تعود شاشة إثبات التسليم للطلب D-5531 مع الصورة والرقمين.
السيناريوهات العشرة، الجزء الثاني. POD-06 (المقاطعة): مكالمة واردة، مع الرد والرفض، بينما يكتب العميل الرمز؛ وكذلك قفل الشاشة وفتحها. المتوقع: العودة إلى شاشة إثبات التسليم والمدخلات سليمة، ولا يُرسل شيء من تلقاء نفسه. POD-07 (الأذونات، R2): ارفض إذن الموقع، ثم ارفضه مرة أخرى حتى يتوقف النظام عن السؤال (وفي iOS يكفي الرفض الأول لذلك). المتوقع: يظل التأكيد ممكناً، ويُعلَّم الإثبات «بلا موقع»، ولا يتكرر طلب الإذن في حلقة، ويشرح التطبيق كيف يُسمح بالموقع من الإعدادات. POD-08 (الأذونات، الكاميرا داخل التطبيق): ارفض إذن الكاميرا عند أول استخدام؛ وفي محاولة منفصلة امنحه ثم اسحبه من الإعدادات والتطبيق ينتظر في الخلفية على شاشة إثبات التسليم. المتوقع: عند الرفض يشرح التطبيق ما الذي لم يعد متاحاً وكيف يُسمح بالكاميرا من الإعدادات، دون تكرار الطلب في حلقة، ويتبع التأكيد إجابة مالك المنتج عن التسليم دون صورة؛ وبعد السحب، الذي يُنهي عملية التطبيق في Android، يُعاد تشغيل التطبيق بسلاسة على شاشة منطقية، كالطلب D-5531، دون انهيار. POD-09 (الإشعارات الفورية، R4): إشعار إعادة الإسناد والتطبيق في المقدمة، وفي الخلفية، وبعد إنهائه، ومرة بعد انتهاء الجلسة. المتوقع: النقر يفتح قائمة الطلبات، بعد تسجيل الدخول عند الحاجة؛ ولم يعد الطلب D-5531 فيها، ولا يمكن تأكيد تسليمه. POD-10 (الشاشات والإدخال): حقل الرمز، والواجهة العربية مع الأرقام العربية الهندية (٠١٢٣)، وتدوير شاشتي الكاميرا وإثبات التسليم، وأكبر حجم خط. المتوقع: لوحة مفاتيح رقمية؛ وتُقبل الأرقام أو تُرفض برسالة واضحة، حسب القرار؛ وتبقى الصورة والأرقام بعد التدوير؛ ويظل زر «تأكيد التسليم» ظاهراً أو يمكن الوصول إليه بالتمرير. ومما يصلح أيضاً: نقر مزدوج سريع على «تأكيد التسليم» (إثبات واحد)، وشبكة بطيئة مع صورة كبيرة (مؤشر تقدّم، ومهلة معقولة، ولا تكرار)، وهاتف شبه ممتلئ لحظة حفظ الصورة، وشبكة Wi-Fi ببوابة مقيدة (Captive portal) في ردهة مبنى، والرفع في وضع Doze أو وضع الطاقة المنخفضة، والإصدار 4.5 يعرض طلب التحديث الإجباري.
السيناريو الكامل الأول (POD-04 مكتوباً كاملاً). المعرّف: POD-UPD-01. المجال: التثبيت والتحديث، ترحيل طابور العمل دون اتصال. الشاشة: «بانتظار الرفع» في قائمة الطلبات. الإعداد: محاكي Android عليه الإصدار 4.9 (adb install courier-4.9.0.apk)، والمندوب مسجّل الدخول، والشبكة مقطوعة (adb shell svc wifi disable وadb shell svc data disable)، والطلبان D-5531 ثم D-5532 معلَّمان «تم التسليم»، فينتظر كلاهما في pending_uploads. المُحفِّز: التحديث بالأمر adb install -r courier-5.0.0.apk الذي يُبقي بيانات التطبيق، ثم تشغيل الإصدار 5.0 وفحص الطابور، ثم إعادة الشبكة (adb shell svc wifi enable وadb shell svc data enable). الملاحظة: المندوب ما زال مسجّل الدخول؛ والتأكيدان ظاهران بانتظار الرفع بعد التحديث؛ وبعد عودة الاتصال يُرسل كلٌّ منهما مرة واحدة بالضبط، D-5531 أولاً، ويصبح الطلبان «تم التسليم» (في قائمة الطلبات وفي API)؛ وبعد إعادة تشغيل التطبيق لا يُرسل شيء من جديد، أي أن محتوى الجدول القديم لا يُرسل مرة ثانية. الأجهزة: محاكي Android وهاتف Android من الفئة الأولى، ثم هاتف iPhone من الفئة الأولى ببناء 4.9 المحفوظ ووضع الطيران. وكرر السيناريو من 4.6 على محاكٍ نظيف: ألغِ التثبيت أولاً، لأن الإصدار 4.6 لا يُثبَّت ببساطة فوق 4.9.
السيناريو الكامل الثاني (POD-05 مكتوباً كاملاً). المعرّف: POD-LIFE-01. المجال: المقاطعات، موت العملية. الشاشة: إثبات التسليم للطلب D-5531. الإعداد: المندوب مسجّل الدخول، والشبكة متصلة، وإذنا الموقع والكاميرا ممنوحان، والصورة ملتقطة، وكتب العميل رقمين من الرمز. المُحفِّز: اضغط زر الشاشة الرئيسية، وأنهِ العملية بالأمر adb shell am kill com.example.courier، ثم أعد فتح التطبيق من التطبيقات الأخيرة. الملاحظة: تُفتح شاشة إثبات التسليم للطلب D-5531، لا الشاشة الرئيسية ولا طلب آخر؛ وتُستعاد الصورة والرقمان؛ ولم يُرفع شيء؛ ولا انهيار. الأجهزة: محاكي Android وهاتف Android من الفئة الأولى؛ والأمر خاص بنظام Android، فاتفق مع مطوّري iOS على طريقة فرض الظرف نفسه على iPhone. وفي نموذج دورة الحياة في الدليل يغطي هذا السيناريو المسار من المقدمة إلى الخلفية ثم الإنهاء ثم العودة إلى المقدمة، وهو مسار لم يمرّ به فحص المطوّرين. وخيار المطوّرين «عدم الاحتفاظ بالأنشطة» فحص أول أرخص للاستعادة نفسها، لكن إنهاء العملية وحده يختبر موت العملية. وبمصطلحات ISTQB، يسمّي كل سيناريو من السيناريوهات ذات السطر الواحد شرط اختبار (Test condition)، وكتابته كاملاً تحوّله إلى حالة اختبار (Test case): الإعداد يحمل الشروط المسبقة، والمُحفِّز الخطوات، والملاحظة النتائج المتوقعة.
أسئلة مفتوحة لمالك المنتج. رفض إذن الكاميرا: هل يستطيع المندوب التأكيد دون صورة، كما تسمح القاعدة R2 بالتأكيد دون موقع، أم يُمنع التسليم، وماذا يرى منسّق التوزيع؟ الموقع التقريبي (عند إيقاف الموقع الدقيق): هل يُعدّ موقعاً أم «بلا موقع»؟ التأكيدات المرحَّلة من 4.x بلا صورة ولا رمز: هل يقبلها الخادم، وهل تُميَّز لمنسّق التوزيع؟ أين يُفحص الرمز؟ إن كان الخادم هو الذي يفحصه، فلا يمكن فحص إثبات مؤجل عند الباب: فماذا يحدث حين يصل إثبات مؤجل برمز خاطئ، وكم محاولة مسموحة؟ إعادة الإسناد أثناء العمل دون اتصال: إن أكّد المندوب طلباً دون اتصال وأعاد منسّق التوزيع إسناده قبل الرفع، فأيهما يُعتمد، وماذا يرى كلٌّ منهما؟ أي وقت يسجّله الإثبات، وقت التأكيد على الهاتف أم وقت الرفع، وماذا لو تغيّرت ساعة الهاتف أو منطقته الزمنية أثناء انعدام الاتصال؟ هل تُقبل الأرقام العربية الهندية في حقل الرمز؟
تقرير الخطأ عند فشل POD-LIFE-01. العنوان: «[Android] شاشة إثبات التسليم تُفتح فارغة بعد موت العملية: ضياع الصورة والرمز المكتوب (الطلب D-5531)». البيئة: طراز الجهاز وإصدار النظام؛ وإصدار التطبيق ورقم البناء (5.0 ورقم بنائه)؛ وكيف وصل التطبيق إلى تلك الحالة (تثبيت جديد للإصدار 5.0 أم تحديث من 4.9، وهذا مهم هنا لأن التحديث يرحّل بيانات محلية)؛ ونوع الشبكة؛ والاتجاه؛ ولغة الواجهة؛ وحجم الخط؛ وحالة الأذونات (الموقع والكاميرا ممنوحان)؛ وحساب المندوب الاختباري والطلب. وفي الخطوات اذكر الأمر بالضبط، وأن التطبيق أُعيد فتحه من التطبيقات الأخيرة. وأرفق تسجيلاً للشاشة ومخرجات logcat من لحظة الإنهاء حتى إعادة الفتح.
راجع عملك. يجب أن يسمّي كل سيناريو ظرفاً تستطيع فرضه وملاحظة تستطيع فحصها على الشاشة وفي البيانات: «اختبر وضع عدم الاتصال» بلا ملاحظة، و«يجب أن يعمل إثبات التسليم» بلا ظرف. وقد يختلف ترتيبك إن جاءت أسبابك من المادة، لكن الخطة التي تخلو من سيناريو للشبكة وآخر للتحديث وثالث لموت العملية قد أغفلت أكبر ثلاثة مخاطر في هذا الإصدار. ولا تهم المعرّفات ولا الصياغة ولا ترتيب السيناريوهات العشرة؛ المهم تغطية مجالات الكتالوج، والربط بالقواعد R1–R4، والأسئلة المفتوحة.
تقدّمك في هذا الموضوع
سجّل الدخول لتتابع تقدّمك
علّم الموضوعات مكتملة، وتابع من حيث توقفت، وافتح امتحانات التخصص.
جزء من مسار تعلم ضمان الجودة
قبل هذا الموضوع
الموضوعات التالية
الأدوات المذكورة في هذا الدليل
عرّف الحالات والأحداث، ثم ولّد جدول الانتقالات واختبارات الانتقالات الصالحة/غير الصالحة وتغطية 0-switch/1-switch.
احصل على نقطة نهاية عامة تعيد أي رمز حالة HTTP، مع تأخير اختياري وجسم JSON مخصّص، لاختبار معالجة الأخطاء في العميل.
ولّد استجابات خطأ منظّمة (التحقق والمصادقة وعدم العثور وتحديد المعدّل وخطأ الخادم) بالصيغ الشائعة.
ولّد أسماء وعناوين وجملاً وأرقاماً عربية (بالأرقام العربية-الهندية) وحالات حدّية للكتابة من اليمين إلى اليسار لاختبار التوطين.
ولّد السجلات نفسها بلغات متعددة (الإنجليزية والعربية والهندية وغيرها) لاختبار التدويل (i18n) واختلاط RTL/LTR.
ولّد أرقام هواتف اختبارية بصيغة صحيحة للسعودية والأردن والإمارات والهند والولايات المتحدة والمملكة المتحدة وغيرها.
حلّل حجم الاستجابة: البايتات الخام مقابل المضغوطة، وحجم الترويسات، ووزن بنية JSON، وأكبر الحقول.
ولّد حالات اختبار منظّمة (المعرّف والعنوان والشروط المسبقة والخطوات والنتيجة المتوقّعة والأولوية) من وصف الميزة وقائمة الحقول.