ما أتمتة الاختبار؟

أتمتة الاختبار (Test Automation) هي استخدام البرمجيات لتنفيذ أنشطة الاختبار أو دعمها، كما يعرّفها مسرد ISTQB. وفي معظم الفرق تعني التنفيذ الآلي للاختبار: شيفرة تهيّئ موقفاً، وتشغّل المنتج عبر دالة أو واجهة API أو متصفح، وتقارن النتيجة الفعلية بنتيجة متوقعة مكتوبة مسبقاً، ثم تبلّغ بالنجاح أو الفشل دون أن يراقبها أحد. فحالة اختبار الانحدار اليدوية «يستطيع المستخدم المسجَّل تسجيل الدخول» تصبح نصاً برمجياً (Script) يعمل عند كل إيداع (Commit).

قدّم لك درس الأدوات الداعمة للاختبار فئاتِ الأدوات وقائمتَي ISTQB للفوائد والمخاطر. أما هذا الدرس فينظر إلى الداخل: مما يتكوّن الاختبار المؤتمت الواحد، وما الذي تقدّمه الأتمتة للفريق فعلياً، وما الذي يسوء بعد أن توجد النصوص البرمجية، ولماذا هذه النصوص برمجياتٌ تحتاج إلى صيانة.

لماذا يهم

كل إصدار يضيف فحوص انحدار جديدة، وإعادة تشغيلها كلها يدوياً تستغرق وقتاً أطول في كل مرة، فإما أن يتباطأ الفريق وإما أن يتوقف عن إعادة الفحص فتصل الانحدارات إلى المستخدمين. والأتمتة هي ما يُبقي سلوك الأمس مؤكَّداً بينما يبني الفريق ميزات اليوم. لكنها إذا نُفّذت بشكل سيئ كانت أسوأ من غيابها: فالحزمة الحمراء دائماً يتجاهلها الجميع، والحزمة الخضراء دائماً لأنها لا تفحص شيئاً تمنح ثقة لم يستحقها المنتج.

وحتى لو لم تبنِ إطار عمل قط، فالأتمتة تغيّر عملك اليومي: تقرأ نتائج التشغيل، وتقرر هل الاختبار الأحمر عيب في المنتج أم عيب في الاختبار نفسه أم مشكلة في البيئة، وتراجع النصوص البرمجية التي يكتبها زملاؤك.

مما يتكوّن الاختبار المؤتمت

للاختبار المؤتمت أجزاء حالة الاختبار اليدوية الجيدة نفسها، لكنها مكتوبة شيفرةً. فهو يهيّئ الشروط المسبقة (Arrange)، وينفّذ الخطوات (Act)، ويؤكّد بمقارنة النتائج الفعلية بالنتائج المتوقعة (Assert)، ثم ينظّف ما أحدثه ليبدأ الاختبار التالي من حالة معروفة. والتأكيد (Assertion) هو قلب الاختبار: فبلا نتيجة متوقعة دقيقة لا يثبت النص البرمجي إلا أن شيئاً لم ينهَر. ويسمّي بعض الممارسين الاختبار المؤتمت «فحصاً» (Check) للتشديد على أنه لا يتحقق إلا مما قرّره أحدٌ مسبقاً.

أدناه حالة تسجيل الدخول نفسها مكتوبةً اختبارَ متصفح بأداة Playwright، ولاختبارات Selenium WebDriver وCypress الشكل نفسه. ولا تحتاج الآن إلى فهم كل كلمة مفتاحية: اقرأ التعليقات والخطوات والتأكيد. والسطر مثل page.getByLabel('Email') محدِّد (Locator)، أي طريقة يجد بها الاختبار عنصراً في الصفحة، وهنا عبر تسميته الظاهرة. والنص البرمجي ليس إلا جزءاً واحداً مما يسمّيه منهج ISTQB المتقدم لهندسة أتمتة الاختبار «حل أتمتة الاختبار» (Test Automation Solution): النصوص البرمجية مع كل ما يلزم لتشغيلها والإبلاغ عن نتائجها. وكل جزء منه قابل للتعطّل:

  • النصوص البرمجية للاختبار: سلوك واحد في كل اختبار، باسم يذكر القاعدة التي يفحصها.
  • إطار عمل ومشغّل (Runner) يكتشف الاختبارات ويشغّلها ويسجّل نتيجة كل منها.
  • الواجهة التي يشغّلها الاختبار: دالة (مستوى الوحدة)، أو واجهة HTTP API، أو واجهة مستخدم. والمستويات الأدنى أسرع وأقل تعطّلاً، كما يبيّن درس هرم أتمتة الاختبار.
  • بيانات الاختبار والبيئة: الحسابات والمنتجات والإعدادات التي يحتاجها الاختبار، والنظام الذي يعمل عليه.
  • مُطلِق وتقرير: غالباً خط تكامل مستمر (CI pipeline) يشغّل الحزمة عند كل تغيير، ونتيجة يقرؤها أحد.
import { test, expect } from '@playwright/test';
import { testUser } from './test-data';

test('registered user can sign in', async ({ page }) => {
  // Arrange: start on the sign-in page with a known test account
  await page.goto('/login'); // resolved against baseURL in playwright.config.ts

  // Act: the steps of the manual test case
  await page.getByLabel('Email').fill(testUser.email);
  await page.getByLabel('Password').fill(testUser.password);
  await page.getByRole('button', { name: 'Sign in' }).click();

  // Assert: the expected result, decided before the test ran
  await expect(page.getByRole('heading', { name: 'My account' })).toBeVisible();

  // Clean up: nothing to undo, signing in changes no data
});

جرّبها: مختبِر REST API جرّبها: مولّد طلبات REST

ما تقدّمه الأتمتة للفريق

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

  • تغذية راجعة سريعة عن الانحدار: تعمل الحزمة عند كل تغيير، فيُبلَّغ عن الانحدار والمطوّر ما زال يتذكر الشيفرة.
  • مقارنة دقيقة ومتكررة: كل حقل في الاستجابة وكل إجمالي حتى آخر هللة، في كل تشغيل؛ أما الإنسان الذي يعيد الحالة للمرة العشرين فيبدأ بالقراءة السريعة.
  • التوسّع (Scale): الخطوات نفسها على مئات صفوف البيانات، وفي عدة متصفحات، وكل ليلة.
  • بوابة جودة: يستطيع الفحص المؤتمت في خط التكامل إيقاف بناء معطوب عند كل تغيير، قبل أن يصل إلى بيئة Staging، ودون انتظار أحد.
  • توثيق حي: اختبار اسمه «الطلبات بقيمة ⁦300.00⁩ ريال فأكثر توصيلها مجاني» يذكر قاعدة ويُظهر في كل تشغيل أنها ما زالت صحيحة.
  • وقت المختبِر: الساعات التي كانت تذهب في إعادة تنفيذ الحالات المكتوبة تذهب إلى الاختبار الاستكشافي وإلى تصميم اختبارات الميزات الجديدة.

جرّبها: مولّد سيناريوهات الانحدار جرّبها: مولّد حالات الاختبار

ما الذي يسوء بعد أن توجد النصوص البرمجية

مخاطر درس الأدوات الداعمة للاختبار تخص قرار الأتمتة: توقعات غير واقعية، وجهد مقدَّر بأقل من حقيقته، وأداة غير مناسبة. وبعد أن توجد الحزمة تظهر مجموعة ثانية، ومعظمها يأتي من النصوص البرمجية نفسها:

  • ثقة زائفة: تأكيدات أضعف من أن تفشل. فالاختبار الذي يتحقق فقط من اكتمال تحميل صفحة السلة يبقى أخضر والإجمالي فيها خاطئ.
  • الاختبارات المتذبذبة (Flaky Tests): تنجح وتفشل دون أي تغيير في المنتج أو في الاختبار نفسه، غالباً بسبب التوقيت أو بيانات اختبار مشتركة أو بيئة غير مستقرة. وبعد بضعة إنذارات كاذبة يتوقف الفريق عن قراءة النتائج الحمراء، فتمرّ الانحدارات الحقيقية معها.
  • نصوص هشّة: اختبارات مرتبطة بتفاصيل تتغير كثيراً، مثل اسم فئة CSS (class) أو موضع زر، تنكسر مع كل إعادة تصميم رغم أن السلوك لم يتغير.
  • حزم بطيئة: حين يستغرق التشغيل أطول مما يقبل الناس انتظاره، يدمجون التغييرات دونه وتضيع التغذية الراجعة السريعة.
  • اختبارات مُستهلَكة: الحزمة لا تعيد فحص إلا ما توقّعه أحد، فتجد الانحدارات ونادراً ما تجد عيوباً جديدة، ولا تحلّ محل الاختبار الاستكشافي.
  • مالك واحد: إذا لم يفهم إطار العمل إلا شخص واحد، توقفت الصيانة حين ينتقل ذلك الشخص إلى عمل آخر.
لكل فائدة من فوائد أتمتة الاختبار خطر يقابلها: الحزمة التي تُصان كبرمجيات تعطي تغذية راجعة سريعة ودقيقة عن الانحدار، والحزمة المهملة تعطي ضجيجاً أو ثقة زائفة.

الفائدة: حزمة تُصان كبرمجيات

تحت التحكم في الإصدارات، تُراجَع، ويُفرز كل فشل

التغذية الراجعة:
يُبلَّغ عن الانحدار والشيفرة ما زالت حاضرة في الذهن
المقارنة:
فحوص دقيقة بالطريقة نفسها في كل تشغيل
التشغيل الأخضر:
نجحت الفحوص المكتوبة
التشغيل الأحمر:
يُفرز: عيب في المنتج أو في الاختبار أو مشكلة في البيئة
تغيير في المنتج:
تعديل واحد في دالة مساعدة مشتركة
وقت المختبِر:
يتفرغ للاختبار الاستكشافي والاختبارات الجديدة

الخطر: حزمة متروكة بلا صيانة

سُجّلت مرة واحدة، ولا تُراجَع، والنتائج الحمراء مُهمَلة

التغذية الراجعة:
بطيئة إلى حد أن الناس يدمجون دونها
المقارنة:
نتيجة متوقعة خاطئة تتكرر بالأمانة نفسها
التشغيل الأخضر:
تأكيدات ضعيفة: أخضر والإجمالي خاطئ
التشغيل الأحمر:
حالات الفشل المتذبذبة تعلّم الفريق تجاهل الأحمر
تغيير في المنتج:
الإصلاح نفسه في عشرات النصوص المنسوخة
وقت المختبِر:
يضيع في إعادة التشغيل وإصلاح النصوص

شيفرة الأتمتة برمجيات وتحتاج إلى صيانة

حزمة الاختبارات برنامج يختبر برنامجاً آخر. لها متطلبات (حالات الاختبار التي تنفّذها)، وتصميم، واعتماديات، وعيوب خاصة بها: نتيجة متوقعة خاطئة، أو انتظار ناقص، أو اختبار لا ينجح إلا بعد تشغيل اختبار آخر. وهي تعيش ما يعيشه المنتج، فتتغير كلما تغيّر.

وتأتي الصيانة من أربعة اتجاهات: يتغير المنتج (زر أُعيدت تسميته، أو حقل إلزامي جديد، أو استجابة API تغيّرت)، وتتغير الأدوات (ترقيات المتصفح وإطار العمل وبيئة التشغيل)، وتتغير البيانات والبيئات، وتظهر عيوب الاختبارات نفسها. والفرق التي تبقى حزمها مفيدة تعامل شيفرة الاختبار كما تعامل شيفرة المنتج:

  • التحكم في الإصدارات (Version Control) بجوار شيفرة المنتج؛ فتغيير السلوك وتغيير اختباره يدخلان معاً.
  • مراجعة الشيفرة للاختبارات أيضاً: الأسماء والتأكيدات والتكرار وأوقات الانتظار الثابتة.
  • كتابة كل خطوة مرة واحدة، في دالة مساعدة مشتركة (ولاحقاً في هذه الوحدة، في نموذج كائن الصفحة Page Object)، فيصبح تغيير واحد في الواجهة تعديلاً واحداً.
  • حفظ البيانات والعناوين والأسرار في الإعدادات، وعدم وضع كلمة مرور حقيقية في نص برمجي أبداً.
  • فرز كل فشل وتسجيله على أنه عيب في المنتج أو عيب في الاختبار أو مشكلة في البيئة، وعدم إعادة التشغيل حتى يخضرّ.
  • تخطيط وقت للصيانة في كل سبرنت، وحذف الاختبارات التي لم تعد تحمي شيئاً.

مثال تطبيقي: إعادة تصميم واحدة و⁦37⁩ اختباراً أحمر

لدى فريق ⁦120⁩ اختباراً للمتصفح. قسّم المصممون صفحة تسجيل الدخول إلى خطوتين، البريد الإلكتروني وزر «Continue» أولاً ثم كلمة المرور، وغيّروا اسم الزر من «Sign in» إلى «Log in». فأظهر التشغيل الليلي ⁦37⁩ فشلاً. فرز المختبِر النتائج قبل أن يعيد أحدٌ تشغيل أي شيء: حالات الفشل هي بالضبط الاختبارات الـ⁦37⁩ التي تسجّل الدخول، وكلها تتوقف عند خطوة تسجيل الدخول، ولكل ملف من ملفاتها نسخته الخاصة من أسطر تسجيل الدخول. المنتج يعمل؛ والاختبارات هي المتقادمة.

كان ترقيع ⁦37⁩ ملفاً سيستغرق معظم يوم ويتكرر عند إعادة التصميم التالية، فنقل الفريق الخطوات إلى دالة مساعدة واحدة تُعدَّل وتُراجَع مرة واحدة. وبعد الإصلاح نجح ⁦36⁩ اختباراً، وظل واحد يفشل في خطوة لاحقة: خيار «Remember me» لم يعد يُبقي المستخدم مسجّلاً بعد إعادة تشغيل المتصفح. أعاد المختبِر إنتاج المشكلة يدوياً وأبلغ عن عيب في المنتج، وهذا بالضبط ما وُجدت الحزمة من أجله.

// Before: these three lines were copied into 37 test files
//   await page.getByLabel('Email').fill(testUser.email);
//   await page.getByLabel('Password').fill(testUser.password);
//   await page.getByRole('button', { name: 'Sign in' }).click();

// After: one helper (sign-in.ts) that every test calls; the next redesign means one edit
import type { Page } from '@playwright/test';
import type { TestUser } from './test-data';

export async function signIn(page: Page, user: TestUser) {
  // Step 1: email, then "Continue". Step 2: password, then the renamed button.
  await page.getByLabel('Email').fill(user.email);
  await page.getByRole('button', { name: 'Continue' }).click();
  await page.getByLabel('Password').fill(user.password);
  await page.getByRole('button', { name: 'Log in' }).click();
}

// In each test: await signIn(page, testUser);

أخطاء شائعة

  • معاملة الأتمتة كمشروع ينتهي: تسجيل النصوص البرمجية مرة واحدة وعدم تخصيص أي وقت لصيانتها.
  • أتمتة حالة يدوية نتيجتها المتوقعة غامضة، فينتج فحص لا يمكن أن يفشل.
  • الوثوق بتشغيل أخضر دون قراءة ما تتحقق منه تأكيداته فعلاً.
  • إعادة تشغيل الاختبارات الفاشلة حتى تنجح بدلاً من فرز كل فشل.
  • إبقاء شيفرة الاختبار خارج التحكم في الإصدارات والمراجعة، مع عناوين وأوقات انتظار وكلمات مرور مكتوبة داخلها.
  • قياس النجاح بعدد الاختبارات المؤتمتة بدلاً من الانحدارات التي تكشفها والجهد الذي تكلّفه.

من منظور ضمان الجودة

عند تنقيح قصة مستخدم، اسأل أيّ فحوصها سيُؤتمت، وعلى أي مستوى، ومن سيصونها؛ فالنتيجة المتوقعة الدقيقة في حالة الاختبار هي مساهمتك حتى لو كتب المطوّر النص البرمجي. وراجع شيفرة الاختبار في طلبات الدمج (Pull Requests) نفسها التي تضم شيفرة المنتج التي تغطيها.

وحين يكون التشغيل أحمر، افرز النتائج قبل أن يعيد أحدٌ التشغيل، وسجّل كل فشل على أنه عيب في المنتج أو عيب في الاختبار أو مشكلة في البيئة. وتابع الاختبارات المتذبذبة والساعات التي تُنفق على الصيانة؛ فهذه السجلات هي ما يحتاجه الفريق حين يقرر ما يؤتمته بعد ذلك. وحين تبلّغ بأن «اختبار الانحدار المؤتمت نجح»، فاذكر ما تغطيه الحزمة وما لا تغطيه.

تمرين عملي

راجع اختباراً مؤتمتاً كما تراجع الشيفرة

المطلوب

أتمت زميلك الحالة اليدوية أدناه. راجع النص البرمجي كما تراجع شيفرة المنتج: اكتب كل مشكلة تجدها، ولماذا تهمّ، واقترح إصلاحاً لها.

ثم صنّف ثلاث حالات فشل للاختبار بعد تحسينه: عيب في المنتج، أو عيب في الاختبار، أو مشكلة في البيئة.

المادة
الحالة اليدوية TC-CART-01: إضافة منتج إلى السلة
الشروط المسبقة: تسجيل الدخول بعميل اختبار؛ المنتج 1042 متوفر؛ السلة فارغة
الخطوات: افتح المنتج 1042؛ انقر «Add to cart»
المتوقع: شارة السلة تعرض 1؛ في السلة المنتج 1042، الكمية 1، السعر 49.00 ريال

test('test1', async ({ page }) => {
  await page.goto('https://staging.shop.example/login');
  await page.fill('#email', 'sara.qa@example.com');
  await page.fill('#pwd', 'secret123');
  await page.click('text=Sign in');
  await page.waitForTimeout(5000);
  await page.click('#product-1042');
  await page.click('.btn-primary');
  await expect(page.locator('.cart-count')).toBeVisible();
});

حالات فشل الاختبار بعد تحسينه:
A. يفشل فقط أثناء إعادة نشر بيئة staging صباح الاثنين الساعة 08:00: الاتصال مرفوض.
B. بعد إعادة تصميم صار اسم الزر «Add to basket»؛ والمنتج يعمل بشكل صحيح.
C. الشارة تعرض 2 بعد إضافة منتج واحد إلى سلة فارغة؛ وتتكرر المشكلة يدوياً.
الخطوات
  1. قارن النص البرمجي بالحالة اليدوية: أيّ الشروط المسبقة والنتائج المتوقعة احتفظ بها، وأيّها أسقط؟
  2. افحص الاسم والبيانات وأوقات الانتظار والمحددات (Locators).
  3. تحقّق هل يمكن تشغيل الاختبار مرتين متتاليتين، وعلى جهاز آخر.
  4. صنّف حالات الفشل الثلاث، واذكر ما ستفعله بعد ذلك في كل منها.
إظهار الإجابة النموذجية
الإجابة النموذجية

الاسم: test1 لا يقول شيئاً. سمِّه باسم القاعدة، مثل «إضافة منتج متوفر إلى سلة فارغة تُظهره مرة واحدة بسعره».

البيانات والأسرار: عنوان بيئة staging، وحساب شخصي يبدو حقيقياً، وكلمة مروره، كلها مكتوبة داخل الشيفرة. استخدم عنوان الأساس (Base URL) المهيّأ، وعميل اختبار تنشئه مرحلة التهيئة، وسراً يأتي من البيئة.

الانتظار: waitForTimeout(5000) يكلّف خمس ثوانٍ في كل مرة ويفشل مع ذلك حين تكون staging أبطأ. انتظر شرطاً بدلاً منه؛ ودرس الانتظار والتزامن يشرح كيف.

المحددات: #pwd و#product-1042 و.btn-primary تعتمد على تفاصيل التنفيذ. فضّل التسميات والأدوار والأسماء الظاهرة، وانقل أسطر تسجيل الدخول إلى الدالة المساعدة المشتركة.

التأكيد: «الشارة ظاهرة» لا يتحقق بدقة من أيٍّ من النتائج المتوقعة: فهو ينجح حين تعرض الشارة ⁦0⁩ أو ⁦2⁩، أو حين يكون في السلة منتج خاطئ. أكّد أن الشارة تعرض ⁦1⁩، وأن السلة تضم المنتج ⁦1042⁩ بكمية ⁦1⁩ وبسعر ⁦49.00⁩ ريالاً.

الشروط المسبقة: يسجّل النص البرمجي الدخول لكنه يُسقط الشرطين الآخرين. فلا شيء يفرغ السلة، فيبدأ التشغيل الثاني وفيها عنصر مسبقاً، ولا شيء يضمن أن المنتج ⁦1042⁩ متوفر. أنشئ عميل اختبار جديداً أو أفرغ السلة في مرحلة التهيئة، وجهّز المخزون في بيانات الاختبار، ونظّف بعد الاختبار.

حالات الفشل: A مشكلة في البيئة؛ سجّلها وجدوِل التشغيل خارج نافذة إعادة النشر. وB عيب في الاختبار لأن الاختبار متقادم: تأكّد أن الاسم الجديد مقصود، ثم حدّث المحدِّد في مكان واحد. وC عيب في المنتج كشفه التأكيد الأقوى؛ أبلغ عنه مع الخطوات والعدد المتوقع ⁦1⁩ والعدد الفعلي ⁦2⁩.

أسئلة شائعة

هل يجب أن أكون مبرمجاً لأؤتمت الاختبارات؟

تحتاج إلى قراءة الشيفرة وكتابتها بمستوى أساسي كي تؤتمت بطريقة قابلة للصيانة. أدوات التسجيل وإعادة التشغيل (Record and Playback) والأدوات منخفضة الشيفرة تقلل الكتابة، لا الحاجة إلى تصميم الاختبارات ومراجعتها وصيانتها. ودرس أساسيات البرمجة لأتمتة الاختبار يغطيها؛ وحتى ذلك الحين فإن حالات الاختبار الدقيقة والفرز المتأني جزء من عمل الأتمتة.

هل أتمتة الاختبار هي نفسها الاختبار الآلي؟

تستخدم الفرق المصطلحين عادةً للتنفيذ الآلي للاختبار. أما تعريف ISTQB لأتمتة الاختبار فأوسع: أي استخدام للبرمجيات لتنفيذ أنشطة الاختبار أو دعمها، مثل توليد بيانات الاختبار أو تجهيز البيئات أو إعداد التقارير.

هل تجد الأتمتة عيوباً أكثر من الاختبار اليدوي؟

إنها تجد نوعاً مختلفاً. فالحزمة المؤتمتة تعيد فحص السلوك المعروف بسرعة وتكشف الانحدارات، أما العيوب الجديدة فتأتي غالباً من تصميم اختبارات جديدة ومن الاختبار الاستكشافي. وقيمتها الأساسية في التأكيد السريع المتكرر، لا في الاكتشاف.

ما مقدار الصيانة الذي نتوقعه؟

لا يوجد رقم عام: فالأمر يعتمد على عدد مرات تغيّر المنتج وعلى تصميم الحزمة. لذلك قِسه: سجّل في كل سبرنت الساعات التي أُنفقت على إصلاح الاختبارات وسببها. والدرس التالي يستخدم هذه الأرقام في حساب صادق للعائد على الاستثمار (ROI).

المراجع

  • ISTQB Certified Tester Foundation Level (CTFL) v4.0ISTQB · 2023المنهج التأسيسي لاختبار البرمجيات: مستويات الاختبار وأنواعه وتقنيات تصميم الاختبارات وإدارة الاختبار والأدوات.
  • ISTQB GlossaryISTQBالتعريفات القياسية لمصطلحات الاختبار — حالة الاختبار واختبار الانحدار والخطورة والأولوية وتحليل القيم الحدّية وغيرها.
  • Certified Tester Advanced Level Test Automation Engineering (CTAL-TAE) v2.0ISTQB · 2024منهج ISTQB المتقدم لتصميم حلول أتمتة الاختبار وتنفيذها وصيانتها وبنيتها.
  • Best Practices — PlaywrightMicrosoft (Playwright)اختبر السلوك الذي يراه المستخدم، واجعل الاختبارات معزولة، وفضّل المحدِّدات المتينة والتأكيدات التي تنتظر، واستخدم التتبّع لتصحيح الأخطاء.

تدرّب بأدوات متقن

اختبر نقاط نهاية REST بتحكم كامل في الطريقة والترويسات وجسم JSON، ثم أضف تأكيدات على الحالة والترويسات ومسارات JSON.

اختبار واجهات API

توليد كود جاهز للتنفيذ لطلبات REST API بلغات cURL وJavaScript fetch وaxios وPython requests وJava وC# وGo وPHP.

الويب

ولّد حالات اختبار منظّمة (المعرّف والعنوان والشروط المسبقة والخطوات والنتيجة المتوقّعة والأولوية) من وصف الميزة وقائمة الحقول.

تصميم الاختبارات

للتعمّق أكثر

تقدّمك في هذا الموضوع

جزء من مسار تعلم ضمان الجودة