تخطَّ إلى المحتوى

تصحيح اختبار فاشل مع وكيل

يبيّن هذا الدليل كيف تجعل وكيلًا يستخدم المصحّح لفشل تعجز عبارات الطباعة عن تفسيره.

تقود أداة 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. نتيجة أداة تملأ نافذة السياق تنهي التشغيل الذي كانت تساعده.