أنت تريد اختبارات واجهة برمجة التطبيقات (API) التي تُقرأ كاللغة الإنجليزية العادية، وتعيش في Git بجانب التعليمات البرمجية الخاصة بك، وتعمل في أي مسار تكامل مستمر (CI). كاراتيه (Karate) مصمم خصيصًا لذلك. يستخدم لغة خاصة بالمجال (DSL) حتى تكتب الاختبارات كخطوات Given / When / Then بدلاً من طرق Java. يشرح هذا الدليل ماهية كاراتيه، وكيف تعمل ملفات ميزاته (feature files)، وعينة قابلة للتشغيل.
ما هو كاراتيه
كاراتيه (Karate) هو إطار عمل مفتوح المصدر لأتمتة اختبارات واجهة برمجة التطبيقات (API) يعتمد على Java. يمكنك وصف كل اختبار كسيناريو في ملف .feature باستخدام Gherkin، وهو نفس هيكل Given/When/Then الذي يأتي من تطوير السلوك المدفوع (Behavior-Driven Development). الفرق عن أدوات مثل Cucumber هو أنك لا تكتب كود ربط (glue code) لتعريف الخطوات. كاراتيه يأتي بخطوات HTTP والتأكيدات ومعالجة JSON مدمجة، لذا فإن اختبار واجهة برمجة تطبيقات يعمل لا يحتاج إلى Java على الإطلاق.

يضم المشروع أكثر من مجرد اختبار واجهة برمجة التطبيقات (API). يتضمن المستودع وحدات للمحاكاة (mocks)، واختبار الأداء (عبر Gatling)، وأتمتة واجهة المستخدم (UI). بالنسبة لهذا الدليل، ينصب التركيز على جوهر اختبار واجهة برمجة التطبيقات، وهو ما تبدأ به معظم الفرق أولاً.
نظرًا لأن الاختبارات هي ملفات نصية عادية، فإنها تتوافق جيدًا مع أنظمة التحكم بالإصدار. يوضح فرق طلب السحب (pull request diff) بالضبط أي تأكيد قد تغير. وهذا يتناسب بشكل جيد مع مراجعة الكود ومع سير عمل يعتمد على الكود ومدمج مع Git.
إذا كنت جديدًا على نمط Given/When/Then، فإن مقدمتنا حول تطوير السلوك المدفوع تشرح من أين يأتي ولماذا تستخدمه الفرق.
كيف يعمل: ملفات الميزات و karate-config.js
يبدأ اختبار كاراتيه بملف ميزة (feature file). يحتوي كل ملف على كتلة Feature: واحدة وكتلة Scenario: واحدة أو أكثر. داخل السيناريو، تقوم بإعداد الطلب باستخدام Given، ثم تنفذه باستخدام When، وتؤكد النتيجة باستخدام Then.
إليك الهيكل الذي يعرضه دليل البدء السريع الخاص بكاراتيه:
Feature: واجهة برمجة تطبيقات المستخدم
Scenario: سرد جميع المستخدمين
Given url 'https://jsonplaceholder.typicode.com'
And path 'users'
When method get
Then status 200
And match response == '#[10]'
اقرأه من الأعلى إلى الأسفل. url يحدد العنوان الأساسي. path يلحق المورد. method get يرسل الطلب. status 200 يتحقق من رمز HTTP. السطر الأخير يؤكد أن الاستجابة عبارة عن مصفوفة JSON تحتوي على 10 عناصر بالضبط. #[10] هو علامة كاراتيه، وليس JavaScript. المزيد عن هذه العلامات في قسم التأكيدات.
تعد Gherkin هنا قياسية بنمط Given/When/Then. إذا كنت تريد نظرة أعمق على هذا النحو بحد ذاته، فراجع دليلنا إلى Gherkin لتطوير السلوك المدفوع واختبار واجهة برمجة التطبيقات.
تحتاج معظم المشاريع إلى قيم خاصة بالبيئة: عنوان URL أساسي للتطوير، رمز مرحلي، نقطة نهاية للإنتاج. يتعامل كاراتيه مع هذا بملف واحد يسمى karate-config.js. يتم تشغيله مرة واحدة قبل اختباراتك ويعيد كائن تهيئة يمكن لكل سيناريو قراءته.
function fn() {
var env = karate.env || 'dev';
var config = {
baseUrl: 'https://jsonplaceholder.typicode.com'
};
if (env === 'qa') {
config.baseUrl = 'https://qa.example.com';
}
return config;
}
يأتي karate.env من خاصية نظام تمررها عند التشغيل. قم بتبديل البيئات دون لمس ملف ميزة واحد. في السيناريو، ستكتب Given url baseUrl بدلاً من ترميز العنوان بشكل مباشر.
سيناريو عينة
لنكتب شيئًا يتضمن نص طلب. يقوم هذا السيناريو بإنشاء مستخدم، والتحقق من حالته، والتحقق من صحة شكل الاستجابة.
Feature: إنشاء مستخدم
Background:
* url baseUrl
Scenario: إنشاء مستخدم جديد يعيد 201
Given path 'users'
And request { name: 'Ada', job: 'engineer' }
When method post
Then status 201
And match response.name == 'Ada'
And match response.id == '#string'
بعض الأمور التي يجب ملاحظتها. كتلة Background: تُشغل قبل كل سيناريو في الملف، لذا يمكنك تعيين عنوان URL الأساسي مرة واحدة. * هي خطوة أحرف البدل؛ يتعامل كاراتيه مع * بنفس طريقة Given، When، أو Then، مما يتيح لك كتابة خطوات الإعداد دون القلق بشأن القواعد النحوية. تأخذ الكلمة المفتاحية request حمولة JSON مباشرة. لا يوجد مُسرِّل (serializer)، ولا كائنات POJO. و#string هي أداة مطابقة غامضة (fuzzy matcher) تؤكد أن حقل id موجود وهو سلسلة نصية، دون ربطه بقيمة محددة.
التأكيدات ومطابقة JSON
التأكيدات هي حيث يثبت كاراتيه جدارته. الكلمة المفتاحية الأساسية هي match. إنها تقارن قيمة فعلية بقيمة متوقعة وتفشل الاختبار عند أي عدم تطابق.
المطابقة التامة تتحقق من المساواة:
And match response == { id: '#number', name: 'Ada', job: 'engineer' }
الرموز المميزة #number و#string و#boolean و#uuid هي أدوات مطابقة غامضة (fuzzy matchers). إنها تؤكد النوع والوجود دون المطالبة بقيمة حرفية، مما يحافظ على استقرار الاختبارات عندما يعيد الخادم معرفات أو طوابع زمنية مولدة.
عندما تهتم فقط بمجموعة فرعية من الحقول، استخدم contains:
And match response contains { name: 'Ada' }
يمر هذا الاختبار طالما أن name يساوي Ada، حتى لو كانت الاستجابة تحتوي على عشرة حقول أخرى. يدعم كاراتيه أيضًا !contains وcontains only وcontains any وcontains deep للتحكم الدقيق في المطابقة الجزئية.
يمكنك التحقق من صحة المصفوفات أيضًا. match response == '#[10]' يؤكد وجود مصفوفة بطول 10. يمكنك تطبيق مخطط على كل عنصر باستخدام each:
And match each response == { id: '#number', name: '#string' }
يتحقق هذا السطر الواحد من أن كل كائن في المصفوفة يحتوي على id رقمي وname نصي. هذا النوع من التحقق من الشكل سيستغرق حلقة وعدة تأكيدات في إطار عمل اختبار للأغراض العامة. إذا كنت تريد صورة أوسع حول التحقق من صحة الاستجابات، فإن دليلنا العملي لتأكيدات واجهة برمجة التطبيقات يغطي الأنماط عبر الأدوات.
الاختبار القائم على البيانات والتكامل المستمر (CI)
تقوم مجموعات الاختبار الحقيقية بتشغيل نفس المنطق مقابل العديد من المدخلات. يتعامل كاراتيه مع هذا باستخدام Scenario Outline وجدول Examples. يتم ملء العناصر النائبة الموجودة بين الأقواس الزاوية من كل صف.
Scenario Outline: إنشاء مستخدمين من جدول
Given url baseUrl
And path 'users'
And request { name: '<name>', job: '<job>' }
When method post
Then status 201
And match response.name == '<name>'
Examples:
| name | job |
| Ada | engineer |
| Grace | scientist |
| Alan | analyst |
يقوم ذلك بتشغيل السيناريو ثلاث مرات، مرة واحدة لكل صف. يمكنك أيضًا قراءة الصفوف من ملف خارجي بدلاً من جدول مضمن، مما يبقي مجموعات البيانات الكبيرة خارج ملفات ميزاتك:
Examples:
| read('classpath:test-data/users.json') |
يقرأ كاراتيه ملفات JSON و CSV بهذه الطريقة، لذلك يمكن أن تعيش بيانات اختبارك حيثما يفضل فريقك إدارتها.
بالنسبة للتكامل المستمر (CI)، لديك مساران. في مشروع Maven أو Gradle، يعمل كاراتيه عبر JUnit 5. يمكنك إضافة تبعية karate-junit5 وتوجيه مُشغِّل إلى ملفات الميزات الخاصة بك، بحيث يقوم mvn test بتنفيذها مثل أي اختبار وحدة آخر. وهذا يعني أن خطوة CI الحالية لديك لا تحتاج إلى أدوات خاصة.
المسار الثاني هو ملف JAR المستقل، والذي لا يحتاج إلى أداة بناء. قم بتنزيل karate.jar من إصدارات المشروع وقم بتشغيل ملفات الميزات مباشرة. لاحظ أن ملف JAR يتطلب إصدار Java حديثًا، لذا تحقق من ملاحظات الإصدار للحد الأدنى المطلوب.
java -jar karate.jar src/test/java/features
يمكنك التصفية حسب العلامة (tag)، والتشغيل بالتوازي، واختيار دليل الإخراج:
java -jar karate.jar --tags @smoke --threads 4 --output reports src/test/java/features
مرر بيئة باستخدام خاصية نظام، والتي تتدفق إلى karate.env داخل karate-config.js:
java -jar karate.jar -Dkarate.env=qa src/test/java/features
يكتب كاراتيه تقرير HTML إلى دليل الإخراج بعد كل تشغيل، مما يجعل فحص الفشل سهلاً في مخرجات مسار العمل. للحصول على صورة أوسع للتكامل المستمر (CI)، تعرف على كيفية أتمتة اختبارات واجهة برمجة التطبيقات في CI/CD.
نقاط القوة والمقايضات
يتمتع كاراتيه بنقاط قوة واضحة. تُقرأ الاختبارات بشكل قريب من اللغة الإنجليزية العادية، مما يقلل الحاجز أمام الأشخاص غير المتقنين للغة Java. تزيل مطابقة JSON المدمجة، بما في ذلك المطابقات الغامضة (fuzzy matchers) وeach، الكثير من التعليمات البرمجية المتكررة للتأكيدات. كل شيء موجود في ملفات نصية تحت Git، لذا يمكن مراجعة الاختبارات ومقارنتها (diff) مثل الكود المصدري. ويغطي أكثر من مجرد HTTP، لذلك يمكن للفريق إضافة محاكاة (mocks) أو اختبارات أداء لاحقًا دون الحاجة إلى تبديل الأدوات.
المقايضات حقيقية أيضًا. يعمل كاراتيه على JVM، لذا تحتاج إلى تثبيت Java ومستوى راحة مع نظام JVM البيئي لأي شيء يتجاوز الأساسيات. اللغة الخاصة بالمجال (DSL) هي شيء منفصل يجب تعلمه؛ فالصياغة سهلة القراءة ولكن كتابة المطابقات الصحيحة وأنماط إعادة الاستخدام تتطلب ممارسة. غالبًا ما تدفعك المنطق القابل لإعادة الاستخدام والمساعدات المخصصة والإعدادات المعقدة نحو وظائف JavaScript أو التفاعل مع Java. ونظرًا لأن الاختبارات هي تعليمات برمجية، فإن غير المطورين في الفريق لا يمكنهم عادةً تأليفها أو تعديلها دون مساعدة.
لا شيء من ذلك يُعد انتقادًا. إنه وصف لإطار عمل يعتمد على الكود أولاً. السؤال هو ما إذا كان هذا الوصف يتناسب مع كيفية عمل فريقك.
كاراتيه مقابل نهج بدون كود (Apidog)
كاراتيه يعتمد على الكود ومتوافق أصلاً مع Git. تكتب ملفات الميزات (feature files)، وتلتزم بها (commit)، وتشغلها من أداة بناء أو ملف JAR. هذا يناسب المهندسين الذين يرغبون في الاحتفاظ بالاختبارات في نظام التحكم بالإصدار بجانب التطبيق والذين يشعرون بالراحة مع بيئة JVM.
Apidog يتخذ مسارًا مرئيًا وخاليًا من الكود لتحقيق نفس الهدف. تقوم ببناء سيناريوهات الاختبار في واجهة المستخدم، وربط الطلبات، وإضافة التأكيدات بالنقر بدلاً من كتابة لغة خاصة بالمجال (DSL). نظرًا لأن دورة حياة API بأكملها (التصميم، التصحيح، المحاكاة، التوثيق) تعيش في مكان واحد، يمكن للاختبارات إعادة استخدام نقاط النهاية والمخططات التي قمت بتعريفها بالفعل. هذا يقلل الحاجز أمام مهندسي ضمان الجودة (QA) وأصحاب المنتجات الذين لا يرغبون في إدارة مشروع Java.

مجموعات الاختبار المرئية ليست محصورة في واجهة المستخدم. يقوم Apidog بتشغيلها بدون واجهة رسومية (headless) في التكامل المستمر (CI) عبر واجهة سطر الأوامر (CLI) الخاصة بـ Apidog، لذا لا تزال مجموعة الاختبار الخالية من الكود تتناسب مع مسار عمل مؤتمت. يمكنك تثبيته باستخدام Node:
npm install -g apidog-cli
ثم قم بتشغيل سيناريو أو مجموعة اختبار محفوظة باستخدام المعرف (ID)، مشيرًا إلى بيئة واختيار تنسيقات التقارير:
apidog run --access-token "$APIDOG_ACCESS_TOKEN" -t <scenarioOrSuiteId> -e <environmentId> -r cli,html,junit
العلامة -t تستهدف سيناريو أو مجلد أو مجموعة اختبار؛ -e تختار البيئة؛ -r تختار مُقرِّرًا واحدًا أو أكثر (cli، html، json، junit). لعمليات التشغيل القائمة على البيانات، تأخذ -d (أو --iteration-data) مسار ملف بيانات أو معرف بيانات اختبار. واجهة سطر الأوامر (CLI) تعمل بدون واجهة رسومية (headless) وتعمل على أي خطوة تكامل مستمر يمكنها تشغيل Node. إنها تشغل سيناريوهات Apidog المحفوظة لديك؛ وليست مُرسِل طلبات تفاعليًا أو مُولِّد حمل. شاهد جولة كاملة في واجهة سطر أوامر Apidog للتكامل المستمر والتسليم المستمر، ومقارنة جنبًا إلى جنب مع مُشغّل آخر في واجهة سطر أوامر Apidog مقابل نيومان.
ينتج كلا النهجين اختبارات واجهة برمجة تطبيقات مؤتمتة تعمل بدون واجهة رسومية (headless) في التكامل المستمر (CI). يكمن الاختلاف في أسلوب التأليف: كاراتيه يريد منك كتابة لغة خاصة بالمجال (DSL) في Git؛ بينما يريد Apidog منك النقر في واجهة مستخدم تقوم أيضًا بالتصدير إلى مسار العمل.
كيف تختار
اختر كاراتيه عندما يكون فريقك يعتمد بشكل كبير على المطورين، ويشعر بالراحة مع JVM، ويريد اختبارات يتم التحكم بإصدارها كتعليمات برمجية بجانب التطبيق. تؤتي ملفات الميزات النصية العادية ومطابقة JSON المدمجة ثمارها عندما يمتلك المهندسون مجموعة الاختبار من البداية إلى النهاية.
اختر أداة خالية من الكود مثل Apidog عندما يشمل المؤلفون مهندسي ضمان الجودة (QA) وأشخاص المنتجات، وعندما تريد ربط الاختبارات بسير عمل تصميم وتوثيق موجود، أو عندما تفضل عدم صيانة بناء Java لتشغيل فحوصات واجهة برمجة التطبيقات. لا يزال بإمكانك الحصول على تغطية التكامل المستمر (CI) عبر واجهة سطر الأوامر (CLI).
تستخدم بعض الفرق كلا الأمرين: كاراتيه لمجموعات اختبار الانحدار الشاملة والمملوكة للكود، وأداة مرئية لتغطية واسعة وسريعة يمكن لغير المطورين توسيعها. إذا كنت لا تزال توازن الخيارات، فإن نظرتنا العامة حول كيفية اختيار إطار عمل لأتمتة اختبار واجهة برمجة التطبيقات تحدد معايير القرار.
الأسئلة الشائعة
هل أحتاج إلى معرفة Java لاستخدام كاراتيه؟ لا، ليس لكتابة اختبارات واجهة برمجة التطبيقات الأساسية. تستخدم ملفات الميزات (feature files) لغة Gherkin الخاصة بالمجال (DSL)، ويأتي كاراتيه بخطوات HTTP والتأكيدات مدمجة. ستحتاج إلى تثبيت Java لتشغيل الاختبارات، وبعض المعرفة بـ Java أو JavaScript تساعد بمجرد أن تحتاج إلى مساعدات مخصصة أو إعادة استخدام معقدة.
كيف يختلف كاراتيه عن Cucumber؟ كلاهما يستخدم بناء جملة Given/When/Then من Gherkin. مع Cucumber، تكتب كود تعريف الخطوات (step-definition code) لدعم كل خطوة. كاراتيه يوفر خطوات اختبار واجهة برمجة التطبيقات لك، لذلك لا يوجد كود ربط (glue code) للحفاظ عليه لاختبارات HTTP القياسية.
هل يمكن تشغيل كاراتيه بدون Maven أو Gradle؟ نعم. قم بتنزيل ملف karate.jar المستقل من إصدارات المشروع وقم بتشغيل ملفات الميزات باستخدام java -jar karate.jar <path>. إنه يدعم العلامات (tags)، والخيوط المتوازية (parallel threads)، ودليل إخراج مخصص بدون أي أداة بناء.
ماذا تعني الصيغة #string أو #[10]؟ هذه هي المطابقات الغامضة (fuzzy matchers) في كاراتيه. تؤكد #string أن الحقل هو سلسلة نصية بأي قيمة، و#number أنه رقم، و#[10] تؤكد أن مصفوفة JSON بطول 10. تتيح لك التحقق من شكل الاستجابة دون ترميز القيم المولدة بشكل ثابت.
هل يمكن لاختبارات واجهة برمجة التطبيقات الخالية من الكود أن تعمل في التكامل المستمر (CI)؟ نعم. تقوم أداة مرئية مثل Apidog بتصدير السيناريوهات المحفوظة إلى واجهة سطر الأوامر (CLI) الخاصة بـ Apidog، وهي تعمل بدون واجهة رسومية (headless) وتعمل على أي خطوة CI باستخدام Node. لذا يمكنك تأليف الاختبارات في واجهة المستخدم ولا يزال بإمكانك الحصول على تشغيل مسارات عمل مؤتمتة.
