انتقل إلى المحتوى

الاختبار

يُتحقق من Greph عبر ثلاث طبقات من الاختبارات:

  1. اختبارات الوحدة للمكونات المنفردة (المحللات، والمتجوّلات، وبرامج الترميز، والخيارات).
  2. مجموعة اختبارات التراجع المرجعية التي تقارن مخرجات Greph مع ملفات grep وripgrep وast-grep التنفيذية المعتمدة، ضمن مجموعة ثابتة من السيناريوهات.
  3. مصفوفة ميزات قائمة على الاختبارات المسبقة تتحقق من النطاق المؤكد لأغلفتي rg وsg.

تشغّل CI عند كل دفع إلى main وعند كل طلب دمج (.github/workflows/ci.yml). وتشغّل معايير كتابة الشيفرة (composer cs) والتحليل الساكن (composer analyse) ومجموعتي اختبارات الوحدة والتكامل في PHPUnit (composer test) وcomposer audit على PHP 8.4. مجموعة الاختبارات المرجعية (composer test:oracle) غير مشمولة في CI، وتُعاد كتابة مصفوفة الميزات يدويًا باستخدام php bin/feature-matrix. تتضمن مجموعة PHPUnit اختبارًا ينشئ المصفوفة مع اعتبار rg وsg من أدوات المنبع غير متاحتين، ويتحقق من بنية التقرير، لذا لا يفشل عند تراجع اختبار مسبق واحد.

العمل من نسخة مستنسخة

تتطلب كل المعلومات في هذه الصفحة استنساخ المستودع. منذ الإصدار 0.2.3، لا تتضمن حزمة Composer سوى src/ والبرامج التنفيذية الأربعة؛ أما tests/ وscenarios/ وbenchmarks/ وسكربتات التطوير في bin/ فمستثناة منها.

سطر الأوامر
git clone https://github.com/inline0/greph
cd greph
composer install

تشغيل الاختبارات

سطر الأوامر
# PHPUnit unit and integration suites
composer test

# Oracle regression corpus
composer test:oracle

# Static analysis
composer analyse

# Coding standards
composer cs
composer cs:fix

# Full release-grade verification (analyse + cs + test + test:oracle)
composer verify

يمثل composer verify الحد الأدنى المطلوب لأي إصدار. إذا لم يجتز الاختبار، فالتغيير غير مكتمل.

نموذج المرجع

يتبع Greph نموذج تحقق قائمًا على المرجع. تُشغّل ثلاثة أوامر لكل سيناريو:

  1. المرجع: grep أو ripgrep أو ast-grep، مع التقاط المخرجات استنادًا إلى مجموعة السيناريوهات.
  2. الناتج الفعلي: Greph، مع التقاط المخرجات استنادًا إلى المجموعة نفسها.
  3. أداة المقارنة: مقارنة منظّمة تتحقق من التطابق سطرًا بسطر أو من التكافؤ الدلالي.

إذا لم يتفق Greph مع المرجع، فهذا يعني أن Greph غير صحيح. وإذا اختلف grep وrg، يسجّل السيناريو هذا الخلاف ضمن oracle_disagreement، ويحدد الأداة التي يتبعها Greph في greph_follows، ويضبط المقارنة مع الأداة الأخرى على skip. وكلا الاتجاهين وارد في المجموعة.

تُقارن سيناريوهات النص مع grep وrg، بينما تُقارن سيناريوهات AST وإعادة الكتابة مع sg. تُلتقط مخرجات المرجع مرة واحدة وتُحفظ ضمن مجلد oracle/ الخاص بكل سيناريو، لذا لا يحتاج التشغيل المعتاد إلا إلى PHP؛ ولا تُحتاج الأدوات الخارجية إلا لالتقاط مخرجات المرجع أو تحديثها.

يوجد التنفيذ في tests/Oracle/، والسيناريوهات في scenarios/text/ وscenarios/ast/ وscenarios/rewrite/ وscenarios/edge/.

بنية السيناريو

كل سيناريو مجلد مستقل ومتكامل:

الكود
scenarios/text/literal-simple/
├── scenario.json     # name, category, pattern, flags, path
├── setup/            # corpus to search through
├── oracle/           # captured oracle output (grep.txt, rg.txt, rg.json, ...)
├── actual/           # captured greph output (generated, git-ignored)
└── reports/          # comparison results (generated, git-ignored)

يحدد scenario.json النمط والرايات ومسار البحث. ويضبط كائن expectations اختياري وضع المقارنة لكل مرجع (exact أو semantic أو skip)؛ وفي غيابه، تُقارن سيناريوهات النص كلًا من grep وrg بدقة، ويُقارن rg JSON دلاليًا، بينما تُقارن سيناريوهات AST وإعادة الكتابة مع sg.

تشغيل سيناريو واحد

يحتوي المستودع على مجموعة صغيرة من أدوات CLI للعمل على سيناريوهات منفردة. وهي أدوات تطوير وليست نقاط دخول وقت التشغيل: توجد إلى جانب الملفات التنفيذية وقت التشغيل في bin/، لكنها غير مشمولة في حزمة Composer. تتلقى كل أداة اسم السيناريو نسبةً إلى scenarios/.

سطر الأوامر
# Capture oracle output for a scenario (needs grep and rg, or sg)
./bin/oracle text/literal-simple

# Run greph against a scenario, capture its output
./bin/actual text/literal-simple

# Diff oracle vs actual
./bin/compare text/literal-simple

# Full pipeline: oracle (only if missing) -> actual -> compare
./bin/test-scenario text/literal-simple

# Recapture the oracle output first
./bin/test-scenario text/literal-simple --refresh

تشغيل مجموعة اختبارات التراجع كاملة

سطر الأوامر
# All scenarios (the same as composer test:oracle)
./bin/test-regression

# Filter by category
./bin/test-regression --category text
./bin/test-regression --category ast
./bin/test-regression --category rewrite
./bin/test-regression --category edge

# Print only failures and the summary
./bin/test-regression --fast

# Recapture every oracle before comparing
./bin/test-regression --refresh

تُشغّل السيناريوهات دائمًا واحدًا تلو الآخر. يُقبل --jobs N ويُطبع في سطر الملخص، لكنه لا يشغّل أي شيء بالتوازي (#7). وفي النسخة المستنسخة حديثًا، يفشل text/no-ignore وtext/explicit-file-input لأن ملفات التجهيزات في setup/vendor/ غير محفوظة في المستودع (#6).

مجموعة اختبارات التراجع هي معيار قبول السلوك الجديد. يتطلب أي راية جديدة أو حالة طرفية جديدة أو إصلاح لخلل جديد سيناريو يحدد السلوك المتوقع بالاستناد إلى مرجع.

إعداد تقارير الامتثال

سطر الأوامر
./bin/verify-compliance

لا يشغّل verify-compliance أي شيء بنفسه. بل يقرأ ملفات المرجع والنتائج الفعلية والتقارير التي خلّفها آخر تشغيل للسيناريو، ثم يطبع السيناريوهات الناجحة والفاشلة وتلك التي لا يتوفر لها تقرير بعد. شغّل ./bin/test-regression أولًا. يكتب --output report.json التقرير أيضًا في JSON. هذا هو الأمر المناسب لمعرفة ما إذا كان الفرع الحالي جاهزًا للإصدار.

سير عمل التطوير القائم على الاختبارات

عند إضافة ميزة:

  1. اكتب مجلد سيناريو يتضمن مجموعة الاختبارات والرايات التي تختبر السلوك الجديد.
  2. شغّل ./bin/oracle <scenario> لالتقاط مخرجات الأداة المعتمدة.
  3. نفّذ الميزة في src/.
  4. شغّل ./bin/test-scenario <scenario> للتحقق من تطابق Greph مع المرجع.
  5. شغّل ./bin/test-regression --fast للتأكد من عدم تراجع أي شيء آخر.
  6. شغّل composer verify قبل الإيداع.

عند إصلاح خلل:

  1. التقط المدخل الذي يسبب الفشل كسيناريو.
  2. تحقق من أن المرجع ينتج المخرجات المتوقعة.
  3. تحقق من أن Greph لا ينتجها.
  4. أصلح الخلل.
  5. تحقق من أن Greph يطابق المرجع الآن.
  6. شغّل composer verify.

يبقى السيناريو في مجموعة الاختبارات دائمًا، لذا لا يمكن أن يعود الخلل دون أن يفشل composer test:oracle (وcomposer verify).