رمز الحالة الأخضر قد يخدع. نقطة نهاية POST /orders الخاصة بك تُرجع 201 Created، ويبدو نص الاستجابة مثاليًا، وينجح اختبارك. ولكن هل وصل الصف فعلاً إلى قاعدة البيانات بالحالة الصحيحة؟ هل نقص عدد المخزون؟ الاختبار الذي يقرأ استجابة HTTP فقط يتحقق مما قالته واجهة برمجة التطبيقات، وليس مما فعله النظام. لسد هذه الفجوة، يجب عليك النظر إلى قاعدة البيانات نفسها.
هنا تكمن قيمة استعلامات قاعدة البيانات داخل سيناريو الاختبار. تقوم بتهيئة حالة معروفة قبل الطلب، ثم تُطلق الطلب، وبعد ذلك تستعلم الجدول لتأكيد الحقيقة على القرص. يمتلك Apidog هذه الميزة مدمجة من خلال اتصالات قاعدة البيانات ومعالج عمليات قاعدة البيانات (Database Operation processor)، لذا يمكنك تشغيل أوامر SQL أو NoSQL كخطوات في نفس السيناريو الذي يشغل مكالمات HTTP الخاصة بك، بدون الحاجة إلى أي برمجة نصية خارجية. إذا كنت جديدًا في بناء السيناريوهات، فإن الدليل حول كيفية كتابة سيناريو اختبار باستخدام Apidog يغطي الأساسيات على مستوى الطلب التي يعتمد عليها هذا المقال. لتحديث معلوماتك حول كيفية نمذجة المخازن العلائقية لهذه البيانات، فإن نظرة عامة على جانب الخادم من MDN هي مقدمة ممتازة.
ما الذي توفره لك عمليات قاعدة البيانات في الاختبار
اختبار واجهة برمجة التطبيقات الذي لا يلامس قاعدة البيانات هو صندوق أسود. إنه يثق بالاستجابة. في معظم الأحيان يكون هذا جيدًا، ولكن الأخطاء المثيرة للاهتمام تكمن في الفجوة بين ما تُرجعه واجهة برمجة التطبيقات وما تحتفظ به: حقل حالة لا يتغير أبدًا، مفتاح أجنبي يشير إلى لا شيء، حذف ناعم (soft-delete) يتحول إلى حذف قوي (hard-delete).
تتيح لك خطوات قاعدة البيانات القيام بثلاثة أمور لا يستطيع اختبار HTTP البحت القيام بها:
- تهيئة حالة بداية دقيقة حتى لا يكون الاختبار تحت رحمة البيانات المتبقية.
- التأكيد على الحقيقة الأساسية بقراءة الصف الذي تدعي واجهة برمجة التطبيقات أنها كتبته.
- استخراج قيمة حقيقية من قاعدة البيانات وتغذية الطلب التالي بها، بحيث يستخدم اختبارك معرفات (IDs) قام الخادم بإنشائها فعليًا بدلاً من التخمينات.
يقسم Apidog الميزة إلى قسمين. أولاً، تقوم بإنشاء اتصال قابل لإعادة الاستخدام ضمن الإعدادات (Settings) > اتصالات قاعدة البيانات (Database Connections). ثم تقوم بإرفاق خطوة عملية قاعدة البيانات (Database Operation) بطلب كمعالج مسبق (Pre Processor) (يعمل قبل الطلب) أو معالج لاحق (Post Processor) (يعمل بعده). اتصال واحد، يُعاد استخدامه عبر كل سيناريو في المشروع.
ملاحظة حول التغطية قبل التخطيط بناءً عليها. تعمل MySQL وSQL Server (2014 والأحدث) وPostgreSQL وOracle على الخطة المجانية. أما ClickHouse وMongoDB وRedis فهي مدفوعة. توضح وثائق MongoDB ذلك بصراحة: الاتصال بـ MongoDB هو ميزة مدفوعة. وينطبق الشيء نفسه على Redis. لذا فإن الشرح العملي لـ MySQL أدناه يعمل على الطبقة المجانية؛ بينما تحتاج أقسام Mongo وRedis إلى خطة مدفوعة.
الخطوة 1: إنشاء اتصال قاعدة بيانات
افتح الإعدادات (Settings) > اتصالات قاعدة البيانات (Database Connections) وانقر على + جديد في الزاوية العلوية اليمنى. اختر نوع قاعدة البيانات الخاصة بك، ثم املأ حقول الاتصال:
- المضيف (Host) (على سبيل المثال
db.staging.internalأو127.0.0.1) - المنفذ (Port) (
3306لـ MySQL) - اسم المستخدم (Username) وكلمة المرور (Password)
- اسم قاعدة البيانات (Database Name) (على سبيل المثال
shop)

إذا كانت قاعدة بياناتك تقع خلف حصن (bastion)، فقم بتوسيع قسم نفق SSH (SSH Tunnel) وأضف تفاصيل مضيف القفز (jump-host). تعرض MySQL أيضًا وضع SSL بأربعة خيارات: Prefer (الافتراضي، الذي يحاول SSL ثم يعود للخلف)، Require (يتطلب)، Verify CA (التحقق من المرجع المصدق)، وVerify Full (التحقق الكامل). اختر الخيار الأكثر صرامة الذي يدعمه خادمك. ثم انقر على حفظ (Save).
نقطتان هامتان في الاتصال ستوفران عليك فترة ما بعد الظهيرة من الحيرة:
- مصادقة MySQL 8. قد يرفض المكون الإضافي الافتراضي
caching_sha2_passwordالاتصال. إذا واجهت خطأ في المصادقة، قم بتبديل المستخدم باستخدامALTER USER 'tester'@'%' IDENTIFIED WITH mysql_native_password BY '...';وحاول مرة أخرى. يغطي دليل MySQL المرجعي الفرق بين المكونات الإضافية بتعمق. - بيانات الاعتماد محلية. يتم تخزين تفاصيل الاتصال على جهازك الخاص ولا تتم مزامنتها مع السحابة. يقوم كل عضو في الفريق بتكوين الاتصال بنفسه. إذا كنت تنسق فريقًا، فإن الملاحظات حول مشاركة إعدادات اتصال قاعدة البيانات تشرح سير العمل.
الخطوة 2: تهيئة البيانات باستخدام معالج مسبق (Pre Processor)
لنفترض أنك تختبر سير عمل إنشاء الطلبات. تريد أن يكون هناك عميل معروف موجود قبل أن تقوم بتقديم طلب، حتى لا يعتمد الاختبار على ما قد يكون موجودًا في الجدول.
افتح طلبك، ابحث عن المعالجات المسبقة (Pre Processors)، مرر مؤشر الفأرة فوق إضافة معالج قاعدة بيانات (Add Database Processor)، واختر عملية قاعدة بيانات (Database operation). سمّها شيئًا مثل seed customer، اختر اتصال MySQL الخاص بك، ثم تحت أدخل أمر SQL (Enter SQL Command) اكتب أمر إدخال. تستخدم المتغيرات الديناميكية بناء الجملة {{variable_name}}، بحيث يمكنك سحب القيم مباشرة من بيئتك:
INSERT INTO customers (id, email, status)
VALUES ({{customer_id}}, '{{customer_email}}', 'active')
ON DUPLICATE KEY UPDATE status = 'active';
الآن يتم تشغيل الطلب مقابل حالة مضمونة. العميل موجود، نشط، ولديه معرف تعرفه خطواتك اللاحقة بالفعل. تساعد التهيئة في المعالج المسبق على إبقاء كل اختبار مستقلًا بدلاً من الاعتماد على الآثار الجانبية لترتيب الاختبار.
الخطوة 3: التأكيد مقابل قاعدة البيانات باستخدام معالج لاحق (Post Processor)
هذا هو جوهر الأمر. يقوم طلبك بإنشاء طلب. بعد عودته، تستعلم جدول orders لتأكيد وجود الصف بالحالة الصحيحة.
أضف الطلب الذي يستدعي واجهة برمجة التطبيقات الخاصة بك:
POST /api/orders
Content-Type: application/json
{
"customer_id": {{customer_id}},
"items": [{ "sku": "APRON-01", "qty": 2 }]
}
افترض أن نص الاستجابة يحمل معرف الطلب الجديد، والذي تقوم بالتقاطه في متغير يسمى order_id باستخدام تأكيد استجابة عادي. الآن افتح المعالجات اللاحقة (Post Processors) لهذا الطلب. في وضع التصميم (DESIGN Mode) ستجدهم في علامة التبويب تشغيل (Run)؛ في وضع التصحيح (DEBUG Mode) ستجدهم في علامة التبويب الطلب (Request). مرر مؤشر الفأرة فوق إضافة معالج لاحق (Add PostProcessor)، اختر عملية قاعدة بيانات (Database operation)، سمّها verify order row، واختر اتصالك.
ضمن تكوين العملية (Configure Operation)، اختر العملية وأدخل SQL:
SELECT id, status, total_cents
FROM orders
WHERE id = {{order_id}};
تُرجع نتائج الاستعلام كمصفوفة من الكائنات، كائن واحد لكل صف. لسحب حقل واحد، افتح استخراج النتائج (اختياري) (Extract Results (Optional)) وأضف إدخال استخراج نتيجة إلى متغير (Extract Result To Variable). عيّن اسم متغير (Variable Name) مثل db_order_status وتعبير JSONPath (JSONPath Expression) الذي يعزل الحقل من الصف الأول:
$[0].status
انقر على إرسال (Send) وتحقق من الطرفية (Console) لرؤية النتيجة الخام والقيمة المستخرجة. الآن يحمل db_order_status ما هو موجود فعليًا على القرص. أضف تأكيدًا بأنه يساوي pending (أو أي قيمة يجب أن تحددها واجهة برمجة التطبيقات الخاصة بك)، ويتحقق اختبارك أخيرًا من الثبات، وليس مجرد صدى HTTP. إذا أعادت واجهة برمجة التطبيقات 201 ولكنها كتبت status = 'draft'، فهذه هي الخطوة التي تكشف ذلك.
الخطوة 4: استخراج قيمة من قاعدة البيانات واستخدامها في الخطوات اللاحقة
الاستخراج ليس فقط للتأكيدات. فغالبًا ما تحتوي قاعدة البيانات على قيمة لا تعيدها الاستجابة أبدًا، وتحتاج إليها للطلب التالي.
تخيل سير عمل حيث يؤدي إنشاء طلب إلى إنشاء fulfillment_ref داخلي على الخادم، يُكتب في الصف ولكن يُحذف من استجابة واجهة برمجة التطبيقات. طلبك التالي، GET /api/fulfillments/{ref}، يحتاج إليه. استعلم عنه في معالج لاحق (Post Processor):
SELECT fulfillment_ref
FROM orders
WHERE id = {{order_id}};
استخرجه باستخدام اسم المتغير (Variable Name) fulfillment_ref وتعبير JSONPath (JSONPath Expression) $[0].fulfillment_ref. نظرًا لأن Apidog يحدد نطاق هذا المتغير للبيئة، فإن طلبك التالي يشير فقط إلى {{fulfillment_ref}} في مساره أو نصه ويلتقط القيمة الحقيقية التي أنشأها الخادم. هذا هو نفس النمط الذي يُستخدم في ربط استجابات HTTP، والذي تم تغطيته في تمرير البيانات بين خطوات الاختبار وتنسيق اختبارات API وتمرير البيانات، باستثناء أن مصدر الحقيقة هو جدول بدلاً من نص JSON.
MongoDB و Redis: أنواع NoSQL
يعمل المعالج بنفس الطريقة لمخازن NoSQL، ولكن بواجهة تكوين مختلفة. كلاهما ميزتان مدفوعتان، لذا خطط لذلك. تحتوي وثائق Apidog على المرجع الكامل للحقول إذا احتجت إليه.
MongoDB
أضف خطوة عملية قاعدة بيانات (Database Operation) واختر MongoDB كنوع. بدلاً من SQL الخام، ستحصل على قائمة منسدلة نوع العملية (Operation Type) تحتوي على Find (بحث)، Insert (إدخال)، Update (تحديث)، Delete (حذف)، وتشغيل أمر قاعدة البيانات (Run Database Command). لأي عملية CRUD، يكون اسم المجموعة (Collection Name) إلزاميًا. يقبل حقل شرط الاستعلام (Query Condition) JSON:
{ "_id": "65486728456e79993a150f1c" }
يقوم Apidog بتحويل سلسلة معرف مطابقة إلى ObjectId تلقائيًا، لذا لا داعي لتغليفها بنفسك. عندما تحتاج إلى أنواع BSON، يتم دعم المساعدات ISODate(...) وObjectId(...) وNumberDecimal(...) وNumberLong(...)؛ توضح وثائق MongoDB كيفية تعيين كل منها لقيمة مخزنة. يقبل الاتصال إما سلسلة اتصال كاملة أو مكونات المضيف وبيانات الاعتماد الفردية.
ملاحظة صريحة: يوثق سير عمل MySQL استخراج JSONPath إلى متغير، لكن وثائق MongoDB و Redis لا تصف نفس آلية استخراج النتيجة إلى متغير (Extract Result To Variable). لذا اعتمد على عمليات Mongo لتهيئة الحالة وتأكيدها، ولا تفترض أن مسار الاستخراج بأسلوب SQL يعمل بشكل مطابق حتى تتحقق من ذلك في الطرفية (Console).
Redis
يتطلب اتصال Redis المضيف (Host) والمنفذ (Port) وكلمة المرور (Password) وفهرس قاعدة البيانات (Database Index). تستخدم العمليات المرئية قائمة منسدلة نوع العملية (Operation Type) تدعم GET (جلب)، SET (تعيين)، وDELETE (حذف). لقراءة جلسة مخبأة، اختر GET وعيّن المفتاح (Key) لشيء مثل user:session:123. لأي شيء لا تغطيه القائمة المنسدلة، تقوم علامة التبويب تشغيل أمر Redis (Run Redis Command) بتشغيل أي أمر صالح:
KEYS user:*
هذه هي الطريقة التي تؤكد بها إدخال ذاكرة تخزين مؤقت كان من المفترض أن تكتبه واجهة برمجة التطبيقات، أو مسح واحد قبل الاختبار لإثبات أن نقطة النهاية تعيد ملئه.
النماذج المتقدمة والقيود
بعض الأمور الجديرة بالمعرفة قبل بناء مجموعة كبيرة من الاختبارات:
- الحلقات (Loops). عند التكرار فوق الصفوف في خطوة ForEach، أشر إلى العنصر الحالي في الحلقة باستخدام
{{$.StepID.element.field}}، حيثStepIDهو الرقم الفعلي لخطوة الحلقة. مفيد للتأكيد على صف واحد لكل تكرار. - التفرع بناءً على قيمة قاعدة البيانات. استخرج حقل حالة، ثم وجه بقية السيناريو بناءً عليه. يتيح لك دمج قراءات قاعدة البيانات مع المنطق الشرطي في سيناريوهات اختبار API للاختبار أن يسلك مسارًا واحدًا عندما يكون الصف
مدفوعًا (paid)ومسارًا آخر عندما يكونمعلقًا (pending). - توجيه البيئة (Environment routing). المزيد عن هذا أدناه، ولكن النسخة المختصرة: حدد اتصالًا واحدًا لكل بيئة ويختار Apidog الاتصال الصحيح تلقائيًا.
- الإجراءات المخزنة (Stored procedures). لا تتعامل الواجهة المرئية مع العمليات المعقدة مثل الإجراءات المخزنة. حافظ على SQL في خطواتك بحيث تكون عبارات مباشرة.
- إعداد Oracle. يتطلب Oracle تثبيت عميل Oracle منفصل على جهازك قبل أن يتمكن من الاتصال على الإطلاق.
التعامل مع بيانات الاعتماد لكل بيئة
لا ترغب أبدًا في أن يصيب اختبار بيانات الإنتاج عن طريق الخطأ. حل Apidog هو اتصال قاعدة بيانات واحد لكل بيئة. تنشئ اتصال staging واتصال local، كل منهما بمضيفه وكلمة مروره الخاصة.
ثم تقوم بتبديل البيئات باستخدام القائمة المنسدلة في الزاوية العلوية اليمنى. يقوم Apidog تلقائيًا بتوجيه كل استعلام في السيناريو إلى الاتصال الذي يتطابق مع البيئة المحددة حاليًا. حدد staging وسيتم تشغيل SELECT الخاص بك على بيئة الاختبار (staging)؛ انتقل إلى local وستعمل نفس الخطوة بالضبط على قاعدة بيانات جهاز الكمبيوتر المحمول الخاص بك، دون أي تعديلات على SQL أو الخطوة. تختلف بيانات الاعتماد لكل بيئة دون أي إعادة تكوين يدوية أثناء التشغيل.
ولأن بيانات الاعتماد هذه موجودة محليًا ولا تتم مزامنتها، فإن هذا يحافظ أيضًا على كلمات مرور الإنتاج بعيدًا عن المشروع السحابي المشترك. يحتفظ كل مهندس بكلمات مروره الخاصة به.
أتمتة سير العمل باستخدام Apidog CLI
بمجرد أن ينجح السيناريو في التطبيق، قم بتشغيله بدون واجهة مستخدم (headless) في CI (الدمج المستمر) بحيث يقوم كل طلب سحب (pull request) بإعادة التحقق من قاعدة البيانات، وليس فقط عقد HTTP. قم بتثبيت واجهة سطر الأوامر (CLI) والمصادقة:
npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
ثم قم بتشغيل السيناريو الذي قمت ببنائه، بمعرفه (ID) الخاص به، مقابل بيئة مختارة:
apidog run --access-token $APIDOG_ACCESS_TOKEN -t <scenario_id> -e <env_id> -r cli
هنا -t هو معرف سيناريو الاختبار، -e هو معرف البيئة، و-r هو أداة الإبلاغ (reporter) (cli، html، أو junit؛ افصلها بفاصلة لعدة أنواع، مثل -r html,cli). أمر واحد يجب التخطيط له: تفاصيل اتصال قاعدة البيانات محلية، لذا يحتاج المشغل إلى التكوين المصدر (exported configuration) للوصول إلى قاعدة بياناتك من CI. إذا قمت بتغذية صفوف السيناريو من مجموعة بيانات، فإن الاختبار الموجه بالبيانات (data-driven testing) باستخدام Apidog CLI يوضح كيف يقوم كل صف بتشغيل نفس تأكيدات قاعدة البيانات، وجدولة اختبارات API باستخدام Apidog يغطي تشغيل هذا بوتيرة معينة بحيث يظهر تأكيد قاعدة بيانات فاشل كأي اختبار آخر.
الأسئلة الشائعة
ما هي قواعد البيانات المجانية والمدفوعة؟ تتوفر MySQL وSQL Server (2014 والأحدث) وPostgreSQL وOracle ضمن الخطة المجانية. أما ClickHouse وMongoDB وRedis فتحتاج إلى خطة مدفوعة. توضح وثائق MongoDB و Redis أن إمكانية الاتصال بهما هي ميزة مدفوعة، لذا تحقق من صفحة الأسعار قبل التخطيط لمجموعة NoSQL. قم بتنزيل Apidog لتجربة قواعد البيانات المجانية أولاً.
هل يمكنني استخدام قيمة من قاعدة البيانات في طلب لاحق؟ نعم. أضف معالجًا لاحقًا (Post Processor) مع عملية قاعدة بيانات، وقم بتشغيل SELECT، ثم استخدم "استخراج نتيجة إلى متغير" (Extract Result To Variable) مع اسم متغير (Variable Name) وتعبير JSONPath مثل $[0].fulfillment_ref لعزل الحقل من الصف الأول. قم بالإشارة إليه لاحقًا كـ {{variable_name}}. يتم تغطية نفس فكرة التسلسل لاستجابات HTTP في تمرير البيانات بين خطوات الاختبار.
هل يحصل أعضاء فريقي تلقائيًا على اتصالات قاعدة البيانات الخاصة بي؟ لا. يتم تخزين بيانات اعتماد الاتصال محليًا على كل عميل ولا تتم مزامنتها مع السحابة، لذا يقوم كل عضو في الفريق بتكوين الاتصال بنفسه. هذا مقصود: فهو يحافظ على كلمات مرور الإنتاج بعيدًا عن المشروع السحابي المشترك.
اتصال MySQL 8 الخاص بي يستمر في الفشل. لماذا؟ يقوم MySQL 8 بشكل افتراضي بتعيين المكون الإضافي للمصادقة caching_sha2_password، والذي يمكن أن يمنع الاتصال. قم بتبديل المستخدم إلى mysql_native_password باستخدام ALTER USER ... IDENTIFIED WITH mysql_native_password وأعد الاتصال.
هل يمكنني تشغيل الإجراءات المخزنة (stored procedures) أو منطق قاعدة البيانات المعقد؟ ليس من خلال الواجهة المرئية. إنها تتعامل مع عبارات SELECT و INSERT و UPDATE و DELETE القياسية، لكن العمليات المعقدة مثل الإجراءات المخزنة غير مدعومة. حافظ على خطوات الاختبار الخاصة بك في شكل عبارات مباشرة.
خلاصة
تحوّل استعلامات قاعدة البيانات اختبار API من "بدا أن الاستجابة صحيحة" إلى "البيانات صحيحة بالفعل". قم بتهيئة حالة معروفة في معالج مسبق (Pre Processor)، وتحقق من الصف المخزن في معالج لاحق (Post Processor)، واستخرج القيم التي تم إنشاؤها بواسطة الخادم لربطها بالطلب التالي، كل ذلك داخل سيناريو واحد. قم بإعداد اتصال لكل بيئة وستعمل نفس الخطوات بأمان على بيئة التطوير (staging) أو المحلية (local) دون تعديلات.
جربها مجانًا، لا يلزم وجود بطاقة ائتمان: قم بتنزيل Apidog، ووجه اتصال MySQL الخاص بك إلى قاعدة بيانات التطوير الخاصة بك، وأضف معالجًا لاحقًا واحدًا (Post Processor) يقرأ الصف الذي ينشئه طلبك التالي.
