Skip to content

يدعم عداء الاختبار خطافات دورة الحياة التالية. هذا مفيد لتحميل عناصر اختبار الاختبار، ومحاكاة البيانات، وتكوين بيئة الاختبار.

الخطافالوصف
beforeAllيعمل مرة واحدة قبل جميع الاختبارات.
beforeEachيعمل قبل كل اختبار.
afterEachيعمل بعد كل اختبار.
afterAllيعمل مرة واحدة بعد جميع الاختبارات.
onTestFinishedيعمل بعد انتهاء اختبار واحد (بعد جميع afterEach).

الإعداد والتفكيك لكل اختبار

قم بتنفيذ منطق الإعداد والتفكيك لكل اختبار مع beforeEach و afterEach.

test.ts
ts
import { beforeEach, afterEach, test } from "bun:test";

beforeEach(() => {
  console.log("تشغيل الاختبار.");
});

afterEach(() => {
  console.log("تم الانتهاء من الاختبار.");
});

// الاختبارات...
test("مثال اختبار", () => {
  // سيتم تشغيل beforeEach قبل هذا الاختبار
  // و afterEach بعده
});

الإعداد والتفكيك لكل نطاق

قم بتنفيذ منطق الإعداد والتفكيك لكل نطاق مع beforeAll و afterAll. يتم تحديد النطاق بواسطة مكان تعريف الخطاف.

محدد بنطاق كتلة Describe

لتحديد نطاق الخطافات لكتلة describe معينة:

test.ts
ts
import { describe, beforeAll, afterAll, test } from "bun:test";

describe("مجموعة الاختبار", () => {
  beforeAll(() => {
    // الإعداد لمجموعة describe هذه
    console.log("إعداد مجموعة الاختبار");
  });

  afterAll(() => {
    // التفكيك لمجموعة describe هذه
    console.log("تفكيك مجموعة الاختبار");
  });

  test("الاختبار 1", () => {
    // تنفيذ الاختبار
  });

  test("الاختبار 2", () => {
    // تنفيذ الاختبار
  });
});

محدد بنطاق ملف الاختبار

لتحديد نطاق الخطافات لملف الاختبار بأكمله:

test.ts
ts
import { describe, beforeAll, afterAll, test } from "bun:test";

beforeAll(() => {
  // الإعداد للملف بأكمله
  console.log("إعداد ملف الاختبار");
});

afterAll(() => {
  // التفكيك للملف بأكمله
  console.log("تفكيك ملف الاختبار");
});

describe("مجموعة الاختبار", () => {
  test("الاختبار 1", () => {
    // تنفيذ الاختبار
  });
});

onTestFinished

استخدم onTestFinished لتشغيل دالة استدعاء بعد انتهاء اختبار واحد. يعمل بعد جميع خطافات afterEach.

test.ts
ts
import { test, onTestFinished } from "bun:test";

test("التنظيف بعد الاختبار", () => {
  onTestFinished(() => {
    // يعمل بعد جميع خطافات afterEach
    console.log("انتهى الاختبار");
  });
});

غير مدعوم في الاختبارات المتزامنة؛ استخدم test.serial بدلاً من ذلك.

الإعداد والتفكيك العام

لتحديد نطاق الخطافات لتشغيل اختبار متعدد الملفات بأكمله، عرّف الخطافات في ملف منفصل.

setup.ts
ts
import { beforeAll, afterAll } from "bun:test";

beforeAll(() => {
  // الإعداد العام
  console.log("إعداد الاختبار العام");
  // تهيئة اتصالات قاعدة البيانات، بدء الخوادم، إلخ.
});

afterAll(() => {
  // التفكيك العام
  console.log("تفكيك الاختبار العام");
  // إغلاق اتصالات قاعدة البيانات، إيقاف الخوادم، إلخ.
});

ثم استخدم --preload لتشغيل نص الإعداد قبل أي ملفات اختبار.

bash
bun test --preload ./setup.ts

لتجنب كتابة --preload في كل مرة تشغل فيها الاختبارات، يمكن إضافتها إلى bunfig.toml:

bunfig.toml
toml
[test]
preload = ["./setup.ts"]

أمثلة عملية

إعداد قاعدة البيانات

database-setup.ts
ts
import { beforeAll, afterAll, beforeEach, afterEach } from "bun:test";
import { createConnection, closeConnection, clearDatabase } from "./db";

let connection;

beforeAll(async () => {
  // الاتصال بقاعدة بيانات الاختبار
  connection = await createConnection({
    host: "localhost",
    database: "test_db",
  });
});

afterAll(async () => {
  // إغلاق اتصال قاعدة البيانات
  await closeConnection(connection);
});

beforeEach(async () => {
  // البدء بقاعدة بيانات نظيفة لكل اختبار
  await clearDatabase(connection);
});

إعداد خادم API

server-setup.ts
ts
import { beforeAll, afterAll } from "bun:test";
import { startServer, stopServer } from "./server";

let server;

beforeAll(async () => {
  // بدء خادم الاختبار
  server = await startServer({
    port: 3001,
    env: "test",
  });
});

afterAll(async () => {
  // إيقاف خادم الاختبار
  await stopServer(server);
});

إعداد المحاكاة

mock-setup.ts
ts
import { beforeEach, afterEach } from "bun:test";
import { mock } from "bun:test";

beforeEach(() => {
  // إعداد المحاكاة الشائعة
  mock.module("./api-client", () => ({
    fetchUser: mock(() => Promise.resolve({ id: 1, name: "مستخدم اختبار" })),
    createUser: mock(() => Promise.resolve({ id: 2 })),
  }));
});

afterEach(() => {
  // مسح جميع المحاكاة بعد كل اختبار
  mock.restore();
});

خطافات دورة الحياة غير المتزامنة

تدعم جميع خطافات دورة الحياة الدوال غير المتزامنة:

test.ts
ts
import { beforeAll, afterAll, test } from "bun:test";

beforeAll(async () => {
  // إعداد غير متزامن
  await new Promise(resolve => setTimeout(resolve, 100));
  console.log("اكتمل الإعداد غير المتزامن");
});

afterAll(async () => {
  // تفكيك غير متزامن
  await new Promise(resolve => setTimeout(resolve, 100));
  console.log("اكتمل التفكيك غير المتزامن");
});

test("اختبار غير متزامن", async () => {
  // سينتظر الاختبار اكتمال beforeAll
  await expect(Promise.resolve("test")).resolves.toBe("test");
});

خطافات متداخلة

يمكن تداخل الخطافات وستعمل بالترتيب المناسب:

test.ts
ts
import { describe, beforeAll, beforeEach, afterEach, afterAll, test } from "bun:test";

beforeAll(() => console.log("File beforeAll"));
afterAll(() => console.log("File afterAll"));

describe("outer describe", () => {
  beforeAll(() => console.log("Outer beforeAll"));
  beforeEach(() => console.log("Outer beforeEach"));
  afterEach(() => console.log("Outer afterEach"));
  afterAll(() => console.log("Outer afterAll"));

  describe("inner describe", () => {
    beforeAll(() => console.log("Inner beforeAll"));
    beforeEach(() => console.log("Inner beforeEach"));
    afterEach(() => console.log("Inner afterEach"));
    afterAll(() => console.log("Inner afterAll"));

    test("اختبار متداخل", () => {
      console.log("تشغيل الاختبار");
    });
  });
});
txt
// ترتيب الإخراج:
// File beforeAll
// Outer beforeAll
// Inner beforeAll
// Outer beforeEach
// Inner beforeEach
// Test running
// Inner afterEach
// Outer afterEach
// Inner afterAll
// Outer afterAll
// File afterAll

معالجة الأخطاء

إذا طرح خطاف دورة حياة خطأ، فسيؤثر على تنفيذ الاختبار:

test.ts
ts
import { beforeAll, test } from "bun:test";

beforeAll(() => {
  // إذا طرح هذا، سيتم تخطي جميع الاختبارات في هذا النطاق
  throw new Error("فشل الإعداد");
});

test("سيتم تخطي هذا الاختبار", () => {
  // لن يعمل هذا لأن beforeAll فشل
});

لمعالجة أخطاء أفضل:

test.ts
ts
import { beforeAll, test, expect } from "bun:test";

beforeAll(async () => {
  try {
    await setupDatabase();
  } catch (error) {
    console.error("فشل إعداد قاعدة البيانات:", error);
    throw error; // إعادة الرمي لفشل مجموعة الاختبار
  }
});

أفضل الممارسات

اجعل الخطافات بسيطة

test.ts
ts
// جيد: إعداد بسيط ومركّز
beforeEach(() => {
  clearLocalStorage();
  resetMocks();
});

// تجنب: منطق معقد في الخطافات
beforeEach(async () => {
  // الكثير من المنطق المعقد يجعل الاختبارات صعبة التصحيح
  const data = await fetchComplexData();
  await processData(data);
  await setupMultipleServices(data);
});

استخدم النطاق المناسب

test.ts
ts
// جيد: إعداد على مستوى الملف للموارد المشتركة
beforeAll(async () => {
  await startTestServer();
});

// جيد: إعداد على مستوى الاختبار للحالة الخاصة بالاختبار
beforeEach(() => {
  user = createTestUser();
});

تنظيف الموارد

test.ts
ts
import { afterAll, afterEach } from "bun:test";

afterEach(() => {
  // التنظيف بعد كل اختبار
  document.body.innerHTML = "";
  localStorage.clear();
});

afterAll(async () => {
  // تنظيف الموارد المكلفة
  await closeDatabase();
  await stopServer();
});

Bun بواسطة www.bunjs.com.cn تحرير