ما الذي يتحقق منه اختبار العقود
أن تكون البنية التي يتوقعها الطرفان واحدة: أسماء الحقول، وأنواعها، وما هو إلزامي وما هو اختياري، ورموز الحالة. فإذا حذفت الخدمة المنتِجة حقلًا تعتمد عليه الخدمة المستهلِكة، يفشل اختبار العقود وقت البناء بدلًا من الثالثة فجرًا.
وفي نظام يضم خدمات كثيرة وعمليات نشر مستقلة، هذه قيمة حقيقية وأقل كلفة بكثير من بيئات التكامل الشاملة من طرف إلى طرف.
ما لا يتحقق منه عمدًا
ما إذا كانت القيمة صحيحة. فاستجابة سليمة البنية تحمل إجماليًا خاطئًا تستوفي كل عقد.
ما إذا كان التدفق يعمل. إذ يمكن لكل استدعاء أن يستوفي عقده بينما تنتج السلسلة نتيجة بلا معنى.
ما يراه المستخدم. فالعقود تدور حول حديث الخدمات مع الخدمات. لم يفتح أحد المنتج نفسه.
لا شيء من هذا نقد. فاختبار عقودٍ يتحقق من القيم سيصبح مرتبطًا بالبيانات وينكسر باستمرار، وهو تحديدًا ما صُمّم اختبار العقود لتفاديه. الضيق هنا هو الميزة.
نمط الإخفاق الذي ينبغي الانتباه له
يتبنّى فريقٌ اختبار العقود، فتتوقف إخفاقات التكامل وترتفع الثقة. وبعد ستة أشهر ينكسر في الإنتاج شيءٌ اجتاز كل اختبارات العقود، لأن البنية كانت صحيحة والسلوك كان خاطئًا. والدرس الذي يستخلصه الناس عادةً هو أن اختبار العقود قد أخفق، وهذا هو الدرس الخاطئ.
لقد أدّى اختبار العقود وظيفته. الفجوة أن لا شيء كان يتحقق من السلوك، ونجاح طبقة العقود جعل تلك الفجوة أصعب في الرؤية.
ما ينبغي أن يقف إلى جانبه
تحقّق وظيفي مقابل الخدمات العاملة: هل تنتج سلسلة الاستدعاءات النتيجة الصحيحة، وهل تتصرف مسارات الخطأ كما ينبغي، وهل يصمد التفويض. تلك طبقة مختلفة، وهي تجيب عن الأسئلة التي لا تستطيع العقود الإجابة عنها.
وهذه الفحوص تحتاج إلى التعامل مع الجلسات، والقيم الملتقطة بين الاستدعاءات، والترتيب والتنظيف، وهو ما يغطيه توثيق اختبار API.
الطرفية
npm install -g @testsprite/testsprite-cli
testsprite setup
وإن كنت تفضّل ألّا تثبّت شيئًا، فلوحة التحكم تؤدي الغرض نفسه. أما كل ما يستطيع سطر الأوامر فعله فتجده في مستودع CLI.
المقاربة المدفوعة بالمستهلِك، ولماذا تتفوق عادةً
تختلف المقاربتان في مَن يكتب العقد، ويظهر الفرق بعد عام لا على الفور.
العقود المدفوعة بالمنتِج تُدوّن ما تنوي الخدمة تقديمه. وهذا مفيد، لكنه يميل إلى السخاء: فالعقد يصف الاستجابة كاملة، بما فيها حقول لا يستهلكها أحد. عندئذٍ تُفشل التغييراتُ الكاسرة في حقول غير مستخدمة عمليةَ البناء، فتبدأ الفرق بتجاهل إخفاقات العقود، وهو ما يُبطل الغاية منها.
أما العقود المدفوعة بالمستهلِك فتُدوّن ما يقرأه كل مستهلِك فعلًا. العقد أصغر، والإخفاقات حقيقية، وتحصل على ناتج جانبي مفيد حقًا: خريطة دقيقة لأي الحقول يهم أيَّ طرف. وهذه الخريطة هي ما يتيح للمنتِج أن يوقف دعم شيء ما بثقة، وهو ما أراده الجميع فعلًا.
أين يعمل كل منهما
اختبارات العقود وقت البناء، سريعةً ومع كل إيداع، لأن قيمتها كلها في التقاط انحراف البنية قبل التكامل. والتحقق السلوكي مقابل بيئة منشورة، مع كل طلب سحب.
المُشغّل أهم من الآلية. فتوجيهه إلى حدث النشر لديك يعني أن كل تغيير يُفحص دون أن يقرر أحد ذلك؛ فـ GitHub App يؤدي ذلك من لوحة التحكم، أما GitHub Actions فتؤدي خطوةٌ فيه ذلك من داخل سير عملك.
ما تجيب عنه TestSprite ولا تستطيع العقود الإجابة عنه
ما إذا كانت القيم صحيحة وما إذا كانت السلسلة تنتج النتيجة الصحيحة. فهي تشغّل الخدمات العاملة عبر واجهاتها، وبذلك تُلتقط الاستجابة التي تستوفي كل عقد وتحمل إجماليًا خاطئًا.
التدفقات متعددة الخطوات هي الفجوة تحديدًا. تربط Integration Tests الاستدعاءات في سلسلة تغذّي فيها كل استجابة ما يليها، وتستنتج Dependency Chains ترتيبًا آمنًا مما تحتاجه كل حالة وما تنتجه. وتُبقي Auto-Authentication الجلسات حيّة طوال التشغيل، وتنقل Dynamic Variables القيم بين الاستدعاءات، وتستنتج Dependency Chains ترتيب التنفيذ مما تحتاجه كل حالة وما تنتجه، وتزيل Auto-Cleanup ما أنشأه التشغيل بالضبط.
وما تنتهي إليه هو طبقتان لا تتداخلان: عقود تلتقط انحراف البنية وقت البناء، بكلفة زهيدة ومع كل إيداع، وتحقق سلوكي يلتقط أسئلة الصحّة التي تعمى عنها العقود عمدًا.
هل تُجري TestSprite اختبار عقود؟
لا. فهي تتحقق من السلوك مقابل الخدمات العاملة. اختبار العقود أداة مختلفة، والاثنان يكمّل أحدهما الآخر.
هل يكفي اختبار العقود للخدمات المصغّرة؟
هو الإجابة الصحيحة لانحراف البنية بين الخدمات، لكنه لا يخبرك ما إذا كان تدفق يمتد عبر عدة خدمات ينتج النتيجة الصحيحة.
مدفوع بالمستهلِك أم مدفوع بالمنتِج؟
المدفوع بالمستهلِك يلتقط أعطالًا حقيقية أكثر، لأنه يُدوّن ما يستخدمه المستهلكون فعلًا لا ما نوى المنتِج تقديمه.
هل ما زلنا بحاجة إلى اختبارات التكامل؟
عدد أقل منها، وهذا هو المقصود. احتفظ بمجموعة صغيرة تغطي التدفقات الممتدة عبر الخدمات، واترك للعقود مسألة البنية.
ماذا لو كنا نتحكم بالطرفين معًا؟
تنخفض القيمة، لأن بإمكانك تغييرهما معًا. وتكون فائدته أكبر ما تكون حين تنشر الفرق بشكل مستقل.
بنية صحيحة، وسلوك مجهول.
يلتقط اختبار العقود انحراف البنية بين الخدمات بكلفة زهيدة، وهو أعمى عمدًا عن صحّة أيٍّ من الطرفين. أبقِه وقت البناء، وضع إلى جانبه تحققًا سلوكيًا مقابل الخدمات العاملة.