bun test متكامل بعمق مع وقت تشغيل Bun. هذا جزء مما يجعل bun test سريعًا وسهل الاستخدام.
متغيرات البيئة
NODE_ENV
يُعيِّن bun test تلقائيًا $NODE_ENV إلى "test" ما لم يكن مُعيَّنًا بالفعل في البيئة أو عبر ملفات .env. هذا سلوك قياسي لمعظم مُشغِّلي الاختبار ويساعد على ضمان سلوك اختبار متسق.
import { test, expect } from "bun:test";
test("NODE_ENV مُعيَّن إلى test", () => {
expect(process.env.NODE_ENV).toBe("test");
});يمكنك تجاوز هذا بتعيين NODE_ENV صراحةً:
NODE_ENV=development bun testTZ (المنطقة الزمنية)
بشكل افتراضي، تستخدم جميع تشغيلات bun test UTC (Etc/UTC) كمنطقة زمنية ما لم يتم تجاوزها بواسطة متغير البيئة TZ. هذا يضمن سلوك تاريخ ووقت متسق عبر بيئات التطوير المختلفة.
import { test, expect } from "bun:test";
test("المنطقة الزمنية هي UTC بشكل افتراضي", () => {
const date = new Date();
expect(date.getTimezoneOffset()).toBe(0);
});لاختبار بمنطقة زمنية محددة:
TZ=America/New_York bun testالمهل الزمنية للاختبار
كل اختبار لديه مهلة افتراضية تبلغ 5000ms (5 ثوانٍ) ما لم يتم تجاوزه صراحةً. الاختبارات التي تتجاوز هذه المهلة ستفشل.
المهلة العالمية
غيِّر المهلة عالميًا باستخدام العلم --timeout:
bun test --timeout 10000 # 10 ثوانٍالمهلة لكل اختبار
عيِّن المهلة لكل اختبار كمعامل ثالث لدالة الاختبار:
import { test, expect } from "bun:test";
test("اختبار سريع", () => {
expect(1 + 1).toBe(2);
}, 1000); // مهلة ثانية واحدة
test("اختبار بطيء", async () => {
await new Promise(resolve => setTimeout(resolve, 8000));
}, 10000); // مهلة 10 ثوانٍمهلة غير محدودة
استخدم 0 أو Infinity لتعطيل المهلة:
test("اختبار بدون مهلة", async () => {
// يمكن لهذا الاختبار العمل إلى أجل غير مسمى
await someVeryLongOperation();
}, 0);معالجة الأخطاء
الأخطاء غير المعالجة
يتتبع bun test رفض الوعد غير المعالج والأخطاء التي تحدث بين الاختبارات. إذا حدثت مثل هذه الأخطاء، سيكون رمز الخروج النهائي غير صفري (على وجه التحديد، عدد هذه الأخطاء)، حتى لو اجتازت جميع الاختبارات.
هذا يساعد في اكتشاف الأخطاء في الكود غير المتزامن التي قد تمر دون ملاحظة:
import { test } from "bun:test";
test("الاختبار 1", () => {
// هذا الاختبار يجتاز
expect(true).toBe(true);
});
// هذا الخطأ يحدث خارج أي اختبار
setTimeout(() => {
throw new Error("خطأ غير معالج");
}, 0);
test("الاختبار 2", () => {
// هذا الاختبار يجتاز أيضًا
expect(true).toBe(true);
});
// تشغيل الاختبار سيفشل مع رمز خروج غير صفري
// بسبب الخطأ غير المعالجرفض الوعد
يتم التقاط رفض الوعد غير المعالج أيضًا:
import { test } from "bun:test";
test("اختبار ناجح", () => {
expect(1).toBe(1);
});
// هذا سيتسبب في فشل تشغيل الاختبار
Promise.reject(new Error("رفض غير معالج"));معالجة الأخطاء المخصصة
يمكنك إعداد معالجات أخطاء مخصصة في إعداد الاختبار:
process.on("uncaughtException", error => {
console.error("استثناء غير معالج:", error);
process.exit(1);
});
process.on("unhandledRejection", (reason, promise) => {
console.error("رفض غير معالج عند:", promise, "السبب:", reason);
process.exit(1);
});تكامل أعلام CLI
يمكن استخدام العديد من أعلام Bun CLI مع bun test لتعديل سلوكه:
استخدام الذاكرة
# يقلل استخدام الذاكرة لـ VM مشغل الاختبار
bun test --smolالتصحيح
# يرفق المصحح بعملية مشغل الاختبار
bun test --inspect
bun test --inspect-brkتحميل الوحدة
# يشغل النصوص قبل ملفات الاختبار (مفيد للإعداد/المحاكاة العامة)
bun test --preload ./setup.ts
# يعيِّن ثوابت وقت التجميع
bun test --define "process.env.API_URL='http://localhost:3000'"
# يكوِّن محملات مخصصة
bun test --loader .special:special-loader
# يستخدم tsconfig مختلف
bun test --tsconfig-override ./test-tsconfig.json
# يعيِّن شروط package.json لحل الوحدة
bun test --conditions development
# يحمِّل متغيرات البيئة للاختبارات
bun test --env-file .env.testالأعلام المتعلقة بالتثبيت
# تؤثر على أي طلبات شبكة أو تثبيت تلقائي أثناء تنفيذ الاختبار
bun test --prefer-offline
bun test --frozen-lockfileالمراقبة وإعادة التحميل الساخن
وضع المراقبة
عند تشغيل bun test مع العلم --watch، سيراقب مشغل الاختبار تغييرات الملفات ويعيد تشغيل الاختبارات المتأثرة.
bun test --watchمشغل الاختبار ذكي حول الاختبارات التي يعيد تشغيلها:
import { add } from "./math.js";
import { test, expect } from "bun:test";
test("الجمع", () => {
expect(add(2, 3)).toBe(5);
});إذا عدَّلت math.js، سيتم إعادة تشغيل math.test.ts فقط، وليس جميع الاختبارات.
إعادة التحميل الساخن
يوفر العلم --hot وظائف مماثلة لكنه أكثر عدوانية في محاولة الحفاظ على الحالة بين التشغيلات:
bun test --hotلمعظم سيناريوهات الاختبار، الخيار --watch هو الخيار الموصى به لأنه يوفر عزلًا أفضل بين تشغيلات الاختبار.
المتغيرات العامة
المتغيرات العامة التالية متاحة تلقائيًا في ملفات الاختبار دون استيراد (على الرغم من أنه يمكن استيرادها من bun:test إذا كنت تفضل ذلك):
// كل هذه متاحة عالميًا
test("دالة اختبار عامة", () => {
expect(true).toBe(true);
});
describe("describe عامة", () => {
beforeAll(() => {
// beforeAll عامة
});
it("دالة it عامة", () => {
// it هي اسم مستعار لـ test
});
});
// توافق Jest
jest.fn();
// توافق Vitest
vi.fn();يمكنك أيضًا استيرادها صراحةً إذا كنت تفضل ذلك:
import { test, it, describe, expect, beforeAll, beforeEach, afterAll, afterEach, jest, vi } from "bun:test";تكامل العملية
رموز الخروج
يستخدم bun test رموز خروج قياسية:
0: جميع الاختبارات اجتازت، لا أخطاء غير معالجة1: حدثت إخفاقات اختبار>1: عدد الأخطاء غير المعالجة (حتى لو اجتازت الاختبارات)
معالجة الإشارات
يتعامل مشغل الاختبار بشكل صحيح مع الإشارات الشائعة:
# يوقف تنفيذ الاختبار بسلاسة
kill -SIGTERM <test-process-pid>
# يوقف تنفيذ الاختبار فورًا
kill -SIGKILL <test-process-pid>اكتشاف البيئة
يكتشف Bun تلقائيًا بيئات معينة ويعدل السلوك:
// اكتشاف GitHub Actions
if (process.env.GITHUB_ACTIONS) {
// يُصدِر Bun تلقائيًا تعليقات GitHub Actions
}
// اكتشاف CI
if (process.env.CI) {
// قد يتم تعديل سلوكيات معينة لبيئات CI
}اعتبارات الأداء
عملية واحدة
يشغل مشغل الاختبار جميع الاختبارات في عملية واحدة بشكل افتراضي. هذا يوفر:
- بدء أسرع - لا حاجة ل.spawn عمليات متعددة
- ذاكرة مشتركة - استخدام فعال للموارد
- تصحيح بسيط - جميع الاختبارات في عملية واحدة
ومع ذلك، هذا يعني:
- الاختبارات تشارك الحالة العامة (استخدم خطافات دورة الحياة للتنظيف)
- تعطل اختبار واحد يمكن أن يؤثر على الآخرين
- لا توازٍ حقيقي للاختبارات الفردية
إدارة الذاكرة
# راقب استخدام الذاكرة
bun test --smol # يقلل بصمة الذاكرة
# لمجموعات الاختبار الكبيرة، فكر في تقسيم الملفات
bun test src/unit/
bun test src/integration/عزل الاختبار
نظرًا لأن الاختبارات تعمل في نفس العملية، تأكد من التنظيف المناسب:
import { afterEach } from "bun:test";
afterEach(() => {
// تنظيف الحالة العامة
global.myGlobalVar = undefined;
delete process.env.TEST_VAR;
// إعادة تعيين الوحدات إذا لزم الأمر
jest.resetModules();
});