المقصود بالاختبار

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

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

في ما يلي بعض الأمثلة على السلوكيات على الويب التي يمكنك اختبارها:

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

الاختبار الآلي مقابل الاختبار اليدوي

يمكنك اختبار البرنامج بطريقتين عامتين: الاختبار الآلي والاختبار اليدوي.

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

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

يكون للاختبار اليدوي مكانه، غالبًا كمقدمة لإعداد الاختبارات الآلية، أو عندما يصبح الاختبار الآلي غير موثوق به أو واسع النطاق أو غير عملي في الكتابة.

المبادئ الأساسية من خلال مثال

بالنسبة إلينا، بصفتنا مطوّري برامج على الويب يكتبون لغة JavaScript أو لغات ذات صلة، قد يكون الاختبار الآلي الموجز عبارة عن نص برمجي يشبه هذا النظام كل يوم، مثلاً من خلال أداة Node أو عن طريق تحميله في متصفّح:

import { fibonacci } from "../src/math.js";

if (fibonacci(0) !== 0) {
  throw new Error("Invalid 0th fibonacci result");
}
const fib13 = fibonacci(13);
if (fib13 !== 233) {
  throw new Error("Invalid 13th fibonacci result, was=${fib13} wanted=233");
}

هذا مثال مبسّط يقدّم الإحصاءات التالية:

  • هذا اختبار لأنه يشغّل بعض البرامج (دالة فيبوناتشي دالة) ويتأكد من عمل سلوكها بالطريقة أمّا إذا لم يكن السلوك صحيحًا، فسيسبب الخطأ، ويتم التعبير عنه من خلال عرض علامة Error في JavaScript.

  • على الرغم من احتمال تشغيل هذا النص البرمجي يدويًا في الوحدة الطرفية أو المتصفح، فإنه لا يزال اختبارًا مبرمَجًا لأنّه يمكن تشغيله بشكلٍ متكرّر بدون الحاجة إلى تنفيذ أي خطوات فردية. وتشرح الصفحة التالية حيث يتم إجراء الاختبارات مزيدًا من الشرح.

  • لا يزال هذا الاختبار قيد الاختبار، على الرغم من أنّه لا يستخدم أي مكتبات، فهو عبارة عن لغة JavaScript يمكن تشغيلها في أي مكان. هناك العديد من الأدوات التي يمكن أن تساعدك في كتابة الاختبارات، بما في ذلك الأدوات التي سيتم تناولها لاحقًا في هذه الدورة، لكنها لا تزال تعمل على المبدأ الأساسي المتمثل في التسبب في خطأ إذا حدث خطأ ما.

اختبار المكتبات عمليًا

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

التأكيدات هي طريقة للجمع بين التحقق من النتيجة والتسبب في خطأ إذا حدث خطأ ما. على سبيل المثال، يمكنك جعل الاختبار السابق أكثر إيجازًا من خلال تقديم assert:

import { fibonacci } from "../src/math.js";
import { assert } from "a-made-up-testing-library";

assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");

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

import { fibonacci, catalan } from "../src/math.js";
import { assert, test, suite } from "a-made-up-testing-library";

suite("math tests", () => {
  test("fibonacci function", () => {
    assert.equal(fibonacci(0), 0, "Invalid 0th fibonacci result");
    assert.equal(fibonacci(13), 233, "Invalid 13th fibonacci result");
  });
  test("relationship between sequences", () => {
    const numberToCheck = 4;
    const fib = fibonacci(numberToCheck);
    const cat = catalan(numberToCheck);
    assert.isAbove(fib, cat);
  });
});

في هذا سياق اختبار البرامج، يشير مصطلح test كاسم إلى حالة اختبار: وهي سيناريو فردي ومستقل يمكن معالجته، مثل حالة اختبار "العلاقة بين التسلسلات" في المثال السابق.

تكون الاختبارات ذات الأسماء الفردية مفيدة مع المهام التالية من بين مهام أخرى:

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

تتمثل إحدى طرق التفكير في حالات الاختبار في استخدام "السمات الثلاثة" لاختبار الوحدة: الترتيب والتنفيذ والتأكيد. ستقوم كل حالة اختبار، في جوهرها، بما يلي:

  • ترتيب بعض القيم أو الحالة (يمكن أن تكون هذه مجرد بيانات إدخال غير قابلة للتغيير).
  • تنفيذ إجراء، مثل استدعاء طريقة
  • تأكيد قيم الإخراج أو الحالة المعدَّلة (باستخدام assert)

مقياس الاختبارات

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

إلى جانب اختبارات الوحدات، تشمل بعض الأمثلة على أنواع الاختبارات الأخرى اختبار المكوّنات، والاختبار المرئي، واختبار الدمج. لا يحتوي أي من هذه الأسماء على تعريفات دقيقة، وقد يكون لها معانٍ مختلفة اعتمادًا على قاعدة التعليمات البرمجية لديك، لذا تذكر استخدامها كدليل والتوصل إلى تعريفات مناسبة لك. على سبيل المثال، ما هو المكوِّن الذي يخضع للاختبار في نظامك؟ بالنسبة إلى مطوّري التفاعلات، قد يرتبط هذا فعليًا بـ "مكوِّن التفاعل"، ولكن قد يكون له معنى مختلف بالنسبة إلى المطوّرين في السياقات الأخرى.

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

التسلسل الهرمي للاختبار،
    مع اختبارات شاملة (E2E) في الأعلى، واختبارات دمج في المنتصف،
    واختبارات وحدات في الأسفل.
هرم الاختبار:

وتم تكرار هذه الفكرة، وتم تمييز أشكال أخرى متعددة، مثل ألماس الاختبار أو مخروط الجليد للاختبار. من المحتمل أن تكون أولويات كتابة الاختبار فريدة لقاعدة التعليمات البرمجية لديك. ومع ذلك، هناك سمة شائعة تتمثل في أن الاختبارات البسيطة، مثل اختبارات الوحدات، قد تكون أسرع في التنفيذ، وتسهل كتابتها (لذا سيكون لديك المزيد منها)، واختبار نطاق محدود، في حين أن الاختبارات المعقدة مثل الاختبارات الشاملة تصعب كتابتها ولكن يمكن أن تختبر نطاقًا أوسع. في الواقع، تميل الطبقة العلوية من العديد من "أشكال" الاختبار إلى أن تكون اختبارًا يدويًّا، لأن بعض تفاعلات المستخدم معقد جدًا بحيث لا يمكن منهجه في اختبار تلقائي.

وسيتم توسيع هذه الأنواع في أنواع الاختبار التلقائي.

التحقق من فهمك

ما هي المبادئ الأساسية التي توفرها معظم مكتبات الاختبار وأُطر العمل الخاصة به؟

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