اختبار العقد
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) # локально/контейнер assert match_status(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، ويسرع الإصدارات ويحسن جودة النظام الأساسي بأكمله.