بالنسبة لأولئك المهتمين بموضوع الأتمتة على نظام iOS ، لديّ خبران - جيد وسيئ. جيد: في تطبيق iOS للخدمات المدفوعة ، يتم استخدام نقطة تكامل واحدة فقط - عمليات الشراء داخل التطبيق (عمليات الشراء
المضمنة في التطبيق ). سئ: لا تقدم Apple أي أدوات لأتمتة عمليات الشراء المختبرة.
في هذا المقال ، أقترح أن تبحث أنا وأنت عن طريقة أتمتة عالمية تتجاوز الخير والشر لشركة أبل. ستكون هذه المقالة مفيدة لكل من يدمج خدمات الجهات الخارجية التي تمثل صندوقًا أسود في تطبيقاتهم: الإعلان ، الدفق ، إدارة الموقع ، وما إلى ذلك. عادة ، يصعب اختبار عمليات الدمج هذه ، نظرًا لعدم وجود طريقة لتكوين خدمة طرف ثالث بمرونة لاختبار التطبيق.
اسمي Victor Koronevich ، أنا مهندس أتمتة اختبار أول على Badoo. شارك في التشغيل الآلي للجوال لأكثر من عشر سنوات. جنبا إلى جنب مع زميلي فلاديمير سولودوف ، قدمنا هذا التقرير في مؤتمر Heisenbug. ساعدني أيضًا في إعداد هذا النص.في
المقالة السابقة
، وصفنا الأساليب التي تستخدمها Badoo لاختبار التكامل مع مزودي الدفع ، والتي لدينا أكثر من 70 منها. في هذه المقالة سوف نتحدث أكثر عن كيفية تمكننا من تحقيق أتمتة مستقرة وغير مكلفة لاختبار الخدمات المدفوعة في تطبيق iOS.
لنبدأ بوصف عام لبحثنا:
- تعريف المشكلة
- بيان المشكلة
- الحل رقم 1. أبل رمل
- القرار رقم 2. وظيفة طريقة وهمية واستخدام كائن وهمية
- تقييم القرار: المخاطر الرئيسية
- يؤدي
- استنتاج
تعريف المشكلة
الأتمتة يجب القيام به عند الحاجة الطبيعية. متى جاءت هذه اللحظة معنا؟
هناك الكثير من الميزات المجانية في تطبيق Badoo ، لكن الميزات المدفوعة تمنح المستخدم المزيد من الخيارات. يحصلون عليها بطريقتين: للحصول على قروض - العملة الداخلية في Badoo - أو عن طريق شراء اشتراك متميز. بالنسبة لعدد معين من الائتمانات ، يمكنك رفع ملفك الشخصي في نتائج البحث إلى المقام الأول ، وتقديم هدية لمستخدم آخر ، وأكثر من ذلك. يسري الاشتراك المتميز لفترة معينة من الوقت ويوفر العديد من الخيارات في وقت واحد: قم بتشغيل وضع الاختفاء ، وشاهد الأشخاص الذين أبدوا تعاطفًا معك ، وألغوا نتيجة تصويتك ، وغيرهم.
ظهرت هذه الميزات في Badoo تدريجيا. وقبل عامين ، اختبرنا الخدمات المدفوعة في تطبيقات iOS يدويًا فقط. ولكن مع ظهور الميزات والشاشات الجديدة ، استغرق الاختبار اليدوي المزيد من الوقت. تأتي متطلبات التغييرات في التطبيق من جوانب مختلفة: من مطوري جانب العميل ومطوري جانب الخادم وحتى مزود Apple نفسه. لاختبار واحد ، بدأ التكرار اختبار يستغرق حوالي ثماني ساعات. أصبح من المستحيل الحصول على ملاحظات سريعة للمطور على فرعهم في غضون 30 دقيقة ، مما قد يؤثر سلبًا على القدرة التنافسية للمنتج.
أردنا الحصول على نتائج الاختبار في أسرع وقت ممكن. وواجهوا مشكلة: كيفية تنظيم اختبار الانحدار للخدمات المدفوعة في تطبيقات iOS لدينا بطريقة غير مكلفة من أجل الحصول على نتائج سريعة ومستقرة؟
بيان المشكلة
لذلك ، مع الأخذ في الاعتبار تفاصيل عملية تسليم المنتج النهائي وحجم الفريق ، نريد:
- اختبار أي مشتريات داخل تطبيق العميل (المدفوعات لمرة واحدة والاشتراكات) ؛
- تكرار التكرار للاختبار 10-20 مرة في اليوم ؛
- الحصول على نتائج الاختبار - 150 نصوص اختبار في أقل من نصف ساعة ؛
- تخلص من الضوضاء
- تكون قادرة على إجراء الاختبارات على فرع معين من رمز المطور ، بغض النظر عن نتائج عمليات التشغيل الأخرى.
الآن وقد صممنا المهمة ، فقد حان الوقت لبدء الرحلة إلى عالم المهندسين الرائع وحلولهم.
الحل رقم 1. أبل رمل
بادئ ذي بدء ، بدأنا في البحث عن معلومات حول تنظيم الاختبار التلقائي للخدمات المدفوعة في وثائق Apple. ولم يجدوا أي شيء. دعم الأتمتة تبدو ضئيلة للغاية. إذا ظهر شيء ما ، فإن إعداد الأتمتة باستخدام الأدوات المقترحة أمر صعب (دعنا نتذكر على الأقل
UIAutomation ، وكذلك الوقت الذي
ظهرت فيه أول أداة
xcrun simctl لـ iOS Simulator) وعليك أن تبحث عن حلول هندسية ، بما في ذلك في الجزء المفتوح المصدر.
في وثائق Apple لاختبار الخدمات المدفوعة ، يمكنك العثور على
Apple Sandbox فقط. لم يكن من الواضح كيفية ربط صندوق الرمل بالأتمتة ، لكننا قررنا البحث بجدية عن هذا الحل. حقيقة أن صندوق الرمل Android كان مستقرًا أعطانا الثقة ، وبحلول ذلك الوقت كنا قد نجحنا بالفعل في إجراء اختبارات على Android. ربما سيكون الصندوق الرمل أبل جيدة كما؟
لكن عندما طبقنا اختبارات تلقائية باستخدام صندوق الرمال ، شربنا بالكامل. دعنا نذهب بسرعة على المشاكل الرئيسية.
1. مجموعة من مستخدمي الاختبار
أصبح القيد الرئيسي للأتمتة ميزات المحتوى في مجموعة مستخدمي الاختبار ، والتي ينبغي أن تضمن استقلالية إطلاق الاختبارات الذاتية.
لتشغيل عملية شراء واحدة فقط لعملية شراء اشتراك ، نحتاج إلى:
- خذ مستخدمًا جديدًا للحصول على إذن في صندوق الحماية ؛
- تغيير في محاكاة معرف Apple الحالي المرتبط ؛
- تسجيل الدخول إلى Badoo مع Badoo
- الوصول إلى شاشة شراء الاشتراك وتحديد المنتج ؛
- تأكيد الشراء وتسجيل الدخول عبر Apple ID ؛
- تأكد من نجاح عملية الشراء ؛
- إرسال مستخدم Badoo لتنظيف.
- مسح المستخدم من رمل من الاشتراكات.
إذا حاولت استخدام نفس المستخدم فورًا في الاختبار التالي ، فسيكون من المستحيل شراء اشتراك ثانٍ. تحتاج إلى الانتظار حتى يصبح الاشتراك الأول "سيئًا" ، أو إلغاء الاشتراك في الإعدادات. كما قلنا في
المقالة الأولى ، يحتوي الصندوق الرمل على فترة صلاحية اشتراك محددة. إذا قمت بشراء اشتراك "لمدة شهر" ، فعليك الانتظار خمس دقائق لإغلاقه تلقائيًا. كما أن عملية إلغاء الاشتراك نفسها ليست سريعة.
وفقًا لذلك ، لتشغيل جديد من نفس الاختبار ، سنحتاج إما إلى الانتظار حتى انتهاء الاشتراك ، أو استخدام مستخدم آخر "نظيف". إذا كنا نريد إجراء اختبارين بشكل مستقل في وقت واحد عن بعضنا البعض ، فعلينا أن يكون لدينا اثنان على الأقل من مستخدمي صندوق الحماية في المجموعة. وبالتالي ، لتشغيل 100 اختبار تلقائي بالتوازي مع 100 مؤشر ترابط ، نحتاج إلى 100 مستخدم مختلف.
والآن دعنا نتخيل أننا نقوم بإجراء اختبار ذاتي على عميلين ، يمكن لكل منهما تشغيلهما في 100 مؤشر ترابط. في هذه الحالة ، نحتاج إلى 200 مستخدم على الأقل!
2. الإخطارات "السيئة"
حسنا ، ماذا بحق الجحيم لا يمزح! قمنا بتنظيم مجموعة مستخدمين وبدأنا في مراقبة كيفية إجراء الاختبارات. لقد سقطوا على الطريق ، لكن الأغلبية - لأسباب جديدة غير معروفة لنا. بدأنا نفهم وأدركنا أنه عند التفويض والتأكيد على عملية الشراء والعمل كمستخدم في صندوق الحماية ، يرسل متجر التطبيقات تنبيهات: على سبيل المثال ، يسأل عن اسم مستخدم وكلمة مرور جديدين ، ويؤكد التفويض من خلال النقر على زر "موافق" ، ويقدم معلومات حول خطأ داخلي مع زر "موافق" . في بعض الأحيان تظهر ، في بعض الأحيان لا. وإذا ظهرت ، فابدأ دائمًا بترتيب مختلف.

كيف يمكن أن يتم ببساطة تجاهل خطأ مشبوه في الاختبار التلقائي؟ وإذا حدث خطأ حقيقي ، فماذا أفعل؟ أصبحت هذه المنطقة تلقائيًا "منطقة عمياء" بالنسبة لنا ، واضطررنا إلى كتابة معالجات خاصة لجميع التنبيهات المحتملة التي قد تصل من متجر التطبيقات.
كل هذا جعل الاختبارات أبطأ:
- يمكن أن تصل التنبيهات إلى خطوات مختلفة من سيناريو الاختبار ، مما يؤدي إلى تدمير الفكرة الرئيسية للاختبار - سيناريو الاختبار المتوقع ؛ كان علينا إضافة معالج أخطاء يتوقع ظهور سلسلة محتملة من التنبيهات المتجاهلة المعروفة ؛
- في بعض الأحيان وصلت أشكال جديدة من التنبيهات أو حدثت أخطاء أخرى ، لذلك كان علينا إعادة تشغيل الاختبارات الساقطة ؛ هذا زاد من وقت التشغيل لجميع الاختبارات.
3. كان هناك اختبار؟
لذلك ، يتم حظر المستخدمين في التجمع ، ثم مسح لمدة n دقيقة. نحن نجري اختبارات في 120 موضوعًا ، وهناك بالفعل عدد كبير جدًا من المستخدمين في المجموعة ، لكن هذا لا يكفي. لقد صنعنا نظام إدارة المستخدم الخاص بنا ، وأعدنا معالج تنبيه - ثم حدث ذلك. أصبح الصندوق الرمل غير متاح لبضعة أيام لأي مستخدم اختبار.
لا أحد يتوقع هذا. وكانت هذه هي القشة الأخيرة في كؤوس صبرنا ، والتي قتلت أخيراً حب صندوق رمل أبل وجعلتنا نبدأ في الطريق إلى ما بعد الخير والشر. لقد أدركنا أننا لم نكن بحاجة إلى مثل هذه الأتمتة وأننا لم نرغب في المعاناة بعد هذا القرار الخطير.
القرار رقم 2. وظيفة طريقة وهمية واستخدام كائن وهمية
لذلك ، شربنا مشاكل الأتمتة في رمل Apple. ولكن لا أعتقد أن كل شيء في عالم الأجهزة المحمولة سيء تمامًا. على نظام Android ، صندوق الرمل أكثر ثباتًا - يمكنك تشغيل الاختبارات التلقائية هناك.
دعنا نحاول إيجاد حل آخر لنظام iOS. ولكن كيف تبدو؟ أن ننظر فيها؟ دعونا نلقي نظرة على تاريخ الاختبار وتطوير البرمجيات: ماذا حدث لعالم أبل المجنون؟ ماذا يقول الأشخاص الذين كتبوا مجموعة من الكتب وحصلوا على السلطة في عالم الأتمتة وتطوير البرمجيات؟
تذكرت على الفور العمل "أنماط اختبار xUnit: إعادة اختبار كود الاختبار" ، الذي كتبه جيرارد ميساروش (راجع مارتن فاولر) ، - في رأيي ، أحد أفضل الكتب لأي اختبار يعرف لغة برمجة عالية المستوى واحدة على الأقل ويريد القيام بالأتمتة . يمكن أن يساعدنا فصلان من هذا الكتاب مخصصان لاختبار SUT بمعزل عن المكونات الأخرى للتطبيق ، وهما "الصندوق الأسود" لدينا.
1. مقدمة إلى المخاوي وهمية
تجدر الإشارة إلى أنه في عالم الاختبار التلقائي ، لا توجد حدود مقبولة بشكل عام بين مفاهيم اختبار الزوجي ، اختبار كعب الروتين ، اختبار تجسس ، كائن وهمية ، كائن وهمية ، كائن وهمية. يجب أن تفكر دائمًا في مصطلحات المؤلف. نحتاج إلى مفهومين فقط من العالم الكبير لاختبار الزوجي: وظيفة وهمية وكائن مزيف. ما هذا ولماذا نحتاج هذا؟ نقدم تعريفًا موجزًا لهذه المفاهيم حتى لا يكون لدينا خلافات.
لنفترض أن لدينا تطبيقًا ومكونًا مضمنًا فيه ، وهو بالنسبة لنا "الصندوق الأسود". داخل التطبيق ، يمكننا استدعاء الوظائف عن طريق الوصول إلى هذا المكون والحصول على نتائج هذه الوظائف. اعتمادًا على النتيجة ، يتفاعل تطبيقنا بطريقة محددة. في بعض الأحيان ، قد تكون نتيجة تنفيذ الوظيفة كيانًا كاملًا مع مجموعة من الحقول التي تعكس بيانات المستخدم الحقيقية.
استبدال دالة لأي وظيفة أخرى تُرجع النتيجة المرغوبة ، دعنا نسميها وهمية ، أو ببساطة نسخر منها. قد يكون لهذه الوظائف نفس التوقيع ، لكن هاتان الوظيفتان مختلفتان.
وسيتم استبدال استبدال الكيان الذي تم الحصول عليه نتيجة لوظيفة كيان مزيف (يحتوي على البيانات الضرورية في الحقول ، وأحيانًا حتى البيانات التالفة) بتنفيذ كائن مزيف. يمكنك قراءة المزيد حول هذا الموضوع في الكتاب الذي ذكرته أعلاه ، أو في أي مجموعة أخرى للاختبار وتطوير البرمجيات.
لإنهاء هذا الأمر ، دعنا نؤكد على بعض ميزات استخدام وظائف وهمية وكائنات وهمية:
- للحصول على وظائف مبللة ، تحتاج إلى الوصول إلى التعليمات البرمجية المصدر ومعرفة كيفية عمل التطبيق مع المكون من الداخل على مستوى المطور.
- من أجل تطبيق كائن مزيف ، تحتاج إلى معرفة بنية الكائن الحقيقي.
- باستخدام وظيفة وهمية يسمح التكوين المرن للتطبيق مع المكون.
- يتيح لك استخدام كائن مزيف منح أي كيان أي خصائص.
طريقة moki والكائن وهمية مثالية لعزل تشغيل مكون داخل التطبيق. دعونا نرى كيف يمكننا تطبيق هذه الطريقة لحل مشكلتنا ، حيث سيكون App Store هو المكون. نظرًا لخصائص استخدام هذه الطريقة ، نحتاج أولاً إلى الانتقال إلى دراسة طبيعة عمل التطبيق الخاص بنا مع المكون ، ثم إلى التنفيذ التقني لصنع نماذج معينة من الأشياء المزيفة والأشياء المزيفة.
2. كيف يحدث عملية شراء حقيقية
قبل أن نبدأ في وصف تفاعل جميع أجزاء النظام ، دعنا نبرز العناصر الفاعلة الرئيسية:
- مستخدم التطبيق - أي ممثل ينفذ إجراءات مع التطبيق ، يمكن أن يكون شخصًا ، أو يمكن أن يكون هناك برنامج نصي ينفذ التعليمات اللازمة ؛
- التطبيق (في حالتنا ، نستخدم تطبيق Badoo iOS المثبت في محاكي iOS) ؛
- server - ممثل يقوم بمعالجة الطلبات من التطبيق ويرسل الردود أو الإشعارات غير المتزامنة دون طلب العميل (في هذه الحالة ، نعني خادم Badoo مجرد واحد لتبسيط البنية) ؛
- يعد App Store جهة فاعلة تمثل "مربعًا أسودًا" بالنسبة لنا: لا نعرف كيف يتم ترتيبها في الداخل ، لكننا نعرف الواجهة العامة الخاصة بها لمعالجة عمليات الشراء داخل التطبيق ( إطار StoreKit ) ، كما أننا نعرف أيضًا كيفية التحقق من البيانات الموجودة على خادم Apple.
دعونا نرى كيف يحدث الشراء. يمكن رؤية العملية برمتها في الرسم البياني:
الشكل 1. مخطط الدفع في متجر التطبيقاتسنصف خطوة بخطوة الإجراءات الرئيسية للجهات الفاعلة.
1. نقطة البداية هي حالة جميع الجهات الفاعلة قبل فتح الشاشة مع قائمة المنتجات.
ما هي هذه الشاشة وكيف حصلنا عليها؟
لنفترض أن المستخدم وجد شخصًا مثيرًا للاهتمام ، وفتح ملفه الشخصي ، وكتب رسالة واحدة وأراد إرسال هدية. إرسال هدية هي خدمة مدفوعة. يمكن للمستخدم تمرير ملف التعريف إلى القسم لإرسال الهدايا أو اختيار هدية على الفور من الدردشة.
إذا اختار المستخدم هدية وليس لديه أموال في الحساب ، فسوف يرى قائمة من حزم القروض المختلفة (معالج المدفوعات) للشراء. نقطة الانطلاق في مثالنا هي قائمة الهدايا. في الرسم البياني ، يمكننا النظر في مثل هذه النقطة في أي شاشة قبل عرض قائمة المنتجات لشراء القروض أو الاشتراك.
2. فتح قائمة المنتجات.
نحن في نقطة البداية ، على سبيل المثال ، في قائمة الهدايا. يختار المستخدم واحدة من الهدايا في التطبيق. يقدم التطبيق طلبًا على خادمنا للحصول على قائمة باقات قروض معرّف المنتج الممكنة (100 ، 550 ، 2000 ، 5000). يعيد الخادم هذه القائمة إلى التطبيق.
بعد ذلك ، يرسل التطبيق قائمة معرف المنتج المستلمة للتحقق منها إلى ممثل App Store (إطار نظام iOS لنظام StoreKit يذهب إلى خادم Apple). تقوم بإرجاع قائمة بالمنتجات التي أثبتت جدواها - ونتيجة لذلك ، يعرض التطبيق للمستخدم القائمة النهائية لحزم القروض مع الرموز والأسعار.
3. اختيار المنتج وتوليد استلام.
يختار المستخدم المنتج المدفوع. يتطلب متجر التطبيقات إثبات الشراء والترخيص عبر Apple ID. بعد ترخيص المستخدم الناجح ، يتم نقل التحكم إلى التطبيق. التطبيق ينتظر استلام إيصال داخل الحزمة الخاصة به. يرى المستخدم في هذا الوقت الشمس التي تغلق الشاشة. يمكن فهم هذا الإيصال باستخدام طريقة appStoreReceiptURL لفئة
Bundle . بعد إنشاء الشيك بواسطة App Store ، يقوم التطبيق بتحديد الشيك من الحزمة الخاصة به ويرسل طلبًا مع الشيك وبيانات المستخدم إلى خادم Badoo.
4. التحقق من الاختيار على خادم Badoo.
بمجرد أن يتلقى خادم Badoo الشيك وبيانات المستخدم ، فإنه يرسلهم مرة أخرى إلى جانب خادم Apple لتنفيذ دورة التحقق الأولى. هذه هي واحدة من توصيات أبل. بعد ذلك ، في دورة التحقق الأولى هذه ، يتلقى الخادم معلومات حول الحالة الحالية للاشتراك.
5. إرسال إشعارات الدفع (إشعار الدفع) من الخادم.
يعالج خادم Badoo المعلومات المستلمة مرة أخرى بعد التحقق من Apple ، ويرسل التطبيق استجابة مع إشعار الدفع.
6. دفع الإخطار في التطبيق.
إذا كانت عملية شراء قروض ، فسيتم على الفور تغيير رصيد المستخدم في التطبيق وسيظهر الهدية المرسلة في الدردشة. إذا كان هذا شراء اشتراك ، فيجب على المستخدم انتظار إشعار الدفع النهائي الذي تم تنشيط الاشتراك.
3. تحديد التبعيات واختبار حلقة
لمزيد من المناقشة ، نقدم مفهومين آخرين - الاعتماد الخارجي ودائرة الاختبار.
التبعية الخارجية
نعني بالتبعية الخارجية أي تفاعل مع مكون ، وهو بالنسبة لنا "الصندوق الأسود". في هذه الحالة ، يعمل App Store كمكون في شكل إطار نظام iOS (StoreKit) ، يعمل به تطبيق iOS وخادم Apple ، حيث تذهب طلبات التحقق.
من المستحيل إدارة هذه التبعيات في ظروف حقيقية ، حيث يُجبر التطبيق على الاستجابة لإشارات الخرج من الصندوق الأسود (انظر الشكل 2).
لدينا ثلاث تبعيات خارجية:
- فحص StoreKit المنتجات.
- تلقي واستبدال إيصال الشراء.
- التحقق من الاختيار على خادم Badoo.
الشكل 2. التبعيات الخارجيةدائرة الاختبار
دائرة الاختبار - هذه هي أجزاء من المسار الذي سنستعرضه ونتحقق منه أثناء عملية الاختبار.
الشكل 3. اختبار حلقةالهدف من عملنا على التخلص من التبعيات هو بناء دائرة اختبار أقرب ما يمكن من المسار الحقيقي وتتيح لك استبعاد جميع التبعيات الخارجية والتحكم في النقل إلى جانبك.
نحن نعتبر كل تبعية بالتسلسل.
4. عزل التبعيات: التنفيذ التقني
في شركتنا ، لتنفيذ المدفوعات ، تم اتخاذ مفهوم PPP ، والذي يعتمد على واجهة مزود الدفع. هذه هي الواجهة الرئيسية للتفاعل مع ممثل متجر التطبيقات (StoreKit) داخل تطبيقنا ، والذي له طريقتان رئيسيتان:
- تعد هي الطريقة المسؤولة عن فحص المنتجات ؛
- makePayment هي طريقة تعالج عملية شراء داخل التطبيق.
تم إعادة هيكلة جميع المدفوعات على نظام iOS وفقًا لهذا المفهوم ، والذي سمح لنا بالحصول على مزود دفع مزيف بسيط ومناسب من الدرجة. هذه هي الواجهة الرئيسية للتفاعل مع نسخة مناسبة من سلوك StoreKit داخل تطبيقنا. ماذا تعني عبارة "نسخة مناسبة"؟ يحتوي هذا الموفر على تسخر من أساليب التحضير و makePayment التي تفعل ما نريد. دعونا نلقي نظرة على مثال على الكود ، كيف تمكنا من دمج moki.
الاعتماد رقم 1. فحص StoreKit المنتجات
للتحقق من قائمة المنتجات ، استخدم وظيفة التحضير ، التي تُرجع قائمة المنتجات المحددة. يمكننا استخدام النموذج الذي نوقف فيه الشيك ونعيد قائمة المنتجات الواردة كما تم التحقق منها بالكامل. وبالتالي ، سيتم القضاء على التبعية.
الشكل 4. أول مخطط القضاء التبعيةفي الجزء العلوي من الهندسة المعمارية في طلبنا هو مزود الدفع. وهو يعكس واجهة مزود ممكن في التطبيق. يمكن العثور على رمز تطبيق mok في فئة موفر الدفع المزيف.
public class MockPaymentProvider: PaymentProvider { public static var receipt: String? public static var storeKitTransactionID: String? public func prepare(products: [BMProduct]) -> [BMProduct] { return products } ... }
قائمة 1. وهمية العميل الاختيارفي موفر الدفع المزيف ، يمكننا أن نرى تنفيذ طريقة الإعداد. اتضح أن سحر moka بسيط للغاية: لقد تخطت الطريقة فحص المنتجات على جانب StoreKit ، وأنها ببساطة تعرض قائمة واردة من المنتجات. التنفيذ الفعلي لإعداد يشبه هذا:
public func prepare(products: [BMProduct]) -> [BMProduct] { let validatedProducts = self.productsSource.validate(products: products) return validatedProducts }
قائمة 2. الحقيقي موفر الدفع المتجرالاعتماد رقم 2. تلقي واستبدال إيصال الشراء
التبعية الثانية أكثر تعقيدًا: نحتاج إلى إزالة التفويض أولاً حتى لا نحافظ على مجموعة حسابات المستخدمين ، ثم نحقق بطريقة ما من تلقاء نفسها. يمكننا ببساطة حذف نموذج التفويض:
الشكل 5. إزالة نموذج التفويض عند إجراء الدفعانها ليست بهذه البساطة مع الاختيار. هناك العديد من الأسئلة:
- كيفية الحصول على إيصال للمنتج المناسب مقدما؟
- إذا تلقينا الشيك ، فمتى وكيف نعلقه داخل التطبيق؟
هنا الممثل "المستخدم" لديه دور جديد - ضمان الجودة. عندما نقوم بإجراء الاختبار ، لا يمكننا فقط النقر على الأزرار الموجودة على الواجهة ، ولكن أيضًا استدعاء أساليب API الخاصة بإطار الاختبار (الأساليب التي تحاكي إجراءات المستخدم) وخدمات REST API (الطرق التي يمكنها القيام بالسحر من خدمة Badoo الداخلية). نحن في Badoo نستخدم أداة QA API قوية جدًا (يمكنك العثور على جميع إمكاناتها على الرابط:
https://vimeo.com/116931200 ). هو الذي يساعدنا في الاختبار ويعطي فحصًا للمنتج المناسب من جانب خادم Badoo. خادم Badoo هو أفضل مكان لإنشاء الشيكات: يوجد تشفير وفك تشفير ، لذلك يعرف الخادم كل شيء عن بنية البيانات هذه.
بعد تلقينا شيكًا مزيفًا ، يمكننا وضعه عبر باب
خلفي على جانب التطبيق. بعد ذلك ، سيرسل التطبيق شيكًا مزيفًا مع بيانات المستخدم إلى خادمنا.
الشكل 6. مخطط للاستلامكيف أصبح هذا ممكنًا تقنيًا؟
1. لإعداد فحص وهمية في التطبيق ، تمكنا من استخدام الباب الخلفي الذي حفظ الاختيار وهمية في حقل استلام MockPaymentProvider:
#if BUILD_FOR_AUTOMATION @objc extension BadooAppDelegate { @objc func setMockPurchaseReceipt(_ receipt: String?) { PaymentProvidersFactory.useMockPaymentProviderForITunesPayments = true MockPaymentProvider.receipt = receipt } ... } #endif
قائمة 3. وهمية تحقق مستتر2. كان التطبيق قادراً على اتخاذ الاختيار لدينا بفضل MockPaymentProvider ، حيث استخدمنا makePayment وهمية والشيك المحفوظ في MockPaymentProvider.receipt:
public class MockPaymentProvider: PaymentProvider { ... public func makePayment(_ transaction: BPDPaymentTransactionContext) { ... if let receiptData = MockPaymentProvider.receipt?.data(using: .utf8) { let request = BPDPurchaseReceiptRequest(...) self.networkService.send(request, completion: { [weak self] (_) in guard let sSelf = self else { return } if let receipt = request.responsePayload() { sSelf.delegate?.paymentProvider(sSelf, didReceiveReceipt: receipt) } }) } else { self.delegate?.paymentProvider(self, didFailTransaction: transaction) } } }
القائمة 4. استدعاء موكا معالجة الشراء مع تحقق وهمية3. الحصول على فحص وهمية
للحصول على فحص مزيف ، استخدمنا الطريقة على الخادم (انظر القائمة 5). يتطلب الأمر صفيفًا افتراضيًا يحتوي على بيانات لإنشاء بيانات التحقق ويضيف البيانات اللازمة لمنتج معين إليها.
$new_receipt_model = array_replace_recursive(
سرد 5. خادم جزء من جيل الاختيارلتكرار بنية التحقق الحقيقي ، يجب تشفير الاختيار المخصص المرسلة من قبل التطبيق باستخدام شهادة. نستخدم شهادة العمل الخاصة بنا بدلاً من شهادة Apple.
function signReceipt($receipt, $response) {
سرد 6. طريقة لتوقيع شيك مع شهادة4. نتيجة لذلك ، في الاختبار نحصل على:
(/ "((\d+) | (\d+) ?/) do |service_type|
القائمة 7. خطوة اختبار Gherkin لإطار الخيارالاعتماد رقم 3. التحقق من الاختيار على خادم Badoo
لإزالة التبعية الثالثة ، تحتاج إلى التخلص من التحقق من التحقق على الخادم. من المهم أن نتذكر أن التحقق يتم على مرحلتين. في المرحلة الأولى ، تتم المصادقة على الشيك بناءً على التوقيعات والشهادات. في الثانية - يتم إرسال الشيك إلى متجر التطبيقات. في حالة نجاح التحقق من الصحة في هذه المرحلة ، سوف نتلقى شيكًا مشفرًا يمكن معالجته.
الشكل 7. إزالة التحقق من الخادمأولاً ، يقوم الخادم بالتحقق الأولي من التحقق في طريقة checkReceiptByCert للفئة الأصل. هذا يتحقق من التوقيع مع شهادة متجر التطبيقات. في حالة إجراء فحص مزيف ، ستفشل عملية التحقق هذه لأنها موقعة بواسطة الشهادة الخاصة بنا ، وسنتصل بطريقة التحقق باستخدام الشهادة المحلية checkReceiptByLocalCert. في هذه الطريقة ، سنحاول فك تشفير التحقق باستخدام شهادة محلية ، وإذا نجح ، فسوف نضع نتيجة فك التشفير في الحقل الداخلي local_receipt للفئة الفرعية (addLocallyVerifiedReceipt).
class EngineTest extends Engine function verifyReceiptByCert($receipt) { $result = parent::verifyReceiptByCert($receipt); if ($result === -1 || empty($result)) { $result = $this->verifyReceiptByLocalCert($receipt); } return $result; } function verifyReceiptByLocalCert($receipt) { $receipt_file = tempnam(sys_get_temp_dir(), 'rcp'); file_put_contents($receipt_file, base64_decode($receipt)); $result = openssl_pkcs7_verify($receipt_file, PKCS7_BINARY, '/dev/null', [$DIR]); if ($result) { $this->addLocallyVerifiedReceipt($receipt, base64_decode($response)); } unlink($receipt_file); return $result; } class Engine function verifyReceiptByCert($receipt) { $receipt_file = tempnam(sys_get_temp_dir(), 'rcp'); file_put_contents($receipt_file, base64_decode($receipt)); $result = openssl_pkcs7_verify($receipt_file, PKCS7_BINARY, '/dev/null', [$DIR]); unlink($receipt_file); return $result; }
قائمة 8. التحقق الأوليأثناء عملية التحقق الثانوية (checkReceipt) ، نحصل على قيمة الحقل local_receipt للفصل التابع getLocallyVerifiedReceipt. إذا لم تكن فارغة ، فإننا نستخدم قيمتها نتيجة للتحقق.
إذا كان الحقل فارغًا ، فإننا ندعو إلى التحقق الثانوي من الفئة
الأصل (أصل :: checkReceipt). هناك نقدم طلبًا إلى App Store للتحقق من جانبه. نتيجة التحقق في كلتا الحالتين هي فحص غير مشفر.
class EngineTest extends Engine function verifyReceipt($receipt_encoded, $shared_secret, $env) { $response = $this->getLocallyVerifiedReceipt($receipt_encoded); if (!empty($response)) { return json_decode($response, true); } return parent::verifyReceipt($receipt_encoded, $shared_secret, $env); } class Engine function verifyReceipt($receipt_encoded, $shared_secret, $env) { $response = $this->_sendRequest($receipt_encoded, $shared_secret, $env); return $response; }
قائمة 9. الثانوية التحقق5. تشغيل اختبار الفيديو: شراء القروض والاشتراكات
اختبار رقم 1. شراء الاشتراك
اختبار تشغيل الفيديو:

اختبار رقم 2. شراء القروض وإرسال هدية
اختبار تشغيل الفيديو:

تقييم القرار: المخاطر الرئيسية
تنطوي إزالة التبعيات الخارجية على بعض المخاطر.
1. التكوين غير صحيح.
نظرًا لأن التحقق ليس في صالحنا ، فقد نقوم بتهيئة منتجاتنا بشكل غير صحيح من جانب Apple. للحماية من الأخطاء ، قمنا بكتابة اختبار وحدة منفصلة من جانب الخادم ، والذي يتحقق من أن جميع المنتجات التي نبدأ من جانب Apple تتطابق مع المنتجات التي لدينا في التكوين الخاص بنا.
2. الحالات الحدودية.
على سبيل المثال ، عند اكتمال الدفع بالكامل ، يتلقى المستخدم إشعارًا بأنه قد أكمله ، لكن طلبنا لا يمكنه العثور على الشيك الذي يجب تزويره نتيجة لإجراء هذه الدفعة. يكمن الخطر في حقيقة أننا أنفسنا نعلق الشيك بمساعدة مستتر ، ولا يمكننا بطبيعة الحال تتبع مثل هذه الحالة. من أجل التعويض عن هذا الخطر بطريقة أو بأخرى ، فإننا نجري شيكات شاملة باستخدام صندوق الحماية أو دفعة حقيقية بعد الإصدار.
3. غير عادلة وهمية أو الاحتيال.
بعد قراءة هذا المقال ، قد تعتقد أنه نظرًا لأن Badoo يستخدم اختبارات وهمية ، فيمكنك إرفاق شيء مزيف لنا واستخدام الخدمة مجانًا. حتى لا يتحقق هذا الخطر ، فإننا نوقع كل شيء بشهادتنا الخاصة ونقيد استخدام الموك والشيكات المزيفة في الاختبارات الوظيفية التي يتم تشغيلها فقط في بيئة التطوير الخاصة بنا.
4. تغيير شكل الشيك.
هذا هو الخطر الأكثر خطورة. من الممكن تغيير تنسيق الشيك عندما تغير Apple شيئًا دون تحذيرنا. لدينا مثل هذه الحالة: عند التبديل إلى iOS 11 ، تغير شكل الشيك تمامًا. لقد أنشأنا فحصًا مزيفًا على خادمنا واستخدمناه في الاختبار. كان كل شيء مثاليا معنا: جميع الحقول موجودة ، كل شيء رائع ، كل شيء قيد المعالجة. لكن عندما تحولنا إلى النظام الحقيقي ، لم ينجح شيء. الحقول التي كانت مهمة في الاختيار لم تعد موجودة.
كيف تعوض عن هذا الخطر؟ أولاً ، لا نستبعد إمكانية إجراء اختبار شامل لصندوق الحماية قبل الإصدار والدفع الحقيقي بعد الإصدار. نحن الآن في المرحلة النشطة من المشروع لفحص الإشعارات ، عندما نحاول تصنيف جميع عمليات الفحص التي نتلقاها من الإنتاج على أساس ما إذا كنا نفهم ما هو أو لا نفهم. إذا كانت الإجابة "لا" ، فسنبدأ في معالجة كل شيء يدويًا ، ونرى ما الذي تغير ، وما هو الخطأ ، وما الذي يجب تغييره في نظامنا.
يؤدي
النظر في المزايا الرئيسية التي تمكنا من الحصول عليها نتيجة لتطبيق طريقة moki والكائن وهمية.
أتمتة غير مكلفة وسريعة ومستقرة للخدمات المدفوعة على نظام التشغيل iOS
إلى جانب فريق الاختبار اليدوي لنظام التشغيل iOS (شكر خاص لـ Colin Chan) ، تمكنا من كتابة أكثر من 150 اختبارًا تلقائيًا للدفعات. هذا هو مقدار كبير إلى حد ما من التغطية لمنطقة واحدة من التطبيق.
بفضل التوازي ، يمكننا الحصول على النتيجة في 15-20 دقيقة فقط على أي فرع من مطور عميل iOS أو مطور خادم الفواتير. قبل التشغيل الآلي ، استغرق الاختبار اليدوي لهذه المنطقة من قبل شخص واحد ثماني ساعات.
يمكننا أيضًا اختبار الغالبية العظمى من حالات الاختبار من خلال إعداد موفر الدفع المزيف من خلال moki بالطريقة التي نحتاج إليها. بمساعدة من mooks ، تعلمنا كيفية إيقاف تشغيل فحص المنتج ومحاكاة الحالات عند إجراء الفحص جزئيًا. وهكذا ، فتحنا الحالات التي لم نتمكن من اختبارها من حيث المبدأ من قبل.
الانحدار الوظيفي في تطوير ميزات جديدة
عملت الأتمتة جيدًا في تلك الحالات عندما يؤثر المطور في عملية العمل على ميزة جديدة على الوظيفة القديمة. كان لدينا مثال عندما قام مطور بعمل ميزة معقدة مع التخزين المؤقت وأجرى اختباراتنا التلقائية. سقط بعضهم في الخطأ. رآه وثبته. ثم قام بإعادة تشغيل الاختبارات الذاتية مرة أخرى - ومرة أخرى ، سقط شيء ما. ونتيجة لذلك ، قام بسلسلة من التكرارات حتى اللحظة التي بدأ فيها كل شيء العمل بشكل طبيعي على جانب التطبيق.
الانحدار الوظيفي في إعادة بيع المساكن
ربما يحدث التشغيل الآلي الأكثر نجاحًا وفعالية في مجال إعادة هيكلة الكود. في هذه الحالة ، يتم تغيير التطبيق الداخلي فقط - ليست هناك حاجة لتغيير كود الاختبار التلقائي. لا تتغير واجهة المستخدم بأي شكل من الأشكال ، ويمكن قيادة الاختبارات التلقائية بكفاءة.
اختبار الميزات التجريبية من Apple: فترة السماح
يكون نظام مماثل قابلاً للتبادل تمامًا عند اختبار تكاملات جديدة لم يتم تنفيذها بعد في صندوق الحماية. لذلك كان مع فترة سماح. هذه الوظيفة ليست في رمل. فترة السماح على Apple ليست متاحة بعد للجميع. هذا مشروع رائد تنفذه Badoo مع Apple. من أجل التحقق مع فترة سماح ، نحتاج إلى إضافة قطعة من كود JSON هنا:
pending_renewal_info:[ { expiration_intent: 2 grace_period_expires_date: 2019-04-25 15:50:57 Etc/GMT auto_renew_product_id: badoo.productId original_transaction_id: 560000361869085 is_in_billing_retry_period: 1 grace_period_expires_date_pst: 2019-04-25 08:50:57 America/Los_Angeles product_id: badoo.productId grace_period_expires_date_ms: 1556207457000 auto_renew_status: 1 }]
قائمة 10. فترة سماح للاشتراكلقد فعلنا ذلك بسهولة شديدة في بضع ثوانٍ. في نظامنا ، تمكنا من اختبار رد فعلنا على ميزة جديدة. الآن نحن نعمل على هذه الوظيفة على همز.
اختبار جودة المنتج في طرق التكوين
كنتيجة لبحثنا ، تمكنا من وصف طريقة تزيل الضوضاء من التبعيات الخارجية. ساعد هذا مطوري العملاء في عملية تطوير الميزات في العثور على الأخطاء في المراحل المبكرة.
لكن لا تعتقد أننا تمكنا من اختبار كل شيء بهذه الطريقة. لاختبار كل شيء ، من الأفضل استخدام تركيبة من الأساليب: الاختبار باستخدام بطاقة حقيقية على المنتج ، والاختبار في الصندوق الرمل ، وطريقة الإشارات والأشياء المزيفة ، واختبار الوحدة والتكامل. يرجى تذكر رصيد هرم الاختبار ولا تحاول حل جميع المشكلات باستخدام طريقة واحدة. يمكن أن يؤدي هذا إلى التشغيل التلقائي المحزن في صندوق الحماية ، إلى الاختبار اليدوي الحزين باستخدام بطاقة حقيقية لجميع الحالات ، والعديد من الأخطاء الخطيرة الأخرى في المكان المحدد حيث يكون مظهرها مؤلمًا للغاية.
استنتاج
نتيجة لبحثنا ، حصلنا على وسيلة غير مكلفة وسريعة ومستقرة لاختبار ليس فقط الخدمات المدفوعة على نظام التشغيل iOS ، ولكن أيضًا أي مكونات مدمجة في التطبيق كـ "صندوق أسود". نطبق الآن على Badoo هذه الطريقة للاختبار على مزودي Android المدفوعين (Global Charge ، Boku ، Centili) الذين لديهم صناديق رمل غير مستقرة أو أي قيود أخرى. نستخدم أيضًا طريقة moki لاختبار الإعلان والتدفق وتحديد الموقع الجغرافي.
تجدر الإشارة إلى أن عملية إدخال طريقة جديدة لم تكن سريعة. كان علي التفاوض مع أربعة فرق: iOS QA ، iOS Dev ، Billing QA ، Billing Dev. لا يريد الجميع التحول إلى طريقة جديدة ، خوفًا من المخاطر. في بعض الأحيان ، كانت هذه متابعة عقائدية: لسنوات عديدة قمنا باختبارها في صندوق الحماية ، وكانت القوة الرئيسية التي يمكن أن تدمر العقيدة هي رغبة اختبار الفواتير ومنصة iOS لتغيير الموقف والتخلص من العذاب. في وقت لاحق ، أدرك المطورون مزايا هذه الطريقة مثل التشخيصات الدقيقة (لم نتمكن من العثور على الأخطاء في صندوق الحماية ، ولكن أخطاء العميل أو الخادم الخاص بنا) ، والمرونة في إعداد المكون (تمكنا من اختبار الحالات السلبية بسهولة على مستوى التكامل) ، وكانت الإجابة بالطبع 30 دقيقة على فرع مع رمز المتقدمة.
شكرا جزيلا لكل من قرأ حتى النهاية. شكرا جزيلا لكل من ساعد وشارك في هذا المشروع. شكر خاص لهؤلاء الناس:
- بيتر Kolpashchikov هو مطور دائرة الرقابة الداخلية الذي ساعد في جعل moki على جانب العميل وطور مفهوم PPP ؛
- فلاديمير سولودوف - Billing QA ، الذي ساعد مع API QA لإنشاء شيكات وهمية والخروج من خادم الفواتير ؛
- مكسيم فيلاتوف وفاسيلي ستيبانوف - فريق تطوير الفواتير ، الذي ساعد في رمز خادم الفوترة ؛
- فريق تطوير iOS - المطورين الذين تمكنوا من إعادة تأكيد دفعاتنا في مفهوم جديد ، مما يجعل استخدام mokas ممكنًا ؛
- iOS QA Team هو فريق اختبار رائع كتب مجموعة من الاختبارات الذاتية ؛
- Billing Team QA Team - المختبرين الذين ساعدوا في البحث عن المشكلات.