قبل الدفع · فصل ٦

الاختبار إجابة مكتوبة قبل ما تثق

node:test · assert · exit code · vitest · jest
🎯 الهدف: تكتب اختبار يفشل لو الناتج اتغير، وتعرف إن الأمر لازم يطلع بغير صفر عشان الـ CI يحس.

مش وثيقة، برنامج

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

Node جاي مع مشغّل اختبار من غير حزمة زيادة. الملفين امتدادهما mjs عشان import يشتغل حتى لو المشروع مش معلّم إنه ES modules.

total.mjs
export function total(prices) {  return prices.reduce((sum, n) => sum + n, 0);}
total.test.mjs
import test from "node:test";import assert from "node:assert/strict";import { total } from "./total.mjs";test("قائمة فاضية", () => {  assert.equal(total([]), 0);});test("يجمع رقمين", () => {  assert.equal(total([10, 5]), 15);});
terminal
node --test

assert.equal يقارن بـ ===. لو مختلف، الاختبار يرسب والأمر يطلع بغير صفر. الـ CI مش بيقرا جملة “كل حاجة تمام”. بيبص على رقم الخروج.

اختبار من غير assert زي بوابة مفتوحة. الأمر أخضر والسلوك ممكن يكون أي حاجة.

إيه اللي يستاهل اختبار هنا؟

مش كل سطر. ابدأ بحاجة لو اتغيرت هتكسر حد: حساب، شرط، تحويل بيانات. شكل الزر ومسافة Prettier مش اختبار. ESLint مش بديل عن اختبار: اللينتر مش هيشوف إن الجمع رجّع رقم غلط.

Jest و Vitest

نفس الفكرة: ملفات اختبار، تأكيدات، وأمر يفشل لو واحد رسب. الفرق واجهة والأدوات اللي حواليها. الفريق يختار واحد ويثبّت أمره في package.json عشان الـ CI مناديهوش من الذاكرة.

الأمر في السكربت

حط "test": "node --test" في scripts. بعد كده npm test على جهازك وعلى السيرفر. تغيير المشغّل يبقى تغيير السكربت، مش تغيير عشرين ملف CI.

خلّصت الفصل لما

🧠 اختبر نفسك
١) اختبار يستدعي الدالة ومفيش assert. بيثبت إيه؟
إنه الاستدعاء مرمش استثناء. مش إن الناتج صح.
٢) الـ CI عرف إن الاختبار رسب إزاي؟
من رقم خروج الأمر. غير الصفر يعني فشل.
٣) ESLint يغني عن اختبار الجمع؟
لأ. اللينتر مش بيشوف إن الناتج رقم غلط.