تصحيح اختبار فاشل مع وكيل
يبيّن هذا الدليل كيف تجعل وكيلًا يستخدم المصحّح لفشل تعجز عبارات الطباعة عن تفسيره.
تقود أداة debug جلسة Debug Adapter Protocol حقيقية. يجيب الإطار المتوقف دفعة واحدة عن أسئلة تلك اللحظة كلها — كل متغير محلي، وكل مستدعٍ، وتعبير يُقيَّم في نطاق الإطار نفسه — بينما لا تجيب عبارة الطباعة إلا عن السؤال الذي خطر لك أن تسأله قبل التشغيل.
قبل أن تبدأ
قسم بعنوان “قبل أن تبدأ”تبقى الأداة معروضة ليتسنى للوكيل أن يسأل لماذا لا شيء صالح للاستخدام، بدل أن يخمّن. لا يبدأ المحوّل فعلًا إلا إذا تحقّق الشرطان معًا:
- علامة جذر في نسخة العمل،
- وحلّ مسار ثنائي المحوّل.
اطلب من الوكيل أن يفحص:
debug(op: "adapters")يجيب بما وجده، أو يشرح أن المحوّل يحتاج إلى الشقين معًا.
| اللغة | المحوّل | العلامة | التثبيت |
|---|---|---|---|
| Dart / Flutter | dart debug_adapter |
pubspec.yaml |
يأتي مع SDK — لا شيء يلزم |
| Python | python3 -m debugpy.adapter |
pyproject.toml، setup.py، requirements.txt |
pip install debugpy |
| Rust / C / C++ | lldb-dap |
Cargo.toml، CMakeLists.txt |
يأتي مع LLVM |
| Go | dlv dap |
go.mod |
go install github.com/go-delve/delve/cmd/dlv@latest |
ضع نقطة التوقف أولًا، ثم أطلق
قسم بعنوان “ضع نقطة التوقف أولًا، ثم أطلق”الترتيب مهم، والأداة تفرضه: يجوز وضع نقاط التوقف قبل أن توجد جلسة، لأن هذا هو التسلسل الذي يقتضيه البروتوكول.
اطلب من الوكيل شيئًا كهذا:
الدالة
computeفيbin/main.dartتعيد القيمة الخطأ. ضع نقطة توقف على سطر إسنادproduct، وأطلق البرنامج تحت المصحّح، وأخبرني ما قيمةaوbفعلًا.
سينفّذ تقريبًا:
debug(op: "breakpoints", file: "bin/main.dart", lines: [7])debug(op: "launch", program: "bin/main.dart")يبلّغ الإطلاق أين توقف:
Launched bin/main.dart on dart (session dart-1). Stopped: breakpoint. Use `stack` to see where.اقرأ الإطار
قسم بعنوان “اقرأ الإطار”debug(op: "stack")→ #1 compute (bin/main.dart:7:3) #2 main (bin/main.dart:2:18)ثم انزل إليه:
debug(op: "scopes", frame_id: 1)→ Locals (reference 12)
debug(op: "variables", reference: 12)→ a (int) = 6 b (int) = 7 product (int) = 42يبلّغ الكائن ذو الأبناء [expand: reference N]، ولا يفعل إلا حين يوجد خلفه شيء فعلًا، فلا يُعرَض توسيع يعجز الوكيل عن استخدامه.
ولكل ما لا يظهر كمتغير محلي:
debug(op: "evaluate", expression: "config.timeout.inSeconds", frame_id: 1)تقدّم خطوة بخطوة
قسم بعنوان “تقدّم خطوة بخطوة”| ما تريده | العملية |
|---|---|
| المتابعة حتى التوقف التالي | continue |
| السطر التالي، في الإطار نفسه | step_over |
| الدخول إلى الاستدعاء | step_in |
| الخروج إلى المستدعي | step_out |
| إيقاف برنامج قيد التشغيل | pause |
أرفق بما يعمل أصلًا
قسم بعنوان “أرفق بما يعمل أصلًا”لعملية عالقة، لا لعملية تبدأها أنت:
debug(op: "attach", port: 5858)الإنهاء
قسم بعنوان “الإنهاء”debug(op: "terminate")أنهِ الجلسة دائمًا. يملك محوّل التصحيح عملية متوقفة تحتفظ بما تحتفظ به تلك العملية — منفذ، وقفل، واتصال بقاعدة بيانات.
خرج محدود
قسم بعنوان “خرج محدود”توسيع variables على شبكة كائنات عميقة غير محدود بطبيعته — ودجت Flutter واحد يصل إلى شجرة العناصر كلها. يُحَدّ الأبناء في كل نطاق بـ 50، والقيم بـ 400 حرف، وإطارات المكدس بـ 30. نتيجة أداة تملأ نافذة السياق تنهي التشغيل الذي كانت تساعده.
انظر أيضًا
قسم بعنوان “انظر أيضًا”- ذكاء الشفرة: لماذا يجيب المصحّح والمُصرِّف والمُطابِق عن أسئلة مختلفة
- أدوات الوكيل المضمّنة: كل عملية
debugووسائطها - تشخيص وكيل: حين تكون المشكلة في الوكيل لا في الشفرة