اختبارات التكامل: اكتشاف المشكلات عند تواصل المكونات مع بعضها
لقد كتبت دالة تبدو صحيحة. اجتاز اختبار الوحدة. المنطق نظيف. ثم تقوم بنشرها، ويبدأ التطبيق في إرجاع أخطاء. عمود قاعدة البيانات الذي افترضت وجوده تمت إعادة تسميته الأسبوع الماضي. واجهة API الخارجية التي تستدعيها غيرت تنسيق استجابتها. الخدمة التي تعتمد عليها تتوقع الآن ترويسة مختلفة.
هذه هي الفجوة التي لا تستطيع اختبارات الوحدة سدها. يمكن أن تكون الدالة صحيحة تمامًا بمعزل عن غيرها ومع ذلك تفشل عندما تحاول التواصل مع مكون آخر. توجد اختبارات التكامل لالتقاط هذه الأنواع من المشكلات تحديدًا.
ما الذي تتحقق منه اختبارات التكامل فعليًا
تتحقق اختبارات التكامل من أن مكونين أو أكثر يعملان معًا بشكل صحيح. قد تكون المكونات تطبيقك وقاعدة بيانات، أو خدمتك وواجهة API خارجية، أو خدمتين داخليتين داخل نفس النظام.
الأخطاء التي تلتقطها نادرًا ما تكون متعلقة بمنطق خاطئ. إنها تتعلق بافتراضات غير متطابقة:
يوضح مخطط التسلسل التالي حالة عدم تطابق نموذجية: ترسل الخدمة تاريخًا كسلسلة نصية، لكن قاعدة البيانات تتوقع طابعًا زمنيًا، مما يتسبب في حدوث خطأ.
- يرسل كودك تاريخًا كسلسلة نصية، لكن عمود قاعدة البيانات يتوقع طابعًا زمنيًا.
- تستدعي خدمتك واجهة API بمعامل استعلام، لكن واجهة API نقلت ذلك المعامل إلى نص الطلب.
- يفترض تطبيقك أن حقلاً ما موجود دائمًا، لكن الخدمة الأولية تتضمنه فقط في ظروف معينة.
هذه ليست أخطاء يمكنك اكتشافها بالتحديق في الكود. إنها تظهر فقط عندما تتبادل المكونات البيانات فعليًا.
فخ الهشاشة
لدى اختبارات التكامل سمعة بأنها بطيئة وهشة. هذه السمعة مستحقة. كلما زادت المكونات الحقيقية التي تتضمنها، زادت احتمالية فشل اختباراتك لأسباب خارجة عن كودك. انتهاء مهلة الشبكة. خدمة تابعة معطلة. بيانات اختبار تالفة بسبب تشغيل سابق.
عندما يحدث هذا بشكل متكرر، تتوقف الفرق عن الثقة في نتائج الاختبار. يبدأون في تخطي اختبارات التكامل أو تجاهل حالات الفشل. تصبح الاختبارات ضوضاء بدلاً من إشارة.
الحل ليس تجنب اختبارات التكامل. الحل هو أن تكون انتقائيًا بشأن ما تختبره باستخدام التبعيات الحقيقية.
اختيار ما تختبره باستخدام التبعيات الحقيقية
ليست كل تبعية تحتاج إلى أن تكون حقيقية في اختبارات التكامل الخاصة بك. قاعدة التجربة بسيطة: اختبر باستخدام تبعية حقيقية فقط للأشياء التي يصعب محاكاتها أو التي تسبب مشكلات بشكل متكرر في الإنتاج.
قواعد البيانات عادةً ما تستحق الاختبار باستخدام مثيل حقيقي. سلوك الاستعلام، القيود، المعاملات، والتأمين صعبة المحاكاة بدقة. قد يخبرك المحاكي (mock) أن استعلامك صحيح نحويًا، لكنه لن يخبرك أن استعلامك يسبب طريقًا مسدودًا (deadlock) تحت الوصول المتزامن، أو أن الترحيل (migration) الخاص بك غيّر نوع عمود لا يزال كودك يعامله كسلسلة نصية.
واجهات API الخارجية التابعة لجهات خارجية لا تستحق عمومًا الاختبار باستخدام نقاط نهاية حقيقية في خط أنابيبك. استخدم بدائل اختبار (test doubles) تسجل الاستجابات النموذجية. خطر الاختبارات غير المستقرة بسبب مشكلات الشبكة أو حدود معدل API يفوق الفائدة. احفظ التكامل الحقيقي للبيئة التجريبية (staging) أو التحقق في الإنتاج.
الخدمات الداخلية داخل مؤسستك تقع في المنتصف. يمكنك الاختبار باستخدام مثيلات حقيقية إذا كانت الواجهة تتغير بشكل متكرر وكانت تكلفة عدم التطابق عالية. بخلاف ذلك، غالبًا ما توفر اختبارات العقد (contract tests) إشارة أفضل مع هشاشة أقل.
طريقة عملية للقرر: اسأل نفسك، "إذا كانت هذه التبعية بها مشكلة، هل سأعرف من منطق التطبيق، أم فقط من كيفية اتصالها؟" إذا كانت الإجابة "من كيفية اتصالها" - تنسيق الاستجابة، بنية الترويسة، ترتيب المعاملات - فهي مرشحة لاختبار تكامل مع تبعية حقيقية. إذا كانت الإجابة "من منطق التطبيق"، فإن اختبارات الوحدة أو اختبارات العقد كافية.
الحفاظ على سرعة وموثوقية اختبارات التكامل
بمجرد أن تقرر ما تختبره باستخدام التبعيات الحقيقية، اتبع هذه الممارسات للحفاظ على فائدة اختبارات التكامل:
اختبر الاتصال فقط، وليس منطق الأعمال. إذا كان لديك بالفعل اختبارات وحدة تغطي قواعد عملك، فلا تكررها في اختبارات التكامل. يجب أن يتحقق اختبار التكامل لاستعلام قاعدة بيانات من أن الاستعلام يعمل بنجاح ضد قاعدة بيانات حقيقية ويعيد البنية المتوقعة. لا ينبغي أن يتحقق من كل حالة حافة لمنطق الأعمال الذي يستخدم ذلك الاستعلام.
أعد ضبط البيئة قبل كل اختبار. إذا كنت تستخدم قاعدة بيانات، فأنشئ بيانات اختبار معزولة ونظفها بعد انتهاء الاختبار. الاختبارات التي تعتمد على حالة خلفتها اختبارات سابقة تكون هشة ويصعب تصحيح أخطائها. استخدم معاملات قاعدة بيانات يتم التراجع عنها بعد كل اختبار، أو شغّل حاوية اختبار جديدة لكل تشغيل اختبار.
حدد عدد اختبارات التكامل. لست بحاجة لاختبار كل مجموعة من المعاملات. اختبر مسارًا سعيدًا واحدًا (happy path) وعددًا قليلاً من سيناريوهات الفشل الواقعية. الهدف هو الثقة في أن الاتصال يعمل، وليس تغطية كل مدخل ممكن.
أين تتناسب اختبارات التكامل في خط أنابيبك
تقع اختبارات التكامل بين اختبارات الوحدة واختبارات النهاية إلى النهاية (end-to-end). إنها أكثر تكلفة من اختبارات الوحدة ولكنها أسرع وأكثر تركيزًا من اختبارات النهاية إلى النهاية.
يقوم خط أنابيب نموذجي بتشغيل اختبارات الوحدة أولاً. إذا نجحت، يقوم خط الأنابيب بتشغيل اختبارات التكامل. إذا نجحت اختبارات التكامل، ينتقل خط الأنابيب إلى النشر في البيئة التجريبية أو الإنتاج. اختبارات النهاية إلى النهاية، إذا كانت لديك، تعمل لاحقًا أو في بيئة منفصلة.
الغرض من اختبارات التكامل ليس تحقيق نسبة تغطية. الغرض هو منحك الثقة في أنه عندما يتغير كودك، فإن الاتصالات بين المكونات لا تزال تعمل.
قائمة مراجعة عملية
- لكل تبعية خارجية، قرر: اختبر باستخدام مثيل حقيقي، اختبر باستخدام بديل اختبار، أو اعتمد على اختبارات العقد.
- قم بتشغيل اختبارات التكامل في بيئة معزولة يمكن إعادة ضبطها إلى حالة معروفة.
- حافظ على تركيز اختبارات التكامل على سلوك الاتصال، وليس منطق الأعمال.
- حدد اختبارات التكامل بمسار سعيد واحد وعدد قليل من سيناريوهات الفشل الواقعية.
- راقب وقت تنفيذ الاختبار. إذا استغرقت اختبارات التكامل وقتًا أطول من اختبارات الوحدة، فمن المحتمل أن لديك عددًا كبيرًا جدًا أو النوع الخاطئ منها.
الخلاصة
تجيب اختبارات التكامل على سؤال لا تستطيع اختبارات الوحدة الإجابة عليه: "هل تعمل هذه المكونات معًا فعليًا؟" من الجيد الحصول على الإجابة قبل النشر. لكن اختبارات التكامل هي أداة، وليست هدفًا. كن انتقائيًا بشأن ما تختبره باستخدام التبعيات الحقيقية، وحافظ على سرعة الاختبارات وعزلها، واستخدمها لبناء الثقة في عمليات النشر الخاصة بك، وليس لمطاردة أرقام التغطية.