اصطلاح — أنماط الاختبار
ما هو
ثلاثة اصطلاحات اختبار تعتمد عليها قاعدة الشيفرة، وُلِد كلٌّ منها من صنف عيب حقيقي: ملكية try/finally لحجب المفتاح الأجنبي (بحيث لا تستنزف الاختبارات بيانات البذرة المشتركة)، ومُنبّهات تبديل-المحتوى للبيانات المرجعية AR (بحيث لا تثبّت اختبارات i18n ترجمات هشّة)، وفجوة InMemory-مقابل-Postgres (بحيث تُختبَر استعلامات التجميع مقابل Npgsql الحقيقي، لا مجرّد EF InMemory).
متى تُستخدم
على اختبارات التكامل وE2E. تنطبق قاعدة InMemory-مقابل-Postgres على أي خدمة تجمّع/تُجمِّع؛ وقاعدة الملكية على أي اختبار يُغيِّر صفوف قاعدة-بيانات مشتركة؛ وقاعدة البيانات المرجعية على أي اختبار يؤكّد العرض العربي.
1. ملكية try/finally لحجب المفتاح الأجنبي
القاعدة: يملك الاختبار الصفوف التي يؤكّد عليها ويستعيدها في كتلة finally. تعمل اختبارات التكامل مقابل Postgres تطوير مشترك لا يُعاد ضبطه بين الاكتساحات، فاختبار يستهلك صفًّا مزروعًا دون استعادته يستنزف الترتيب عبر التشغيلات المتكررة.
العيب الذي حفّزها (PB-088): استهلك اختبار صفًّا واحدًا بذرة demand_template_lines بسبب-NULL كل تشغيل دون استعادته؛ ستة تشغيلات استنزفت البذرة 6 → 5 → 1 ثم فشل الاختبار بشكل متقطّع (tests/.../Infrastructure/IntegrationTestCleanup.cs).
الشكل: أدرِج/غيِّر داخل try؛ وفي finally، أعد القراءة بـ IgnoreQueryFilters() (بحيث تكون الصفوف المحذوفة ناعمًا مرئية) واستعد — ألغِ الحذف الناعم للأصل، واحذف نهائيًا أي شقيق اصطناعي. استخدم رمز اختبار مُلحَقًا (<ENT>_TEST_…) بحيث يستطيع مساعد التنظيف اكتساح البقايا.
قواعد الملكية الأربع: تملك الاختبارات الصفوف التي تؤكّد عليها؛ Down() للهجرة هو المعكوس البنيوي؛ لا تبدأ الاكتساحات في منتصف هجرة؛ قوائم تحقّق التحقّق تُشتَقّ من البيانات المزروعة (IntegrationTestCleanup.cs).
2. مُنبّه تبديل-المحتوى للبيانات المرجعية AR
القاعدة: لا تثبّت سلاسل عربية دقيقة — ثبّت الثابتين. تُحرَّر الترجمات نسخيًا؛ اختبار يؤكّد Assert.Equal("تسجيل الدخول", title) هشّ. بدلًا من ذلك أكّد:
- الاتجاهية —
document.documentElement.dir == "rtl"(وlang == "ar") عند تحميل البيانات المرجعية AR. - تبديل المحتوى — عنصر DOM نفسه يعرض نصًّا مختلفًا في EN مقابل AR (
Assert.NotEqual(enTitle, arTitle))، مُثبِتًا أن i18n حُلّ فعلًا بدلًا من الرجوع إلى المفاتيح.
هذا "decision #98"، مقفول في عمل PB-019 ومُطبَّق في tests/.../Locale/ArRtlTests.cs ومُعاد استخدامه في LeaveLocaleTests.cs. لاحظ تمييز locale مقابل language: سياق Playwright يأخذ ar-SA (BCP 47)، وlocalStorage يأخذ ar (حرفين) — يربط المساعد بينهما.
3. فجوة InMemory-مقابل-Postgres للمزوّد
القاعدة: غطِّ الاستعلامات الحسّاسة للمزوّد باختبار تكامل Postgres حقيقي. مزوّد InMemory الخاص بـ EF Core لا يترجم كل استعلام كما يفعل Npgsql، فاختبار وحدة InMemory أخضر قد يحجب فشل ترجمة في وقت التشغيل. المثال المُكرَّس: تجميعات group-all GroupBy(_ => 1) تتصرّف على نحو مختلف على مجموعة فارغة (InMemory مقابل Npgsql → null مقابل 0)، ما كسر حدود المساواة (Handover v10؛ ومؤكَّد في ملاحظة ذاكرة هذا المشروع نفسها).
الممارسة:
- استخدم InMemory للمنطق غير المُجمِّع (المُتحقِّقات، استعلامات الصف الواحد، التنظيم) — سريع ومتوازٍ.
- لأي تجميع/تجميعة (أفواج المساواة، عدّادات تغذّي قيمًا مُستطلَعة في الواجهة)، أضف اختبار
[Collection("PostgresIntegration")]يزرع بيانات واقعية ويؤكّد الشكل مقابل Postgres الحقيقي. - عامل
GroupBy(_ => 1)/GroupBy(_ => true)كعلَم مراجعة — أضف فحص مجموعة-فارغة صريحًا واختبار Postgres.
مزالق / قيود
IgnoreQueryFilters()فيfinally— دونها يخفي مرشّح الحذف-الناعم/المستأجر العام الصف الذي تحاول استعادته.- "يعمل في InMemory" ليس المعيار للتجميعات — اختبار تكامل Postgres وحده هو المعيار.
- لا تؤكّد ترجمات دقيقة — أكّد الاختلاف + الاتجاه. لا تثبّت مواضع البكسل أو الفروق البصرية أيضًا.
- اختبارات PostgresIntegration مُسلسَلة بمجموعة xUnit الخاصة بها (PB-002)، فإضافة واحد لا تبطّئ المجموعة بشكل ملموس — تخطّيه يؤجّل فقط خطأ وقت تشغيل إلى المطوّر التالي.
حالة البناء
Available — الأنماط الثلاثة جميعها حيّة في مجموعات الاختبار (tests/ManpowerIQ.Domain.Tests/، tests/ManpowerIQ.E2E.Tests/).
ذات صلة
- انضباط التدقيق-أولًا — تفحص التدقيقات أن هذه الاصطلاحات مُتّبعة.
- المهام في الخلفية — مهمة الاستيراد حسّاسة للمزوّد (فرع InMemory).
- تعدّد المستأجرين — مرشّح الاستعلام الذي يجب أن يتجاهله
finally. - المصدر:
tests/.../Infrastructure/IntegrationTestCleanup.cs،tests/.../Locale/ArRtlTests.cs؛docs/ManpowerIQ_Handover_v10.md؛ PB-019 / PB-088 / PB-002.