اختبار العقد
1) مكان تطبيق العقود
HTTP REST/JSON: الموارد، الاستعداد، المرشحات، الخصوصية، رموز الخطأ.
gRPC/Protobuf: أنواع الرسائل، والحالات، ودلالات «الموعد النهائي»، والكومبات الخلفية v.proto.
GraphQL: مخططات، غير لاغية، توجيهات، متساهلة في الحقول.
الرسائل/التدفقات (كافكا/بولسار/SQS): مخططات الأحداث (Avro/JSON/Protobuf)، مفاتيح التقسيم، النظام، المفاتيح الخفية.
SDKs/Libraries: Public Features/Excentions/Performance Contracts.
2) نموذج CDC: الأدوار والتحف
ينشر المستهلك عقد التوقعات (عينة من الطلبات/الردود، مطابقات النوع، الثوابت).
يقوم المورد بالتحقق من العقد مقابل خدمته/محوله/معالجه.
يقوم سمسار العقد (Pact Broker/Backstage/repo artifact) بتخزين الإصدارات والعلامات («prod» و «staging» و «canary») ومصفوفة التوافق «consumer @ v → provider @ v».
سياسة الإفراج: يُحظر إرسال مزود إذا تم انتهاك أي عقد «ذي صلة».
3) ما يجب إصلاحه في العقد (مثال HTTP)
الحد الأدنى:- الطريقة/المسار/البارامترات/الرؤوس (بما في ذلك Auth, idempotent key).
- الجسم والمطابقات النموذجية (النوع/الشكل/regexp/النطاقات).
- رموز وهياكل الخطأ ؛ «خطأ _ رمز» مستقر.
- الثوابت الدلالية: الفرز، التفرد، الرتابة "تم إنشاؤها _ at'.
- التوقعات غير الوظيفية (اختياري): p95، حدود الحجم، رؤوس حد المعدل.
json
{
"interaction": "GET /v1/users/{id}",
"request": { "method": "GET", "path": "/v1/users/123", "headers": {"Accept":"application/json"} },
"matchers": {
"response. body. id": "type:number",
"response. body. email": "regex:^.+@.+\\..+$",
"response. body. created_at": "format:rfc3339"
},
"response": {
"status": 200,
"headers": {"Content-Type":"application/json"},
"body": {"id": 123, "email": "alice@example. com", "created_at": "2025-10-31T12:00:00Z"}
},
"error_cases": [
{
"name":"not_found",
"request":{"path":"/v1/users/9999"},
"response":{"status":404, "body":{"error_code":"USER_NOT_FOUND"}}
}
]
}
4) العقود التي تحركها الأحداث
مخطط الحدث: "نوع"، "إصدار"، "معرف"، "حدث _ at_utc'،" منتج "،" موضوع "،" حمولة ".
الثوابت: invariance 'id' and idempotence by '(type, id)', order by the key of the part, munotony 'sequence'.
قواعد التطور والتوافق بين مخططات التسجيل والمخازن (إلى الخلف/إلى الأمام/إلى الأمام/إلى الأمام).
اختبارات عقد المستهلك: إعادة تشغيل الأحداث «الذهبية» ومراحل السلبيات (حقول غير معروفة، غير قابلة للإلغاء).
json
{
"type":"record","name":"UserRegistered","namespace":"events. v1",
"fields":[
{"name":"id","type":"string"},
{"name":"occurred_at_utc","type":{"type":"long","logicalType":"timestamp-millis"}},
{"name":"email","type":"string"},
{"name":"marketing_opt_in","type":["null","boolean"],"default":null}
]
}
5) التطور والتوافق
إصدارات العقد: دلالات «MAJOR». قاصر. التصحيح (كسر رئيسي).
قواعد الراحة:- لا تكسر: لا تحذف الحقول، لا تغير نوع/قيمة «خطأ _ رمز».
- إضافة حقول اختيارية مع التقصير ؛ نقاط نهاية جديدة بدلاً من «السحر».
- التخفيض: الإعلان، الدعم المتزامن، الحذف بالمقاييس.
- الرسم البياني QL: الحقول المضافة فقط، الدخول غير الفارغ عبر المراحل ؛ إصدار التوجيهات.
- gRPC/Proto: لا تعيد استخدام أرقام الحقول ؛ فقط أضف جديدا مع اختياري.
- الأحداث: المخطط 'vN' ؛ على المستهلكين تجاهل المجالات المجهولة (التساهل).
6) الشيكات السلبية والثابتة
سلبي: أنواع غير صحيحة، قيم ممنوعة، معايير متضاربة، تتجاوز الحدود.
الثوابت: فرز الردود، تفرد «هوية»، صحة «المؤشر التالي»، استقرار الاستجابة الخفية عند تكرارها.
العقود ذات الجوانب المؤقتة: «تم إنشاؤها - في» RFC3339/UTC، الإسقاط الصحيح للأيام المحلية ليس جزءًا من عقد النقل - يتم تقديمه إلى الشركات الثابتة.
7) توليد الطعنات والتنمية المحلية
من العقود، يتم إنشاء أكوام المزودين لتطوير المستهلك.
بالنسبة للأحداث - مولدات الرسائل «الصالحة/الحدودية» وفقًا للمخطط.
ويحدد الموظفون بصيغة العقد وتاريخ بنائه ؛ النشر على سبيل الحصر.
8) تضمين CI/CD (خط المرجع)
1. CI المستهلك:
Lint/build → contract ground → unit/test contract → publish in contract-broker (tag: 'consumer @ 1. 7. 0`).
2. المزود CI:
رفع مستوى الخدمة محلياً/في الحاوية → إحضار العقود ذات الصلة ('prod'/'staging') → التحقق → نشر الوضع في السمسار.
3. إطلاق البوابة:
يتم حظر نشر المزود إذا كانت هناك عقود معلقة.
4. المصفوفة الليلية:
مصفوفة التوافق «إصدارات المستهلكين × إصدارات مقدمي الخدمات» ؛ التقارير والإنذارات.
9) أمثلة على الممارسات حسب المجال
9. 1 REST: استعداد المؤشر (عقد ثابت)
يحتوي الرد على «العناصر []» و «المؤشر التالي _» (غير قابل للإلغاء) و «الحد» و «المجموع» (اختياري).
الثوابت: «len (العناصر) ≤ الحد»، مكالمة متكررة بنفس «المؤشر» → مجموعة خفية.
الخطأ إذا تم تحديد كل من «المضيف» و «الصفحة».
9. 2 ما بعد الخصوصية
يتطلب العقد رأس «Idempotency-Key».
ثابت: الاستفسار المتكرر بنفس المفتاح يعيد نفس «الهوية »/الحالة.
9. الأحداث 3: ضمانات النظام
مفتاح التقسيم في العقد هو "التقسيم _ المفتاح = user_id'.
الثابت: «التسلسل» يزداد رتيبًا داخل المفتاح ؛ يجب على المستهلك التعامل مع الإعادة.
10) الأمن والخصوصية في العقود
لا تتضمن البيانات/الأسرار الشخصية في الأمثلة - فقط المواد التركيبية.
إصلاح رؤوس الأمان الإلزامية: «الإذن»، «التوقيع السيني»، «إعادة منع».
بالنسبة للخطابات الشبكية - عقد التوقيع والاستجابة '2xx '/إعادة الطباعة.
في سجلات اختبارات العقد - إخفاء الحقول الحساسة.
11) الأدوات
Pact/Pactflow/Pact Broker - عقود HTTP/Message، مصفوفة التوافق.
OpenAPI/AsyncAPI - مواصفات + مولدات اختبار (Dredd، Schemathesis).
الكاراتيه/REST مضمون - عمليات التحقق من سيناريو عقود REST.
Protobuf/gRPC - 'buf'، 'protolint'، اختبارات التوافق ؛ Schema Registry for Avro/JSON/Proto in streams.
اختبارات المطابقة لـ GraphQL (graphql-compat)، اختبارات دائرة اللقطات.
12) الكود الزائف للتحقق من مقدم الخدمة (مبسط)
python def verify_contract(provider, contract):
for case in contract["cases"]:
req = build_request(case["request"])
res = provider. handle (req) # locally/assert match_status container (res. status, case["response"]["status"])
assert match_headers(res. headers, case["response"].get("headers", {}))
assert match_body(res. body, case["matchers"], allow_extra_fields=True)
for neg in contract. get("error_cases", []):
res = provider. handle(build_request(neg["request"]))
assert res. status == neg["response"]["status"]
assert res. json. get("error_code") == neg["response"]["body"]["error_code"]
13) الأنماط المضادة
«لقطات ساعي البريد هي عقد»: لا توجد إصدارات/مطابقات نموذجية/التحقق التلقائي.
الإفراط في القيلولة: يحدد العقد القيم الدقيقة بدلاً من الأنواع/الأنماط → السقوط الخاطئ.
عقد مشترك واحد لمختلف المناطق/القنوات: يتجاهل التباين (الأعلام والقواعد الجغرافية).
العقود بدون وسيط/مصفوفة: من المستحيل فهم النسخ المتوافقة.
الرهان على e2e بدلاً من العقود: بطيء، مكلف، غير مستقر.
لا توجد حالات سلبية/ثابتة: يتم اختبار «المسار الأخضر» فقط.
14) إمكانية الرصد والتشغيل
حالة التصدير للوسيط + لوحة القيادة «العقود الصحية».
التنبيهات: انخفاضات جديدة في المزود مقابل عقود «الدفع»، وزيادة في «المجال غير المعروف» في الأحداث.
التتبع: 'العقد _ id'، 'النسخة'، 'القرار _ id' في سجلات التحقق.
15) عملية الاكتئاب
1. أضف حقل/نقطة نهاية (غير كسر).
2. ضع علامة على القديم على أنه «مستهجن» في المواصفات، وأعلن التواريخ.
3. تتبع المستهلكين عن طريق السجلات/السماسرة ؛ أدلة الهجرة.
4. قم بتمكين رفض «الظل» في المسرح (الجاف)، ثم فرضه.
5. تحذف بعد الصفر من الاستخدام والتوافق.
16) قائمة مراجعة المهندس المعماري
1. تم تحديد المستهلكين وأصحابهم ؟ العقود يتم تحريرها ؟
2. هل هناك وسيط ومصفوفة توافق مع علامات البيئة ؟
3. هل السلبيات والثوابت (الخصوصية، المؤشرات، الفرز) مدرجة في العقد ؟
4. هل تم إعداد سجل المخطط وطريقة التوافق للأحداث ؟
5. خط الأنابيب يمنع الإفراج عن المزود في حالة انتهاك عقود الإنتاج ؟
6. هل تم وصف عملية الاستنزاف وسياسة التطور ؟
7. يتم إنشاء الطعنات من العقود، هل هناك مولدات أحداث محلية ؟
8. هل تم توثيق إخفاء PD وعناوين السلامة الإلزامية ؟
9. المقاييس/التنبيهات بشأن العقود متصلة، هل هناك تقارير عن الانجراف ؟
10. ويقوم الطرفان (المستهلك والمزود) باستعراض العقود في إطار المبادرة الدولية ؟
خامسا - الاستنتاج
ينقل اختبار العقد «الحقيقة» حول التفاعلات إلى المخرجات المحفوظة ويجعل عمليات الدمج قابلة للتنبؤ. يقوم مركز السيطرة على الأمراض ووسيط العقد وانضباط تطور المخطط باستبدال «كسر المفاجآت» بعملية مُدارة: فحوصات سريعة، وثوابت واضحة، وتوافق الإصدار الشفاف. هذا يقلل من تكلفة e2e، ويسرع الإصدارات ويحسن جودة النظام الأساسي بأكمله.