Skip to content

مُشَغِّل الاختبار

[التاريخ]

الإصدارالتغييرات
v20.0.0مُشَغِّل الاختبار الآن مستقر.
v18.0.0, v16.17.0تمت إضافته في: v18.0.0, v16.17.0

[مستقر: 2 - مستقر]

مستقر: 2 الاستقرار: 2 - مستقر

الكود المصدري: lib/test.js

تُسهِّل وحدة node:test إنشاء اختبارات JavaScript. للوصول إليها:

js
import test from 'node:test';
js
const test = require('node:test');

هذه الوحدة متاحة فقط ضمن نظام node:.

تتكون الاختبارات التي تم إنشاؤها عبر وحدة test من دالة واحدة تتم معالجتها بإحدى ثلاث طرق:

يوضح المثال التالي كيفية كتابة الاختبارات باستخدام وحدة test.

js
test('اختبار تمرير متزامن', (t) => {
  // ينجح هذا الاختبار لأنه لا يطرح استثناءً.
  assert.strictEqual(1, 1);
});

test('اختبار فشل متزامن', (t) => {
  // يفشل هذا الاختبار لأنه يطرح استثناءً.
  assert.strictEqual(1, 2);
});

test('اختبار تمرير غير متزامن', async (t) => {
  // ينجح هذا الاختبار لأن الوعد الذي تم إرجاعه بواسطة الدالة غير المتزامنة
  // قد تم تسويته ولم يتم رفضه.
  assert.strictEqual(1, 1);
});

test('اختبار فشل غير متزامن', async (t) => {
  // يفشل هذا الاختبار لأن الوعد الذي تم إرجاعه بواسطة الدالة غير المتزامنة
  // قد تم رفضه.
  assert.strictEqual(1, 2);
});

test('اختبار فاشل باستخدام الوعود', (t) => {
  // يمكن استخدام الوعود مباشرة أيضًا.
  return new Promise((resolve, reject) => {
    setImmediate(() => {
      reject(new Error('سيتسبب هذا في فشل الاختبار'));
    });
  });
});

test('اختبار تمرير رد نداء', (t, done) => {
  // done() هي دالة رد النداء. عندما يتم تشغيل setImmediate()، فإنها تستدعي
  // done() بدون وسائط.
  setImmediate(done);
});

test('اختبار فشل رد نداء', (t, done) => {
  // عندما يتم تشغيل setImmediate()، يتم استدعاء done() بكائن خطأ و
  // يفشل الاختبار.
  setImmediate(() => {
    done(new Error('فشل رد النداء'));
  });
});

إذا فشلت أي اختبارات، فسيتم تعيين رمز خروج العملية إلى 1.

الاختبارات الفرعية

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

js
test('اختبار المستوى الأعلى', async (t) => {
  await t.test('الاختبار الفرعي 1', (t) => {
    assert.strictEqual(1, 1);
  });

  await t.test('الاختبار الفرعي 2', (t) => {
    assert.strictEqual(2, 2);
  });
});

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

تخطي الاختبارات

يمكن تخطي الاختبارات الفردية عن طريق تمرير خيار skip إلى الاختبار، أو عن طريق استدعاء طريقة skip() في سياق الاختبار كما هو موضح في المثال التالي.

js
// يتم استخدام خيار التخطي، ولكن لم يتم تقديم أي رسالة.
test('خيار التخطي', { skip: true }, (t) => {
  // لن يتم تنفيذ هذا الكود.
});

// يتم استخدام خيار التخطي، ويتم تقديم رسالة.
test('خيار التخطي مع رسالة', { skip: 'تم تخطي هذا' }, (t) => {
  // لن يتم تنفيذ هذا الكود.
});

test('طريقة skip()', (t) => {
  // تأكد من العودة هنا أيضًا إذا كان الاختبار يحتوي على منطق إضافي.
  t.skip();
});

test('طريقة skip() مع رسالة', (t) => {
  // تأكد من العودة هنا أيضًا إذا كان الاختبار يحتوي على منطق إضافي.
  t.skip('تم تخطي هذا');
});

اختبارات TODO

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

js
// يتم استخدام خيار todo، ولكن لم يتم تقديم أي رسالة.
test('خيار todo', { todo: true }, (t) => {
  // يتم تنفيذ هذا الكود، ولكن لا يتم التعامل معه على أنه فشل.
  throw new Error('هذا لا يفشل الاختبار');
});

// يتم استخدام خيار todo، ويتم تقديم رسالة.
test('خيار todo مع رسالة', { todo: 'هذا اختبار todo' }, (t) => {
  // يتم تنفيذ هذا الكود.
});

test('طريقة todo()', (t) => {
  t.todo();
});

test('طريقة todo() مع رسالة', (t) => {
  t.todo('هذا اختبار todo ولا يتم التعامل معه على أنه فشل');
  throw new Error('هذا لا يفشل الاختبار');
});

describe() و it() أسماء مستعارة

يمكن أيضًا كتابة المجموعات والاختبارات باستخدام الدالتين describe() و it(). describe() هو اسم مستعار لـ suite()، و it() هو اسم مستعار لـ test().

js
describe('شيء ما', () => {
  it('يجب أن يعمل', () => {
    assert.strictEqual(1, 1);
  });

  it('يجب أن يكون على ما يرام', () => {
    assert.strictEqual(2, 2);
  });

  describe('شيء متداخل', () => {
    it('يجب أن يعمل', () => {
      assert.strictEqual(3, 3);
    });
  });
});

يتم استيراد describe() و it() من الوحدة النمطية node:test.

js
import { describe, it } from 'node:test';
js
const { describe, it } = require('node:test');

اختبارات only

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

عند استخدام الاختبارات الفرعية داخل test()/it()، فمن الضروري وضع علامة على جميع اختبارات الأصل بالخيار only لتشغيل مجموعة فرعية محددة فقط من الاختبارات.

يمكن استخدام طريقة runOnly() لسياق الاختبار لتنفيذ نفس السلوك على مستوى الاختبار الفرعي. يتم حذف الاختبارات التي لم يتم تنفيذها من ناتج مشغل الاختبار.

js
// افترض أن Node.js يتم تشغيله باستخدام خيار سطر الأوامر --test-only.
// تم تعيين الخيار 'only' للمجموعة، لذلك يتم تشغيل هذه الاختبارات.
test('يتم تشغيل هذا الاختبار', { only: true }, async (t) => {
  // ضمن هذا الاختبار، يتم تشغيل جميع الاختبارات الفرعية افتراضيًا.
  await t.test('تشغيل اختبار فرعي');

  // يمكن تحديث سياق الاختبار لتشغيل الاختبارات الفرعية بالخيار 'only'.
  t.runOnly(true);
  await t.test('تم تخطي هذا الاختبار الفرعي الآن');
  await t.test('يتم تشغيل هذا الاختبار الفرعي', { only: true });

  // قم بتبديل السياق مرة أخرى لتنفيذ جميع الاختبارات.
  t.runOnly(false);
  await t.test('يتم تشغيل هذا الاختبار الفرعي الآن');

  // لا تقم بتشغيل هذه الاختبارات بشكل صريح.
  await t.test('تم تخطي الاختبار الفرعي 3', { only: false });
  await t.test('تم تخطي الاختبار الفرعي 4', { skip: true });
});

// لم يتم تعيين الخيار 'only'، لذلك يتم تخطي هذا الاختبار.
test('لم يتم تشغيل هذا الاختبار', () => {
  // لم يتم تشغيل هذا الكود.
  throw new Error('فشل');
});

describe('مجموعة', () => {
  // تم تعيين الخيار 'only'، لذلك يتم تشغيل هذا الاختبار.
  it('يتم تشغيل هذا الاختبار', { only: true }, () => {
    // يتم تشغيل هذا الكود.
  });

  it('لم يتم تشغيل هذا الاختبار', () => {
    // لم يتم تشغيل هذا الكود.
    throw new Error('فشل');
  });
});

describe.only('مجموعة', () => {
  // تم تعيين الخيار 'only'، لذلك يتم تشغيل هذا الاختبار.
  it('يتم تشغيل هذا الاختبار', () => {
    // يتم تشغيل هذا الكود.
  });

  it('يتم تشغيل هذا الاختبار', () => {
    // يتم تشغيل هذا الكود.
  });
});

تصفية الاختبارات بالاسم

يمكن استخدام خيار سطر الأوامر --test-name-pattern لتشغيل الاختبارات التي يتطابق اسمها فقط مع النمط المقدم، ويمكن استخدام الخيار --test-skip-pattern لتخطي الاختبارات التي يتطابق اسمها مع النمط المقدم. يتم تفسير أنماط أسماء الاختبارات على أنها تعبيرات JavaScript منتظمة. يمكن تحديد الخيارين --test-name-pattern و --test-skip-pattern عدة مرات لتشغيل الاختبارات المتداخلة. لكل اختبار يتم تنفيذه، يتم أيضًا تشغيل أي خطافات اختبار مقابلة، مثل beforeEach(). يتم حذف الاختبارات التي لم يتم تنفيذها من إخراج مشغل الاختبار.

بالنظر إلى ملف الاختبار التالي، سيؤدي بدء تشغيل Node.js باستخدام الخيار --test-name-pattern="test [1-3]" إلى قيام مشغل الاختبار بتنفيذ test 1 و test 2 و test 3. إذا لم يتطابق test 1 مع نمط اسم الاختبار، فلن يتم تنفيذ اختباراته الفرعية، على الرغم من مطابقتها للنمط. يمكن أيضًا تنفيذ نفس مجموعة الاختبارات عن طريق تمرير --test-name-pattern عدة مرات (على سبيل المثال، --test-name-pattern="test 1"، --test-name-pattern="test 2"، إلخ.).

js
test('test 1', async (t) => {
  await t.test('test 2');
  await t.test('test 3');
});

test('Test 4', async (t) => {
  await t.test('Test 5');
  await t.test('test 6');
});

يمكن أيضًا تحديد أنماط أسماء الاختبار باستخدام التعبيرات المنتظمة الحرفية. يتيح ذلك استخدام علامات التعبير المنتظم. في المثال السابق، سيؤدي بدء تشغيل Node.js بـ --test-name-pattern="/test [4-5]/i" (أو --test-skip-pattern="/test [4-5]/i") إلى مطابقة Test 4 و Test 5 لأن النمط غير حساس لحالة الأحرف.

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

js
describe('test 1', (t) => {
  it('some test');
});

describe('test 2', (t) => {
  it('some test');
});

سيؤدي بدء تشغيل Node.js باستخدام --test-name-pattern="test 1 some test" إلى مطابقة some test فقط في test 1.

لا تغير أنماط أسماء الاختبار مجموعة الملفات التي ينفذها مشغل الاختبار.

إذا تم توفير كل من --test-name-pattern و --test-skip-pattern، فيجب أن تستوفي الاختبارات كلا الشرطين ليتم تنفيذها.

نشاط غير متزامن إضافي

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

في المثال التالي، يكتمل اختبار مع وجود عمليتين setImmediate() لا تزالان معلقتين. تحاول العملية setImmediate() الأولى إنشاء اختبار فرعي جديد. نظرًا لأن الاختبار الأصل قد انتهى بالفعل وأخرج نتائجه، يتم على الفور وضع علامة "فشل" على الاختبار الفرعي الجديد، ويتم الإبلاغ عنه لاحقًا إلى <TestsStream>.

تقوم العملية setImmediate() الثانية بإنشاء حدث uncaughtException. يتم وضع علامة "فشل" على أحداث uncaughtException و unhandledRejection المنبثقة من اختبار مكتمل بواسطة وحدة test ويتم الإبلاغ عنها كتحذيرات تشخيصية على المستوى الأعلى بواسطة <TestsStream>.

js
test('اختبار يقوم بإنشاء نشاط غير متزامن', (t) => {
  setImmediate(() => {
    t.test('اختبار فرعي تم إنشاؤه متأخرًا جدًا', (t) => {
      throw new Error('error1');
    });
  });

  setImmediate(() => {
    throw new Error('error2');
  });

  // ينتهي الاختبار بعد هذا السطر.
});

وضع المراقبة

تمت الإضافة في: v19.2.0, v18.13.0

[مستقر: 1 - تجريبي]

مستقر: 1 الاستقرار: 1 - تجريبي

يدعم مُشغّل اختبار Node.js التشغيل في وضع المراقبة عن طريق تمرير العلامة --watch:

bash
node --test --watch

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

تشغيل الاختبارات من سطر الأوامر

يمكن استدعاء مُشغّل اختبار Node.js من سطر الأوامر عن طريق تمرير العلامة --test:

bash
node --test

بشكل افتراضي، سيقوم Node.js بتشغيل جميع الملفات التي تطابق هذه الأنماط:

  • **/*.test.{cjs,mjs,js}
  • **/*-test.{cjs,mjs,js}
  • **/*_test.{cjs,mjs,js}
  • **/test-*.{cjs,mjs,js}
  • **/test.{cjs,mjs,js}
  • **/test/**/*.{cjs,mjs,js}

عند توفير --experimental-strip-types، تتم مطابقة الأنماط الإضافية التالية:

  • **/*.test.{cts,mts,ts}
  • **/*-test.{cts,mts,ts}
  • **/*_test.{cts,mts,ts}
  • **/test-*.{cts,mts,ts}
  • **/test.{cts,mts,ts}
  • **/test/**/*.{cts,mts,ts}

بدلاً من ذلك، يمكن توفير نمط واحد أو أكثر من أنماط glob كوسيطة (وسائط) نهائية لأمر Node.js، كما هو موضح أدناه. تتبع أنماط Glob سلوك glob(7). يجب تضمين أنماط glob بين علامتي اقتباس مزدوجتين في سطر الأوامر لمنع توسيع shell، مما قد يقلل من إمكانية النقل عبر الأنظمة.

bash
node --test "**/*.test.js" "**/*.spec.js"

يتم تنفيذ الملفات المطابقة كملفات اختبار. يمكن العثور على مزيد من المعلومات حول تنفيذ ملف الاختبار في قسم نموذج تنفيذ مُشغّل الاختبار.

نموذج تنفيذ مُشغِّل الاختبارات

عند تمكين عزل الاختبارات على مستوى العملية، يتم تنفيذ كل ملف اختبار مطابق في عملية فرعية منفصلة. يتم التحكم في الحد الأقصى لعدد العمليات الفرعية التي تعمل في أي وقت بواسطة علامة --test-concurrency. إذا انتهت العملية الفرعية برمز خروج 0، فيعتبر الاختبار ناجحًا. بخلاف ذلك، يعتبر الاختبار فاشلاً. يجب أن تكون ملفات الاختبار قابلة للتنفيذ بواسطة Node.js، ولكن ليس مطلوبًا استخدام وحدة node:test داخليًا.

يتم تنفيذ كل ملف اختبار كما لو كان نصًا برمجيًا عاديًا. أي، إذا كان ملف الاختبار نفسه يستخدم node:test لتحديد الاختبارات، فسيتم تنفيذ كل هذه الاختبارات داخل سلسلة عمليات تطبيق واحدة، بغض النظر عن قيمة خيار concurrency الخاص بـ test().

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

جمع تغطية الكود

[مستقر: 1 - تجريبي]

مستقر: 1 الاستقرار: 1 - تجريبي

عند بدء تشغيل Node.js باستخدام علامة سطر الأوامر --experimental-test-coverage، يتم جمع تغطية الكود ويتم الإبلاغ عن الإحصائيات بمجرد اكتمال جميع الاختبارات. إذا تم استخدام متغير البيئة NODE_V8_COVERAGE لتحديد دليل تغطية الكود، فسيتم كتابة ملفات تغطية V8 التي تم إنشاؤها في هذا الدليل. بشكل افتراضي، لا يتم تضمين وحدات Node.js الأساسية والملفات الموجودة داخل أدلة node_modules/ في تقرير التغطية. ومع ذلك، يمكن تضمينها بشكل صريح عبر علامة --test-coverage-include. بشكل افتراضي، يتم استبعاد جميع ملفات الاختبار المطابقة من تقرير التغطية. يمكن تجاوز الاستثناءات باستخدام علامة --test-coverage-exclude. إذا تم تمكين التغطية، يتم إرسال تقرير التغطية إلى أي مُبلّغ اختبارات عبر حدث 'test:coverage'.

يمكن تعطيل التغطية على سلسلة من الأسطر باستخدام بنية التعليقات التالية:

js
/* node:coverage disable */
if (anAlwaysFalseCondition) {
  // لن يتم تنفيذ الكود في هذا الفرع أبدًا، ولكن يتم تجاهل الأسطر لأغراض التغطية. يتم تجاهل جميع الأسطر التي تلي تعليق "disable"
  // حتى تتم مصادفة تعليق "enable" مطابق.
  console.log('this is never executed');
}
/* node:coverage enable */

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

js
/* node:coverage ignore next */
if (anAlwaysFalseCondition) { console.log('this is never executed'); }

/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
  console.log('this is never executed');
}

مراسلو التغطية

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

bash
node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info
  • لا يتم الإبلاغ عن أي نتائج اختبار بواسطة هذا المراسل.
  • من الناحية المثالية، يجب استخدام هذا المراسل جنبًا إلى جنب مع مراسل آخر.

المحاكاة

تدعم الوحدة node:test المحاكاة أثناء الاختبار عبر كائن mock ذي مستوى أعلى. ينشئ المثال التالي تجسسًا على دالة تجمع رقمين معًا. ثم يتم استخدام التجسس للتأكد من استدعاء الدالة كما هو متوقع.

js
import assert from 'node:assert';
import { mock, test } from 'node:test';

test('يتجسس على دالة', () => {
  const sum = mock.fn((a, b) => {
    return a + b;
  });

  assert.strictEqual(sum.mock.callCount(), 0);
  assert.strictEqual(sum(3, 4), 7);
  assert.strictEqual(sum.mock.callCount(), 1);

  const call = sum.mock.calls[0];
  assert.deepStrictEqual(call.arguments, [3, 4]);
  assert.strictEqual(call.result, 7);
  assert.strictEqual(call.error, undefined);

  // إعادة تعيين عمليات المحاكاة المتعقبة عالميًا.
  mock.reset();
});
js
'use strict';
const assert = require('node:assert');
const { mock, test } = require('node:test');

test('يتجسس على دالة', () => {
  const sum = mock.fn((a, b) => {
    return a + b;
  });

  assert.strictEqual(sum.mock.callCount(), 0);
  assert.strictEqual(sum(3, 4), 7);
  assert.strictEqual(sum.mock.callCount(), 1);

  const call = sum.mock.calls[0];
  assert.deepStrictEqual(call.arguments, [3, 4]);
  assert.strictEqual(call.result, 7);
  assert.strictEqual(call.error, undefined);

  // إعادة تعيين عمليات المحاكاة المتعقبة عالميًا.
  mock.reset();
});

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

js
test('يتجسس على طريقة كائن', (t) => {
  const number = {
    value: 5,
    add(a) {
      return this.value + a;
    },
  };

  t.mock.method(number, 'add');
  assert.strictEqual(number.add.mock.callCount(), 0);
  assert.strictEqual(number.add(3), 8);
  assert.strictEqual(number.add.mock.callCount(), 1);

  const call = number.add.mock.calls[0];

  assert.deepStrictEqual(call.arguments, [3]);
  assert.strictEqual(call.result, 8);
  assert.strictEqual(call.target, undefined);
  assert.strictEqual(call.this, number);
});

المؤقتات

تعتبر المؤقتات الوهمية تقنية شائعة الاستخدام في اختبار البرامج لمحاكاة والتحكم في سلوك المؤقتات، مثل setInterval و setTimeout، دون الانتظار فعليًا للفترات الزمنية المحددة.

راجع الفئة MockTimers للحصول على قائمة كاملة بالطرق والميزات.

يتيح ذلك للمطورين كتابة اختبارات أكثر موثوقية وقابلية للتنبؤ للوظائف التي تعتمد على الوقت.

يوضح المثال أدناه كيفية محاكاة setTimeout. باستخدام .enable({ apis: ['setTimeout'] }); سيقوم بمحاكاة وظائف setTimeout في وحدات node:timers و node:timers/promises، وكذلك من سياق Node.js العام.

ملاحظة: لا يتم دعم تفكيك الدوال مثل import { setTimeout } from 'node:timers' حاليًا بواسطة واجهة برمجة التطبيقات هذه.

js
import assert from 'node:assert';
import { mock, test } from 'node:test';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => {
  const fn = mock.fn();

  // Optionally choose what to mock
  mock.timers.enable({ apis: ['setTimeout'] });
  setTimeout(fn, 9999);
  assert.strictEqual(fn.mock.callCount(), 0);

  // Advance in time
  mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);

  // Reset the globally tracked mocks.
  mock.timers.reset();

  // If you call reset mock instance, it will also reset timers instance
  mock.reset();
});
js
const assert = require('node:assert');
const { mock, test } = require('node:test');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => {
  const fn = mock.fn();

  // Optionally choose what to mock
  mock.timers.enable({ apis: ['setTimeout'] });
  setTimeout(fn, 9999);
  assert.strictEqual(fn.mock.callCount(), 0);

  // Advance in time
  mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);

  // Reset the globally tracked mocks.
  mock.timers.reset();

  // If you call reset mock instance, it will also reset timers instance
  mock.reset();
});

يتم أيضًا عرض نفس وظيفة المحاكاة في خاصية mock على كائن TestContext لكل اختبار. الفائدة من المحاكاة عبر سياق الاختبار هي أن مشغل الاختبار سيستعيد تلقائيًا جميع وظائف المؤقتات المحاكاة بمجرد انتهاء الاختبار.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] });
  setTimeout(fn, 9999);
  assert.strictEqual(fn.mock.callCount(), 0);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] });
  setTimeout(fn, 9999);
  assert.strictEqual(fn.mock.callCount(), 0);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
});

التواريخ

تسمح واجهة برمجة تطبيقات المؤقتات الوهمية أيضًا بمحاكاة كائن Date. هذه ميزة مفيدة لاختبار الوظائف التي تعتمد على الوقت، أو لمحاكاة وظائف التقويم الداخلية مثل Date.now().

يعد تطبيق التواريخ أيضًا جزءًا من فئة MockTimers. ارجع إليها للحصول على قائمة كاملة بالطرق والميزات.

ملاحظة: تعتمد التواريخ والمؤقتات على بعضها البعض عند محاكاتها معًا. هذا يعني أنه إذا كان لديك كل من Date و setTimeout محاكيين، فإن تقديم الوقت سيقدم أيضًا التاريخ المحاكى لأنهما يحاكيان ساعة داخلية واحدة.

يوضح المثال أدناه كيفية محاكاة كائن Date والحصول على قيمة Date.now() الحالية.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks the Date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'] });
  // If not specified, the initial date will be based on 0 in the UNIX epoch
  assert.strictEqual(Date.now(), 0);

  // Advance in time will also advance the date
  context.mock.timers.tick(9999);
  assert.strictEqual(Date.now(), 9999);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks the Date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'] });
  // If not specified, the initial date will be based on 0 in the UNIX epoch
  assert.strictEqual(Date.now(), 0);

  // Advance in time will also advance the date
  context.mock.timers.tick(9999);
  assert.strictEqual(Date.now(), 9999);
});

إذا لم يتم تعيين أي حقبة أولية، فسيعتمد التاريخ الأولي على 0 في حقبة Unix. هذا هو 1 يناير 1970، 00:00:00 بالتوقيت العالمي المنسق. يمكنك تعيين تاريخ أولي عن طريق تمرير خاصية now إلى طريقة .enable(). سيتم استخدام هذه القيمة كتاريخ أولي لكائن Date المحاكى. يمكن أن يكون إما عددًا صحيحًا موجبًا، أو كائن تاريخ آخر.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks the Date object with initial time', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 300);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks the Date object with initial time', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 300);
});

يمكنك استخدام طريقة .setTime() لنقل التاريخ المحاكى يدويًا إلى وقت آخر. تقبل هذه الطريقة عددًا صحيحًا موجبًا فقط.

ملاحظة: ستنفذ هذه الطريقة أي مؤقتات محاكية موجودة في الماضي من الوقت الجديد.

في المثال أدناه، نقوم بتعيين وقت جديد للتاريخ المحاكى.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('sets the time of a date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.setTime(1000);
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 1200);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('sets the time of a date object', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['Date'], now: 100 });
  assert.strictEqual(Date.now(), 100);

  // Advance in time will also advance the date
  context.mock.timers.setTime(1000);
  context.mock.timers.tick(200);
  assert.strictEqual(Date.now(), 1200);
});

إذا كان لديك أي مؤقت تم تعيينه للتشغيل في الماضي، فسيتم تنفيذه كما لو تم استدعاء طريقة .tick(). هذا مفيد إذا كنت تريد اختبار الوظائف التي تعتمد على الوقت والتي حدثت بالفعل في الماضي.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);

  context.mock.timers.setTime(800);
  // Timer is not executed as the time is not yet reached
  assert.strictEqual(fn.mock.callCount(), 0);
  assert.strictEqual(Date.now(), 800);

  context.mock.timers.setTime(1200);
  // Timer is executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 1200);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);

  context.mock.timers.setTime(800);
  // Timer is not executed as the time is not yet reached
  assert.strictEqual(fn.mock.callCount(), 0);
  assert.strictEqual(Date.now(), 800);

  context.mock.timers.setTime(1200);
  // Timer is executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 1200);
});

سيؤدي استخدام .runAll() إلى تنفيذ جميع المؤقتات الموجودة حاليًا في قائمة الانتظار. سيؤدي هذا أيضًا إلى تقديم التاريخ المحاكى إلى وقت آخر مؤقت تم تنفيذه كما لو كان الوقت قد مر.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);
  setTimeout(fn, 2000);
  setTimeout(fn, 3000);

  context.mock.timers.runAll();
  // All timers are executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 3);
  assert.strictEqual(Date.now(), 3000);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('runs timers as setTime passes ticks', (context) => {
  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const fn = context.mock.fn();
  setTimeout(fn, 1000);
  setTimeout(fn, 2000);
  setTimeout(fn, 3000);

  context.mock.timers.runAll();
  // All timers are executed as the time is now reached
  assert.strictEqual(fn.mock.callCount(), 3);
  assert.strictEqual(Date.now(), 3000);
});

اختبار اللقطات

[مستقر: 1 - تجريبي]

مستقر: 1 الاستقرار: 1.0 - تطوير مبكر

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

يتم إنشاء ملفات اللقطات عن طريق بدء Node.js باستخدام علامة سطر الأوامر --test-update-snapshots. يتم إنشاء ملف لقطة منفصل لكل ملف اختبار. بشكل افتراضي، يكون لملف اللقطة نفس اسم ملف الاختبار مع امتداد الملف .snapshot. يمكن تكوين هذا السلوك باستخدام الدالة snapshot.setResolveSnapshotPath(). يتوافق كل تأكيد للقطة مع تصدير في ملف اللقطة.

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

js
// test.js
suite('مجموعة اختبارات اللقطات', () => {
  test('اختبار اللقطة', (t) => {
    t.assert.snapshot({ value1: 1, value2: 2 });
    t.assert.snapshot(5);
  });
});

قم بإنشاء ملف اللقطة عن طريق تشغيل ملف الاختبار باستخدام --test-update-snapshots. يجب أن يجتاز الاختبار، ويتم إنشاء ملف باسم test.js.snapshot في نفس الدليل الذي يوجد به ملف الاختبار. يظهر محتوى ملف اللقطة أدناه. يتم تحديد كل لقطة بالاسم الكامل للاختبار وعداد للتمييز بين اللقطات في نفس الاختبار.

js
exports[`مجموعة اختبارات اللقطات > اختبار اللقطة 1`] = `
{
  "value1": 1,
  "value2": 2
}
`;

exports[`مجموعة اختبارات اللقطات > اختبار اللقطة 2`] = `
5
`;

بمجرد إنشاء ملف اللقطة، قم بتشغيل الاختبارات مرة أخرى بدون علامة --test-update-snapshots. يجب أن تجتاز الاختبارات الآن.

مراسلو الاختبار

[تاريخ]

الإصدارالتغييرات
v19.9.0, v18.17.0يتم الآن عرض المراسلين في node:test/reporters.
v19.6.0, v18.15.0تمت إضافته في: v19.6.0, v18.15.0

تدعم الوحدة node:test تمرير علامات --test-reporter ليستخدم عداء الاختبار مراسلًا محددًا.

المراسلون المضمنون التاليون مدعومون:

  • spec يُخرج المراسل spec نتائج الاختبار بتنسيق يمكن للبشر قراءته. هذا هو المراسل الافتراضي.
  • tap يُخرج المراسل tap نتائج الاختبار بتنسيق TAP.
  • dot يُخرج المراسل dot نتائج الاختبار بتنسيق مضغوط، حيث يتم تمثيل كل اختبار ناجح بـ .، ويتم تمثيل كل اختبار فاشل بـ X.
  • junit يُخرج المراسل junit نتائج الاختبار بتنسيق jUnit XML
  • lcov يُخرج المراسل lcov تغطية الاختبار عند استخدامه مع علامة --experimental-test-coverage.

الإخراج الدقيق لهؤلاء المراسلين عرضة للتغيير بين إصدارات Node.js، ولا ينبغي الاعتماد عليه برمجيًا. إذا كانت هناك حاجة للوصول البرمجي إلى إخراج عداء الاختبار، فاستخدم الأحداث التي تنبعث من <TestsStream>.

تتوفر المراسلون عبر الوحدة node:test/reporters:

js
import { tap, spec, dot, junit, lcov } from 'node:test/reporters';
js
const { tap, spec, dot, junit, lcov } = require('node:test/reporters');

مراسلون مخصصون

يمكن استخدام --test-reporter لتحديد مسار إلى مراسل مخصص. المراسل المخصص هو وحدة تصدر قيمة مقبولة بواسطة stream.compose. يجب أن تحول المراسلون الأحداث التي تنبعث من <TestsStream>

مثال على مراسل مخصص باستخدام <stream.Transform>:

js
import { Transform } from 'node:stream';

const customReporter = new Transform({
  writableObjectMode: true,
  transform(event, encoding, callback) {
    switch (event.type) {
      case 'test:dequeue':
        callback(null, `test ${event.data.name} dequeued`);
        break;
      case 'test:enqueue':
        callback(null, `test ${event.data.name} enqueued`);
        break;
      case 'test:watch:drained':
        callback(null, 'test watch queue drained');
        break;
      case 'test:start':
        callback(null, `test ${event.data.name} started`);
        break;
      case 'test:pass':
        callback(null, `test ${event.data.name} passed`);
        break;
      case 'test:fail':
        callback(null, `test ${event.data.name} failed`);
        break;
      case 'test:plan':
        callback(null, 'test plan');
        break;
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        callback(null, event.data.message);
        break;
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals;
        callback(null, `total line count: ${totalLineCount}\n`);
        break;
      }
    }
  },
});

export default customReporter;
js
const { Transform } = require('node:stream');

const customReporter = new Transform({
  writableObjectMode: true,
  transform(event, encoding, callback) {
    switch (event.type) {
      case 'test:dequeue':
        callback(null, `test ${event.data.name} dequeued`);
        break;
      case 'test:enqueue':
        callback(null, `test ${event.data.name} enqueued`);
        break;
      case 'test:watch:drained':
        callback(null, 'test watch queue drained');
        break;
      case 'test:start':
        callback(null, `test ${event.data.name} started`);
        break;
      case 'test:pass':
        callback(null, `test ${event.data.name} passed`);
        break;
      case 'test:fail':
        callback(null, `test ${event.data.name} failed`);
        break;
      case 'test:plan':
        callback(null, 'test plan');
        break;
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        callback(null, event.data.message);
        break;
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals;
        callback(null, `total line count: ${totalLineCount}\n`);
        break;
      }
    }
  },
});

module.exports = customReporter;

مثال على مراسل مخصص باستخدام دالة مولد:

js
export default async function * customReporter(source) {
  for await (const event of source) {
    switch (event.type) {
      case 'test:dequeue':
        yield `test ${event.data.name} dequeued\n`;
        break;
      case 'test:enqueue':
        yield `test ${event.data.name} enqueued\n`;
        break;
      case 'test:watch:drained':
        yield 'test watch queue drained\n';
        break;
      case 'test:start':
        yield `test ${event.data.name} started\n`;
        break;
      case 'test:pass':
        yield `test ${event.data.name} passed\n`;
        break;
      case 'test:fail':
        yield `test ${event.data.name} failed\n`;
        break;
      case 'test:plan':
        yield 'test plan\n';
        break;
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        yield `${event.data.message}\n`;
        break;
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals;
        yield `total line count: ${totalLineCount}\n`;
        break;
      }
    }
  }
}
js
module.exports = async function * customReporter(source) {
  for await (const event of source) {
    switch (event.type) {
      case 'test:dequeue':
        yield `test ${event.data.name} dequeued\n`;
        break;
      case 'test:enqueue':
        yield `test ${event.data.name} enqueued\n`;
        break;
      case 'test:watch:drained':
        yield 'test watch queue drained\n';
        break;
      case 'test:start':
        yield `test ${event.data.name} started\n`;
        break;
      case 'test:pass':
        yield `test ${event.data.name} passed\n`;
        break;
      case 'test:fail':
        yield `test ${event.data.name} failed\n`;
        break;
      case 'test:plan':
        yield 'test plan\n';
        break;
      case 'test:diagnostic':
      case 'test:stderr':
      case 'test:stdout':
        yield `${event.data.message}\n`;
        break;
      case 'test:coverage': {
        const { totalLineCount } = event.data.summary.totals;
        yield `total line count: ${totalLineCount}\n`;
        break;
      }
    }
  }
};

يجب أن تكون القيمة المقدمة إلى --test-reporter عبارة عن سلسلة مثل تلك المستخدمة في import() في كود JavaScript، أو قيمة مقدمة لـ --import.

مراسلون متعددون

يمكن تحديد العلامة --test-reporter عدة مرات للإبلاغ عن نتائج الاختبار بتنسيقات متعددة. في هذه الحالة، من الضروري تحديد وجهة لكل مراسل باستخدام --test-reporter-destination. يمكن أن تكون الوجهة stdout أو stderr أو مسار ملف. يتم إقران المراسلين والوجهات وفقًا للترتيب الذي تم تحديده.

في المثال التالي، سيتم إخراج مراسل spec إلى stdout، وسيتم إخراج مراسل dot إلى file.txt:

bash
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txt

عند تحديد مراسل واحد، ستكون الوجهة افتراضيًا stdout، ما لم يتم توفير وجهة بشكل صريح.

run([options])

[سجل التغييرات]

الإصدارالتغييرات
v23.0.0تمت إضافة خيار cwd.
v23.0.0تمت إضافة خيارات التغطية.
v22.8.0تمت إضافة خيار isolation.
v22.6.0تمت إضافة خيار globPatterns.
v22.0.0, v20.14.0تمت إضافة خيار forceExit.
v20.1.0, v18.17.0تمت إضافة خيار testNamePatterns.
v18.9.0, v16.19.0تمت إضافته في: v18.9.0, v16.19.0
  • options <Object> خيارات تكوين لتشغيل الاختبارات. الخصائص التالية مدعومة:

    • concurrency <number> | <boolean> إذا تم توفير رقم، فسيتم تشغيل هذا العدد من عمليات الاختبار بالتوازي، حيث تتوافق كل عملية مع ملف اختبار واحد. إذا كان true، فسيتم تشغيل os.availableParallelism() - 1 ملف اختبار بالتوازي. إذا كان false، فسيتم تشغيل ملف اختبار واحد فقط في كل مرة. افتراضي: false.

    • cwd: <string> يحدد دليل العمل الحالي الذي سيستخدمه مشغل الاختبار. يعمل كمسار أساسي لحل الملفات وفقًا لـ نموذج تنفيذ مشغل الاختبار. افتراضي: process.cwd().

    • files: <Array> مصفوفة تحتوي على قائمة الملفات المراد تشغيلها. افتراضي: مطابقة الملفات من نموذج تنفيذ مشغل الاختبار.

    • forceExit: <boolean> يقوم بتكوين مشغل الاختبار للخروج من العملية بمجرد انتهاء جميع الاختبارات المعروفة من التنفيذ حتى إذا ظلت حلقة الأحداث نشطة بخلاف ذلك. افتراضي: false.

    • globPatterns: <Array> مصفوفة تحتوي على قائمة أنماط glob لمطابقة ملفات الاختبار. لا يمكن استخدام هذا الخيار مع files. افتراضي: مطابقة الملفات من نموذج تنفيذ مشغل الاختبار.

    • inspectPort <number> | <Function> يعين منفذ الفحص لعملية اختبار فرعية. يمكن أن يكون هذا رقمًا أو دالة لا تأخذ أي وسيطات وترجع رقمًا. إذا تم توفير قيمة خالية، فستحصل كل عملية على منفذ خاص بها، يتم زيادته من process.debugPort الرئيسي. يتم تجاهل هذا الخيار إذا تم تعيين خيار isolation على 'none' حيث لا يتم إنشاء أي عمليات فرعية. افتراضي: undefined.

    • isolation <string> يقوم بتكوين نوع عزل الاختبار. إذا تم تعيينه على 'process'، فسيتم تشغيل كل ملف اختبار في عملية فرعية منفصلة. إذا تم تعيينه على 'none'، فسيتم تشغيل جميع ملفات الاختبار في العملية الحالية. افتراضي: 'process'.

    • only: <boolean> إذا كانت القيمة صحيحة، فسياق الاختبار سيقوم فقط بتشغيل الاختبارات التي تم تعيين خيار only لها

    • setup <Function> دالة تقبل مثيل TestsStream ويمكن استخدامها لإعداد المستمعين قبل تشغيل أي اختبارات. افتراضي: undefined.

    • execArgv <Array> مصفوفة من علامات CLI لتمريرها إلى الملف التنفيذي node عند إنشاء العمليات الفرعية. ليس لهذا الخيار أي تأثير عندما يكون isolation هو 'none'. افتراضي: []

    • argv <Array> مصفوفة من علامات CLI لتمريرها إلى كل ملف اختبار عند إنشاء العمليات الفرعية. ليس لهذا الخيار أي تأثير عندما يكون isolation هو 'none'. افتراضي: [].

    • signal <AbortSignal> يسمح بإجهاض تنفيذ اختبار قيد التقدم.

    • testNamePatterns <string> | <RegExp> | <Array> سلسلة أو تعبير RegExp أو مصفوفة RegExp، يمكن استخدامها لتشغيل الاختبارات فقط التي يتطابق اسمها مع النمط المقدم. يتم تفسير أنماط أسماء الاختبارات كتعبيرات JavaScript منتظمة. لكل اختبار يتم تنفيذه، يتم أيضًا تشغيل أي خطافات اختبار مقابلة، مثل beforeEach(). افتراضي: undefined.

    • testSkipPatterns <string> | <RegExp> | <Array> سلسلة أو تعبير RegExp أو مصفوفة RegExp، يمكن استخدامها لاستبعاد تشغيل الاختبارات التي يتطابق اسمها مع النمط المقدم. يتم تفسير أنماط أسماء الاختبارات كتعبيرات JavaScript منتظمة. لكل اختبار يتم تنفيذه، يتم أيضًا تشغيل أي خطافات اختبار مقابلة، مثل beforeEach(). افتراضي: undefined.

    • timeout <number> عدد بالمللي ثانية سيفشل تنفيذ الاختبار بعده. إذا لم يتم تحديده، فسوف ترث الاختبارات الفرعية هذه القيمة من الأصل. افتراضي: Infinity.

    • watch <boolean> ما إذا كان سيتم التشغيل في وضع المراقبة أم لا. افتراضي: false.

    • shard <Object> تشغيل الاختبارات في جزء معين. افتراضي: undefined.

      • index <number> هو عدد صحيح موجب بين 1 و \<total\> يحدد فهرس الجزء المراد تشغيله. هذا الخيار مطلوب.
      • total <number> هو عدد صحيح موجب يحدد العدد الإجمالي للأجزاء المراد تقسيم ملفات الاختبار إليها. هذا الخيار مطلوب.
    • coverage <boolean> تمكين جمع تغطية التعليمات البرمجية. افتراضي: false.

    • coverageExcludeGlobs <string> | <Array> يستبعد ملفات معينة من تغطية التعليمات البرمجية باستخدام نمط glob، والذي يمكن أن يطابق مسارات الملفات المطلقة والنسبية. هذه الخاصية قابلة للتطبيق فقط عند تعيين coverage على true. إذا تم توفير كل من coverageExcludeGlobs و coverageIncludeGlobs، فيجب أن تفي الملفات بكلتا المعايير ليتم تضمينها في تقرير التغطية. افتراضي: undefined.

    • coverageIncludeGlobs <string> | <Array> يتضمن ملفات معينة في تغطية التعليمات البرمجية باستخدام نمط glob، والذي يمكن أن يطابق مسارات الملفات المطلقة والنسبية. هذه الخاصية قابلة للتطبيق فقط عند تعيين coverage على true. إذا تم توفير كل من coverageExcludeGlobs و coverageIncludeGlobs، فيجب أن تفي الملفات بكلتا المعايير ليتم تضمينها في تقرير التغطية. افتراضي: undefined.

    • lineCoverage <number> يتطلب الحد الأدنى من النسبة المئوية للأسطر المغطاة. إذا لم تصل تغطية التعليمات البرمجية إلى الحد الأدنى المحدد، فستخرج العملية بالرمز 1. افتراضي: 0.

    • branchCoverage <number> يتطلب الحد الأدنى من النسبة المئوية للفروع المغطاة. إذا لم تصل تغطية التعليمات البرمجية إلى الحد الأدنى المحدد، فستخرج العملية بالرمز 1. افتراضي: 0.

    • functionCoverage <number> يتطلب الحد الأدنى من النسبة المئوية للدوال المغطاة. إذا لم تصل تغطية التعليمات البرمجية إلى الحد الأدنى المحدد، فستخرج العملية بالرمز 1. افتراضي: 0.

  • الإرجاع: <TestsStream>

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

js
import { tap } from 'node:test/reporters';
import { run } from 'node:test';
import process from 'node:process';
import path from 'node:path';

run({ files: [path.resolve('./tests/test.js')] })
 .on('test:fail', () => {
   process.exitCode = 1;
 })
 .compose(tap)
 .pipe(process.stdout);
js
const { tap } = require('node:test/reporters');
const { run } = require('node:test');
const path = require('node:path');

run({ files: [path.resolve('./tests/test.js')] })
 .on('test:fail', () => {
   process.exitCode = 1;
 })
 .compose(tap)
 .pipe(process.stdout);

suite([name][, options][, fn])

تمت الإضافة في: v22.0.0, v20.13.0

  • name <string> اسم المجموعة، والذي يتم عرضه عند الإبلاغ عن نتائج الاختبار. افتراضي: خاصية name الخاصة بـ fn، أو '\<anonymous\>' إذا لم يكن لـ fn اسم.
  • options <Object> خيارات تكوين اختيارية للمجموعة. يدعم هذا نفس خيارات test([name][, options][, fn]).
  • fn <Function> | <AsyncFunction> دالة المجموعة التي تعلن عن الاختبارات والمجموعات المتداخلة. الوسيطة الأولى لهذه الدالة هي كائن SuiteContext. افتراضي: دالة لا تقوم بأي عملية.
  • الإرجاع: <Promise> تم تحقيقه على الفور بـ undefined.

يتم استيراد الدالة suite() من الوحدة node:test.

suite.skip([name][, options][, fn])

تمت الإضافة في: v22.0.0, v20.13.0

اختصار لتخطي مجموعة. هذا هو نفسه suite([name], { skip: true }[, fn]).

suite.todo([name][, options][, fn])

تمت الإضافة في: v22.0.0, v20.13.0

اختصار لتعليم مجموعة على أنها TODO. هذا هو نفسه suite([name], { todo: true }[, fn]).

suite.only([name][, options][, fn])

تمت الإضافة في: v22.0.0, v20.13.0

اختصار لتعليم مجموعة على أنها only. هذا هو نفسه suite([name], { only: true }[, fn]).

test([name][, options][, fn])

[سجل التغييرات]

الإصدارالتغييرات
v20.2.0, v18.17.0تمت إضافة الاختصارات skip و todo و only.
v18.8.0, v16.18.0إضافة خيار signal.
v18.7.0, v16.17.0إضافة خيار timeout.
v18.0.0, v16.17.0تمت الإضافة في: v18.0.0, v16.17.0
  • name <string> اسم الاختبار، والذي يتم عرضه عند الإبلاغ عن نتائج الاختبار. افتراضي: خاصية name الخاصة بـ fn، أو '\<anonymous\>' إذا لم يكن لـ fn اسم.

  • options <Object> خيارات تكوين للاختبار. يتم دعم الخصائص التالية:

    • concurrency <number> | <boolean> إذا تم توفير رقم، فسيتم تشغيل هذا العدد من الاختبارات بالتوازي داخل سلسلة عمليات التطبيق. إذا كانت true، فسيتم تشغيل جميع الاختبارات غير المتزامنة المجدولة بالتوازي داخل سلسلة العمليات. إذا كانت false، فسيتم تشغيل اختبار واحد فقط في كل مرة. إذا لم يتم تحديده، فستَرِث الاختبارات الفرعية هذه القيمة من أصلها. افتراضي: false.
    • only <boolean> إذا كانت قيمة حقيقية، وتم تكوين سياق الاختبار لتشغيل اختبارات only، فسيتم تشغيل هذا الاختبار. وإلا، فسيتم تخطي الاختبار. افتراضي: false.
    • signal <AbortSignal> يسمح بإحباط اختبار قيد التقدم.
    • skip <boolean> | <string> إذا كانت قيمة حقيقية، فسيتم تخطي الاختبار. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لتخطي الاختبار. افتراضي: false.
    • todo <boolean> | <string> إذا كانت قيمة حقيقية، فسيتم تعليم الاختبار على أنه TODO. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لكون الاختبار TODO. افتراضي: false.
    • timeout <number> عدد بالمللي ثانية سيفشل الاختبار بعده. إذا لم يتم تحديده، فستَرِث الاختبارات الفرعية هذه القيمة من أصلها. افتراضي: Infinity.
    • plan <number> عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها في الاختبار. إذا كان عدد التأكيدات التي تم تشغيلها في الاختبار لا يتطابق مع الرقم المحدد في الخطة، فسيفشل الاختبار. افتراضي: undefined.
  • fn <Function> | <AsyncFunction> الدالة قيد الاختبار. الوسيطة الأولى لهذه الدالة هي كائن TestContext. إذا كان الاختبار يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كوسيطة ثانية. افتراضي: دالة لا تقوم بأي عملية.

  • الإرجاع: <Promise> تم تحقيقه بـ undefined بمجرد اكتمال الاختبار، أو على الفور إذا تم تشغيل الاختبار داخل مجموعة.

الدالة test() هي القيمة المستوردة من الوحدة test. يؤدي كل استدعاء لهذه الدالة إلى الإبلاغ عن الاختبار إلى <TestsStream>.

يمكن استخدام كائن TestContext الذي تم تمريره إلى الوسيطة fn لتنفيذ الإجراءات المتعلقة بالاختبار الحالي. تتضمن الأمثلة تخطي الاختبار أو إضافة معلومات تشخيصية إضافية أو إنشاء اختبارات فرعية.

تُرجع test()Promise يتم تحقيقه بمجرد اكتمال الاختبار. إذا تم استدعاء test() داخل مجموعة، فإنه يتحقق على الفور. يمكن عادةً تجاهل القيمة المرجعة للاختبارات ذات المستوى الأعلى. ومع ذلك، يجب استخدام القيمة المرجعة من الاختبارات الفرعية لمنع الاختبار الأصل من الانتهاء أولاً وإلغاء الاختبار الفرعي كما هو موضح في المثال التالي.

js
test('top level test', async (t) => {
  // The setTimeout() in the following subtest would cause it to outlive its
  // parent test if 'await' is removed on the next line. Once the parent test
  // completes, it will cancel any outstanding subtests.
  await t.test('longer running subtest', async (t) => {
    return new Promise((resolve, reject) => {
      setTimeout(resolve, 1000);
    });
  });
});

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

test.skip([name][, options][, fn])

اختصار لتخطي اختبار، نفس test([name], { skip: true }[, fn]).

test.todo([name][, options][, fn])

اختصار لتعليم اختبار كـ TODO، نفس test([name], { todo: true }[, fn]).

test.only([name][, options][, fn])

اختصار لتعليم اختبار كـ only، نفس test([name], { only: true }[, fn]).

describe([name][, options][, fn])

اسم مستعار لـ suite().

يتم استيراد الدالة describe() من الوحدة node:test.

describe.skip([name][, options][, fn])

اختصار لتخطي مجموعة اختبار. هذا هو نفسه describe([name], { skip: true }[, fn]).

describe.todo([name][, options][, fn])

اختصار لتعليم مجموعة اختبار كـ TODO. هذا هو نفسه describe([name], { todo: true }[, fn]).

describe.only([name][, options][, fn])

أضيف في: الإصدار 19.8.0، الإصدار 18.15.0

اختصار لتعليم مجموعة اختبار كـ only. هذا هو نفسه describe([name], { only: true }[, fn]).

it([name][, options][, fn])

[سجل التغييرات]

الإصدارالتغييرات
الإصدار 19.8.0، الإصدار 18.16.0استدعاء it() الآن مكافئ لاستدعاء test().
الإصدار 18.6.0، الإصدار 16.17.0أضيف في: الإصدار 18.6.0، الإصدار 16.17.0

اسم مستعار لـ test().

يتم استيراد الدالة it() من الوحدة node:test.

it.skip([name][, options][, fn])

اختصار لتخطي اختبار، نفس it([name], { skip: true }[, fn]).

it.todo([name][, options][, fn])

اختصار لتعليم اختبار كـ TODO، نفس it([name], { todo: true }[, fn]).

it.only([name][, options][, fn])

أضيف في: الإصدار 19.8.0، الإصدار 18.15.0

اختصار لتعليم اختبار كـ only، نفس it([name], { only: true }[, fn]).

before([fn][, options])

تمت الإضافة في: v18.8.0، v16.18.0

  • fn <Function> | <AsyncFunction> دالة الربط. إذا كان الربط يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كمعامل ثاني. افتراضي: دالة لا تفعل شيئًا.
  • options <Object> خيارات التكوين للربط. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإلغاء ربط قيد التقدم.
    • timeout <number> عدد المللي ثانية التي سيفشل بعدها الربط. إذا لم يتم تحديده، فسترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. افتراضي: Infinity.

تقوم هذه الدالة بإنشاء ربط يتم تشغيله قبل تنفيذ مجموعة.

js
describe('tests', async () => {
  before(() => console.log('about to run some test'));
  it('is a subtest', () => {
    assert.ok('some relevant assertion here');
  });
});

after([fn][, options])

تمت الإضافة في: v18.8.0، v16.18.0

  • fn <Function> | <AsyncFunction> دالة الربط. إذا كان الربط يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كمعامل ثاني. افتراضي: دالة لا تفعل شيئًا.
  • options <Object> خيارات التكوين للربط. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإلغاء ربط قيد التقدم.
    • timeout <number> عدد المللي ثانية التي سيفشل بعدها الربط. إذا لم يتم تحديده، فسترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. افتراضي: Infinity.

تقوم هذه الدالة بإنشاء ربط يتم تشغيله بعد تنفيذ مجموعة.

js
describe('tests', async () => {
  after(() => console.log('finished running tests'));
  it('is a subtest', () => {
    assert.ok('some relevant assertion here');
  });
});

ملاحظة: يتم ضمان تشغيل الربط after، حتى إذا فشلت الاختبارات داخل المجموعة.

beforeEach([fn][, options])

أُضيف في: v18.8.0، v16.18.0

  • fn <Function> | <AsyncFunction> دالة الخطاف (hook). إذا كان الخطاف يستخدم ردود النداء (callbacks)، يتم تمرير دالة رد النداء كمعامل ثانٍ. الافتراضي: دالة فارغة (no-op).
  • options <Object> خيارات التكوين للخطاف. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإجهاض خطاف قيد التقدم.
    • timeout <number> عدد من المللي ثانية سيفشل الخطاف بعدها. إذا لم يتم تحديده، سترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. الافتراضي: Infinity.

تقوم هذه الدالة بإنشاء خطاف يتم تشغيله قبل كل اختبار في المجموعة الحالية.

js
describe('tests', async () => {
  beforeEach(() => console.log('about to run a test'));
  it('is a subtest', () => {
    assert.ok('some relevant assertion here');
  });
});

afterEach([fn][, options])

أُضيف في: v18.8.0، v16.18.0

  • fn <Function> | <AsyncFunction> دالة الخطاف (hook). إذا كان الخطاف يستخدم ردود النداء (callbacks)، يتم تمرير دالة رد النداء كمعامل ثانٍ. الافتراضي: دالة فارغة (no-op).
  • options <Object> خيارات التكوين للخطاف. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإجهاض خطاف قيد التقدم.
    • timeout <number> عدد من المللي ثانية سيفشل الخطاف بعدها. إذا لم يتم تحديده، سترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. الافتراضي: Infinity.

تقوم هذه الدالة بإنشاء خطاف يتم تشغيله بعد كل اختبار في المجموعة الحالية. يتم تشغيل خطاف afterEach() حتى إذا فشل الاختبار.

js
describe('tests', async () => {
  afterEach(() => console.log('finished running a test'));
  it('is a subtest', () => {
    assert.ok('some relevant assertion here');
  });
});

snapshot

أُضيف في: الإصدار v22.3.0

[ثابت: 1 - تجريبي]

ثابت: 1 الثبات: 1.0 - تطوير مبكر

كائن تُستخدم طرقه لتكوين إعدادات اللقطات الافتراضية في العملية الحالية. من الممكن تطبيق نفس التكوين على جميع الملفات عن طريق وضع كود التكوين الشائع في وحدة تم تحميلها مسبقًا باستخدام --require أو --import.

snapshot.setDefaultSnapshotSerializers(serializers)

أُضيف في: الإصدار v22.3.0

[ثابت: 1 - تجريبي]

ثابت: 1 الثبات: 1.0 - تطوير مبكر

  • serializers <Array> مصفوفة من الدوال المتزامنة المستخدمة كمسلسلات افتراضية لاختبارات اللقطات.

تُستخدم هذه الدالة لتخصيص آلية التسلسل الافتراضية المستخدمة من قِبل مُشغِّل الاختبار. بشكل افتراضي، يقوم مُشغِّل الاختبار بتنفيذ التسلسل عن طريق استدعاء JSON.stringify(value, null, 2) على القيمة المُقدَّمة. JSON.stringify() لديها قيود فيما يتعلق بالهياكل الدائرية وأنواع البيانات المدعومة. إذا كانت هناك حاجة إلى آلية تسلسل أكثر قوة، فيجب استخدام هذه الدالة.

snapshot.setResolveSnapshotPath(fn)

أُضيف في: الإصدار v22.3.0

[ثابت: 1 - تجريبي]

ثابت: 1 الثبات: 1.0 - تطوير مبكر

  • fn <Function> دالة تُستخدم لحساب موقع ملف اللقطة. تتلقى الدالة مسار ملف الاختبار كوسيطتها الوحيدة. إذا لم يكن الاختبار مرتبطًا بملف (على سبيل المثال في REPL)، يكون الإدخال غير مُعرَّف. يجب أن تُرجع fn() سلسلة تحدد موقع ملف اللقطة.

تُستخدم هذه الدالة لتخصيص موقع ملف اللقطة المستخدم لاختبار اللقطات. بشكل افتراضي، يكون اسم ملف اللقطة هو نفسه اسم ملف نقطة الإدخال بامتداد ملف .snapshot.

الفئة: MockFunctionContext

تمت الإضافة في: الإصدار v19.1.0، v18.13.0

تُستخدم الفئة MockFunctionContext لفحص أو معالجة سلوك النماذج الوهمية التي تم إنشاؤها عبر واجهات برمجة التطبيقات MockTracker.

ctx.calls

تمت الإضافة في: الإصدار v19.1.0، v18.13.0

دالة جلب (getter) تُرجع نسخة من المصفوفة الداخلية المستخدمة لتتبع استدعاءات النموذج الوهمي. كل إدخال في المصفوفة هو كائن له الخصائص التالية.

  • arguments <Array> مصفوفة من الوسائط التي تم تمريرها إلى الدالة الوهمية.
  • error <any> إذا أطلقت الدالة الوهمية استثناءً، فستحتوي هذه الخاصية على القيمة التي تم إطلاقها. افتراضي: undefined.
  • result <any> القيمة التي تم إرجاعها بواسطة الدالة الوهمية.
  • stack <Error> كائن Error يمكن استخدام مكدسه لتحديد موقع الاستدعاء لاستدعاء الدالة الوهمية.
  • target <Function> | <undefined> إذا كانت الدالة الوهمية هي دالة إنشاء (constructor)، فسيحتوي هذا الحقل على الفئة التي يتم إنشاؤها. بخلاف ذلك، سيكون هذا undefined.
  • this <any> قيمة this الخاصة بالدالة الوهمية.

ctx.callCount()

تمت الإضافة في: الإصدار v19.1.0، v18.13.0

  • الإرجاع: <integer> عدد المرات التي تم فيها استدعاء هذا النموذج الوهمي.

تُرجع هذه الدالة عدد المرات التي تم فيها استدعاء هذا النموذج الوهمي. هذه الدالة أكثر كفاءة من التحقق من ctx.calls.length لأن ctx.calls هي دالة جلب (getter) تنشئ نسخة من مصفوفة تتبع الاستدعاءات الداخلية.

ctx.mockImplementation(implementation)

أُضيف في: v19.1.0، v18.13.0

تُستخدم هذه الدالة لتغيير سلوك نموذج موجود.

ينشئ المثال التالي دالة نموذجية باستخدام t.mock.fn()، ويستدعي الدالة النموذجية، ثم يغير تطبيق النموذج إلى دالة مختلفة.

js
test('يغير سلوك النموذج', (t) => {
  let cnt = 0;

  function addOne() {
    cnt++;
    return cnt;
  }

  function addTwo() {
    cnt += 2;
    return cnt;
  }

  const fn = t.mock.fn(addOne);

  assert.strictEqual(fn(), 1);
  fn.mock.mockImplementation(addTwo);
  assert.strictEqual(fn(), 3);
  assert.strictEqual(fn(), 5);
});

ctx.mockImplementationOnce(implementation[, onCall])

أُضيف في: v19.1.0، v18.13.0

  • implementation <Function> | <AsyncFunction> الدالة التي ستستخدم كتطبيق للنموذج لرقم الاستدعاء المحدد بواسطة onCall.
  • onCall <integer> رقم الاستدعاء الذي سيستخدم implementation. إذا حدث الاستدعاء المحدد بالفعل، فسيتم طرح استثناء. افتراضي: عدد الاستدعاء التالي.

تُستخدم هذه الدالة لتغيير سلوك نموذج موجود لاستدعاء واحد. بمجرد حدوث الاستدعاء onCall، سيعود النموذج إلى أي سلوك كان سيستخدمه لو لم يتم استدعاء mockImplementationOnce().

ينشئ المثال التالي دالة نموذجية باستخدام t.mock.fn()، ويستدعي الدالة النموذجية، ويغير تطبيق النموذج إلى دالة مختلفة للاستدعاء التالي، ثم يستأنف سلوكه السابق.

js
test('يغير سلوك النموذج مرة واحدة', (t) => {
  let cnt = 0;

  function addOne() {
    cnt++;
    return cnt;
  }

  function addTwo() {
    cnt += 2;
    return cnt;
  }

  const fn = t.mock.fn(addOne);

  assert.strictEqual(fn(), 1);
  fn.mock.mockImplementationOnce(addTwo);
  assert.strictEqual(fn(), 3);
  assert.strictEqual(fn(), 4);
});

ctx.resetCalls()

أُضيف في: v19.3.0، v18.13.0

يعيد ضبط سجل الاستدعاءات للدالة الوهمية.

ctx.restore()

أُضيف في: v19.1.0، v18.13.0

يعيد ضبط تنفيذ الدالة الوهمية إلى سلوكها الأصلي. لا يزال بالإمكان استخدام الوهمي بعد استدعاء هذه الدالة.

صنف: MockModuleContext

أُضيف في: v22.3.0، v20.18.0

[مستقر: 1 - تجريبي]

مستقر: 1 الاستقرار: 1.0 - تطوير مبكر

يُستخدم الصنف MockModuleContext للتلاعب بسلوك وحدات النماذج الوهمية التي تم إنشاؤها عبر واجهات برمجة التطبيقات MockTracker.

ctx.restore()

أُضيف في: v22.3.0، v20.18.0

يعيد ضبط تنفيذ الوحدة الوهمية.

صنف: MockTracker

أُضيف في: v19.1.0، v18.13.0

يُستخدم الصنف MockTracker لإدارة وظائف المحاكاة الوهمية. توفر وحدة تشغيل الاختبار تصديرًا عالي المستوى mock وهو مثيل MockTracker. يوفر كل اختبار أيضًا مثيل MockTracker الخاص به عبر خاصية mock الخاصة بسياق الاختبار.

mock.fn([original[, implementation]][, options])

أُضيف في: v19.1.0، v18.13.0

  • original <Function> | <AsyncFunction> دالة اختيارية لإنشاء وهمي عليها. افتراضي: دالة لا تفعل شيئًا.

  • implementation <Function> | <AsyncFunction> دالة اختيارية تُستخدم كتنفيذ وهمي لـ original. هذا مفيد لإنشاء نماذج وهمية تعرض سلوكًا واحدًا لعدد محدد من الاستدعاءات ثم استعادة سلوك original. افتراضي: الدالة المحددة بواسطة original.

  • options <Object> خيارات التكوين الاختيارية للدالة الوهمية. الخصائص التالية مدعومة:

    • times <integer> عدد المرات التي سيستخدم فيها الوهمي سلوك implementation. بمجرد استدعاء الدالة الوهمية times مرات، ستستعيد تلقائيًا سلوك original. يجب أن تكون هذه القيمة عددًا صحيحًا أكبر من الصفر. افتراضي: Infinity.
  • إرجاع: <Proxy> الدالة الوهمية. تحتوي الدالة الوهمية على خاصية mock خاصة، وهي مثيل لـ MockFunctionContext، ويمكن استخدامها لفحص وتغيير سلوك الدالة الوهمية.

تُستخدم هذه الدالة لإنشاء دالة وهمية.

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

js
test('mocks a counting function', (t) => {
  let cnt = 0;

  function addOne() {
    cnt++;
    return cnt;
  }

  function addTwo() {
    cnt += 2;
    return cnt;
  }

  const fn = t.mock.fn(addOne, addTwo, { times: 2 });

  assert.strictEqual(fn(), 2);
  assert.strictEqual(fn(), 4);
  assert.strictEqual(fn(), 5);
  assert.strictEqual(fn(), 6);
});

mock.getter(object, methodName[, implementation][, options])

تمت الإضافة في: الإصدار v19.3.0, v18.13.0

هذه الوظيفة هي عبارة عن تسهيل نحوي لـ MockTracker.method مع تعيين options.getter على true.

mock.method(object, methodName[, implementation][, options])

تمت الإضافة في: الإصدار v19.1.0, v18.13.0

  • object <Object> الكائن الذي يتم محاكاة طريقته.

  • methodName <string> | <symbol> مُعرّف الطريقة الموجودة على object المراد محاكاتها. إذا لم يكن object[methodName] دالة، فسيتم طرح خطأ.

  • implementation <Function> | <AsyncFunction> دالة اختيارية تُستخدم كتطبيق وهمي لـ object[methodName]. الافتراضي: الطريقة الأصلية المحددة بواسطة object[methodName].

  • options <Object> خيارات تكوين اختيارية للطريقة الوهمية. الخصائص التالية مدعومة:

    • getter <boolean> إذا كانت true، فسيتم التعامل مع object[methodName] على أنها مُجلب. لا يمكن استخدام هذا الخيار مع خيار setter. الافتراضي: false.
    • setter <boolean> إذا كانت true، فسيتم التعامل مع object[methodName] على أنها مُعدِّل. لا يمكن استخدام هذا الخيار مع خيار getter. الافتراضي: false.
    • times <integer> عدد المرات التي سيستخدم فيها النموذج الوهمي سلوك implementation. بمجرد استدعاء الطريقة الوهمية times مرة، سيتم استعادة السلوك الأصلي تلقائيًا. يجب أن تكون هذه القيمة عددًا صحيحًا أكبر من صفر. الافتراضي: Infinity.
  • Returns: <Proxy> الطريقة الوهمية. تحتوي الطريقة الوهمية على خاصية mock خاصة، وهي عبارة عن نسخة من MockFunctionContext، ويمكن استخدامها لفحص وتغيير سلوك الطريقة الوهمية.

تُستخدم هذه الوظيفة لإنشاء نموذج وهمي لطريقة كائن موجودة. يوضح المثال التالي كيفية إنشاء نموذج وهمي لطريقة كائن موجودة.

js
test('تجسس على طريقة كائن', (t) => {
  const number = {
    value: 5,
    subtract(a) {
      return this.value - a;
    },
  };

  t.mock.method(number, 'subtract');
  assert.strictEqual(number.subtract.mock.callCount(), 0);
  assert.strictEqual(number.subtract(3), 2);
  assert.strictEqual(number.subtract.mock.callCount(), 1);

  const call = number.subtract.mock.calls[0];

  assert.deepStrictEqual(call.arguments, [3]);
  assert.strictEqual(call.result, 2);
  assert.strictEqual(call.error, undefined);
  assert.strictEqual(call.target, undefined);
  assert.strictEqual(call.this, number);
});

mock.module(specifier[, options])

تمت الإضافة في: v22.3.0, v20.18.0

[مستقر: 1 - تجريبي]

مستقر: 1 الاستقرار: 1.0 - تطوير مبكر

  • specifier <string> | <URL> سلسلة تعريف الوحدة النمطية المراد محاكاتها.

  • options <Object> خيارات تكوين اختيارية لوحدة المحاكاة. الخصائص التالية مدعومة:

    • cache <boolean> إذا كانت false، فإن كل استدعاء لـ require() أو import() سيولد وحدة محاكاة جديدة. إذا كانت true، فإن الاستدعاءات اللاحقة ستعيد نفس وحدة المحاكاة، وسيتم إدراج وحدة المحاكاة في ذاكرة التخزين المؤقت لـ CommonJS. الافتراضي: false.
    • defaultExport <any> قيمة اختيارية تستخدم كتصدير افتراضي لوحدة المحاكاة. إذا لم يتم توفير هذه القيمة، فلن تتضمن محاكاة ESM تصديرًا افتراضيًا. إذا كانت المحاكاة عبارة عن وحدة CommonJS أو وحدة مدمجة، فسيتم استخدام هذا الإعداد كقيمة لـ module.exports. إذا لم يتم توفير هذه القيمة، فستستخدم محاكاة CJS والوحدات المدمجة كائنًا فارغًا كقيمة لـ module.exports.
    • namedExports <Object> كائن اختياري تُستخدم مفاتيحه وقيمه لإنشاء الصادرات المسماة لوحدة المحاكاة. إذا كانت المحاكاة عبارة عن وحدة CommonJS أو وحدة مدمجة، فسيتم نسخ هذه القيم على module.exports. لذلك، إذا تم إنشاء محاكاة مع كل من الصادرات المسماة والتصدير الافتراضي غير الكائني، فستقوم المحاكاة بإلقاء استثناء عند استخدامها كوحدة CJS أو وحدة مدمجة.
  • الإرجاع: <MockModuleContext> كائن يمكن استخدامه لمعالجة المحاكاة.

تُستخدم هذه الدالة لمحاكاة صادرات وحدات ECMAScript ووحدات CommonJS ووحدات Node.js المدمجة. لا تتأثر أي مراجع إلى الوحدة الأصلية قبل المحاكاة. لتمكين محاكاة الوحدة، يجب بدء Node.js بعلامة سطر الأوامر --experimental-test-module-mocks.

يوضح المثال التالي كيف يتم إنشاء محاكاة لوحدة نمطية.

js
test('mocks a builtin module in both module systems', async (t) => {
  // Create a mock of 'node:readline' with a named export named 'fn', which
  // does not exist in the original 'node:readline' module.
  const mock = t.mock.module('node:readline', {
    namedExports: { fn() { return 42; } },
  });

  let esmImpl = await import('node:readline');
  let cjsImpl = require('node:readline');

  // cursorTo() is an export of the original 'node:readline' module.
  assert.strictEqual(esmImpl.cursorTo, undefined);
  assert.strictEqual(cjsImpl.cursorTo, undefined);
  assert.strictEqual(esmImpl.fn(), 42);
  assert.strictEqual(cjsImpl.fn(), 42);

  mock.restore();

  // The mock is restored, so the original builtin module is returned.
  esmImpl = await import('node:readline');
  cjsImpl = require('node:readline');

  assert.strictEqual(typeof esmImpl.cursorTo, 'function');
  assert.strictEqual(typeof cjsImpl.cursorTo, 'function');
  assert.strictEqual(esmImpl.fn, undefined);
  assert.strictEqual(cjsImpl.fn, undefined);
});

mock.reset()

تمت إضافته في: الإصدار v19.1.0، v18.13.0

تقوم هذه الدالة باستعادة السلوك الافتراضي لجميع النماذج الوهمية التي تم إنشاؤها مسبقًا بواسطة MockTracker هذه وفصل النماذج الوهمية عن نسخة MockTracker. بمجرد الفصل، لا يزال من الممكن استخدام النماذج الوهمية، ولكن لا يمكن استخدام نسخة MockTracker بعد الآن لإعادة تعيين سلوكها أو التفاعل معها بأي طريقة أخرى.

بعد اكتمال كل اختبار، يتم استدعاء هذه الدالة على MockTracker الخاص بسياق الاختبار. إذا تم استخدام MockTracker العام على نطاق واسع، فمن المستحسن استدعاء هذه الدالة يدويًا.

mock.restoreAll()

تمت إضافته في: الإصدار v19.1.0، v18.13.0

تقوم هذه الدالة باستعادة السلوك الافتراضي لجميع النماذج الوهمية التي تم إنشاؤها مسبقًا بواسطة MockTracker هذه. على عكس mock.reset()، لا تفصل mock.restoreAll() النماذج الوهمية عن نسخة MockTracker.

mock.setter(object, methodName[, implementation][, options])

تمت إضافته في: الإصدار v19.3.0، v18.13.0

هذه الدالة عبارة عن تسهيل في الكتابة لـ MockTracker.method مع تعيين options.setter إلى true.

فئة: ‏MockTimers

[سجل التغييرات]

الإصدارالتغييرات
v23.1.0أصبح Mock Timers الآن مستقرًا.
v20.4.0, v18.19.0تمت إضافته في: الإصدار v20.4.0، v18.19.0

[مستقر: 2 - مستقر]

مستقر: 2 الاستقرار: 2 - مستقر

إنشاء نماذج وهمية للمؤقتات هو أسلوب شائع الاستخدام في اختبار البرامج لمحاكاة والتحكم في سلوك المؤقتات، مثل setInterval و setTimeout، دون الانتظار فعليًا للفترات الزمنية المحددة.

‏MockTimers قادر أيضًا على إنشاء نموذج وهمي لكائن Date.

يوفر MockTracker تصدير timers عالي المستوى وهو عبارة عن نسخة MockTimers.

timers.enable([enableOptions])

[سجل التغييرات]

الإصدارالتغييرات
v21.2.0, v20.11.0تم تحديث المعلمات لتكون كائن خيارات مع واجهات برمجة تطبيقات متاحة والعصر الأولي الافتراضي.
v20.4.0, v18.19.0تمت إضافته في: الإصدار v20.4.0، v18.19.0

يقوم بتمكين إنشاء نموذج وهمي للمؤقتات للمؤقتات المحددة.

  • enableOptions <Object> خيارات تكوين اختيارية لتمكين إنشاء نموذج وهمي للمؤقت. يتم دعم الخصائص التالية:
    • apis <Array> مصفوفة اختيارية تحتوي على المؤقتات المراد إنشاء نموذج وهمي لها. قيم المؤقت المدعومة حاليًا هي setInterval و setTimeout و setImmediate و Date. افتراضي: ['setInterval', 'setTimeout', 'setImmediate', 'Date']. إذا لم يتم توفير مصفوفة، فسيتم إنشاء نموذج وهمي لجميع واجهات برمجة التطبيقات المتعلقة بالوقت ('setInterval' و 'clearInterval' و 'setTimeout' و 'clearTimeout' و 'setImmediate' و 'clearImmediate' و 'Date') بشكل افتراضي.
    • now <number> | <Date> رقم اختياري أو كائن Date يمثل الوقت الأولي (بالمللي ثانية) لاستخدامه كقيمة لـ Date.now(). افتراضي:0.

ملاحظة: عند تمكين إنشاء نموذج وهمي لمؤقت معين، سيتم أيضًا إنشاء نموذج وهمي ضمني لوظيفة المسح المرتبطة به.

ملاحظة: سيؤثر إنشاء نموذج وهمي لـ Date على سلوك المؤقتات الوهمية لأنها تستخدم نفس الساعة الداخلية.

مثال على الاستخدام بدون تعيين الوقت الأولي:

js
import { mock } from 'node:test';
mock.timers.enable({ apis: ['setInterval'] });
js
const { mock } = require('node:test');
mock.timers.enable({ apis: ['setInterval'] });

يمكّن المثال أعلاه إنشاء نموذج وهمي للمؤقت setInterval وينشئ نموذجًا وهميًا ضمنيًا للدالة clearInterval. سيتم إنشاء نموذج وهمي فقط للدوال setInterval و clearInterval من node:timers و node:timers/promises و globalThis.

مثال على الاستخدام مع تعيين الوقت الأولي

js
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: 1000 });
js
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: 1000 });

مثال على الاستخدام مع كائن Date أولي كوقت تم تعيينه

js
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: new Date() });
js
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: new Date() });

بدلاً من ذلك، إذا قمت باستدعاء mock.timers.enable() بدون أي معلمات:

سيتم إنشاء نموذج وهمي لجميع المؤقتات ('setInterval' و 'clearInterval' و 'setTimeout' و 'clearTimeout' و 'setImmediate' و 'clearImmediate'). سيتم إنشاء نموذج وهمي للدوال setInterval و clearInterval و setTimeout و clearTimeout و setImmediate و clearImmediate من node:timers و node:timers/promises و globalThis. بالإضافة إلى كائن Date العام.

timers.reset()

تمت الإضافة في: v20.4.0، v18.19.0

تقوم هذه الدالة باستعادة السلوك الافتراضي لجميع النماذج الوهمية التي تم إنشاؤها مسبقًا بواسطة مثيل MockTimers هذا وتفصل النماذج الوهمية عن مثيل MockTracker.

ملاحظة: بعد اكتمال كل اختبار، يتم استدعاء هذه الدالة على MockTracker لسياق الاختبار.

js
import { mock } from 'node:test';
mock.timers.reset();
js
const { mock } = require('node:test');
mock.timers.reset();

timers[Symbol.dispose]()

يستدعي timers.reset().

timers.tick([milliseconds])

تمت الإضافة في: v20.4.0، v18.19.0

يقدم الوقت لجميع المؤقتات الوهمية.

  • milliseconds <number> مقدار الوقت، بالمللي ثانية، لتقديم المؤقتات. افتراضي: 1.

ملاحظة: يختلف هذا عن كيفية تصرف setTimeout في Node.js ويقبل فقط الأرقام الموجبة. في Node.js، يتم دعم setTimeout مع الأرقام السالبة فقط لأسباب تتعلق بتوافق الويب.

يوضح المثال التالي نموذجًا وهميًا لدالة setTimeout وباستخدام .tick يتقدم في الوقت مما يؤدي إلى تشغيل جميع المؤقتات المعلقة.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();

  context.mock.timers.enable({ apis: ['setTimeout'] });

  setTimeout(fn, 9999);

  assert.strictEqual(fn.mock.callCount(), 0);

  // Advance in time
  context.mock.timers.tick(9999);

  assert.strictEqual(fn.mock.callCount(), 1);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();
  context.mock.timers.enable({ apis: ['setTimeout'] });

  setTimeout(fn, 9999);
  assert.strictEqual(fn.mock.callCount(), 0);

  // Advance in time
  context.mock.timers.tick(9999);

  assert.strictEqual(fn.mock.callCount(), 1);
});

بدلاً من ذلك، يمكن استدعاء الدالة .tick عدة مرات

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();
  context.mock.timers.enable({ apis: ['setTimeout'] });
  const nineSecs = 9000;
  setTimeout(fn, nineSecs);

  const threeSeconds = 3000;
  context.mock.timers.tick(threeSeconds);
  context.mock.timers.tick(threeSeconds);
  context.mock.timers.tick(threeSeconds);

  assert.strictEqual(fn.mock.callCount(), 1);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();
  context.mock.timers.enable({ apis: ['setTimeout'] });
  const nineSecs = 9000;
  setTimeout(fn, nineSecs);

  const threeSeconds = 3000;
  context.mock.timers.tick(threeSeconds);
  context.mock.timers.tick(threeSeconds);
  context.mock.timers.tick(threeSeconds);

  assert.strictEqual(fn.mock.callCount(), 1);
});

سيؤدي تقديم الوقت باستخدام .tick أيضًا إلى تقديم الوقت لأي كائن Date تم إنشاؤه بعد تمكين النموذج الوهمي (إذا تم تعيين Date أيضًا على أن يكون وهميًا).

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();

  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  setTimeout(fn, 9999);

  assert.strictEqual(fn.mock.callCount(), 0);
  assert.strictEqual(Date.now(), 0);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 9999);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });

  setTimeout(fn, 9999);
  assert.strictEqual(fn.mock.callCount(), 0);
  assert.strictEqual(Date.now(), 0);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(fn.mock.callCount(), 1);
  assert.strictEqual(Date.now(), 9999);
});

استخدام دوال clear

كما ذكرنا، يتم عمل محاكاة ضمنية لجميع دوال clear من المؤقتات (clearTimeout و clearInterval و clearImmediate). ألق نظرة على هذا المثال باستخدام setTimeout:

js
import assert from 'node:assert';
import { test } from 'node:test';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] });
  const id = setTimeout(fn, 9999);

  // Implicitly mocked as well
  clearTimeout(id);
  context.mock.timers.tick(9999);

  // As that setTimeout was cleared the mock function will never be called
  assert.strictEqual(fn.mock.callCount(), 0);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
  const fn = context.mock.fn();

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] });
  const id = setTimeout(fn, 9999);

  // Implicitly mocked as well
  clearTimeout(id);
  context.mock.timers.tick(9999);

  // As that setTimeout was cleared the mock function will never be called
  assert.strictEqual(fn.mock.callCount(), 0);
});

العمل مع وحدات مؤقتات Node.js

بمجرد تمكين محاكاة المؤقتات، يتم تمكين وحدات node:timers و node:timers/promises، والمؤقتات من سياق Node.js العالمي:

ملاحظة: تجريد الدوال مثل import { setTimeout } from 'node:timers' غير مدعوم حاليًا بواسطة واجهة برمجة التطبيقات هذه.

js
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimers from 'node:timers';
import nodeTimersPromises from 'node:timers/promises';

test('mocks setTimeout to be executed synchronously without having to actually wait for it', async (context) => {
  const globalTimeoutObjectSpy = context.mock.fn();
  const nodeTimerSpy = context.mock.fn();
  const nodeTimerPromiseSpy = context.mock.fn();

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] });
  setTimeout(globalTimeoutObjectSpy, 9999);
  nodeTimers.setTimeout(nodeTimerSpy, 9999);

  const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1);
  assert.strictEqual(nodeTimerSpy.mock.callCount(), 1);
  await promise;
  assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1);
});
js
const assert = require('node:assert');
const { test } = require('node:test');
const nodeTimers = require('node:timers');
const nodeTimersPromises = require('node:timers/promises');

test('mocks setTimeout to be executed synchronously without having to actually wait for it', async (context) => {
  const globalTimeoutObjectSpy = context.mock.fn();
  const nodeTimerSpy = context.mock.fn();
  const nodeTimerPromiseSpy = context.mock.fn();

  // Optionally choose what to mock
  context.mock.timers.enable({ apis: ['setTimeout'] });
  setTimeout(globalTimeoutObjectSpy, 9999);
  nodeTimers.setTimeout(nodeTimerSpy, 9999);

  const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);

  // Advance in time
  context.mock.timers.tick(9999);
  assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1);
  assert.strictEqual(nodeTimerSpy.mock.callCount(), 1);
  await promise;
  assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1);
});

في Node.js، setInterval من node:timers/promises هو AsyncGenerator وهو مدعوم أيضًا بواسطة واجهة برمجة التطبيقات هذه:

js
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimersPromises from 'node:timers/promises';
test('should tick five times testing a real use case', async (context) => {
  context.mock.timers.enable({ apis: ['setInterval'] });

  const expectedIterations = 3;
  const interval = 1000;
  const startedAt = Date.now();
  async function run() {
    const times = [];
    for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
      times.push(time);
      if (times.length === expectedIterations) break;
    }
    return times;
  }

  const r = run();
  context.mock.timers.tick(interval);
  context.mock.timers.tick(interval);
  context.mock.timers.tick(interval);

  const timeResults = await r;
  assert.strictEqual(timeResults.length, expectedIterations);
  for (let it = 1; it < expectedIterations; it++) {
    assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
  }
});
js
const assert = require('node:assert');
const { test } = require('node:test');
const nodeTimersPromises = require('node:timers/promises');
test('should tick five times testing a real use case', async (context) => {
  context.mock.timers.enable({ apis: ['setInterval'] });

  const expectedIterations = 3;
  const interval = 1000;
  const startedAt = Date.now();
  async function run() {
    const times = [];
    for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
      times.push(time);
      if (times.length === expectedIterations) break;
    }
    return times;
  }

  const r = run();
  context.mock.timers.tick(interval);
  context.mock.timers.tick(interval);
  context.mock.timers.tick(interval);

  const timeResults = await r;
  assert.strictEqual(timeResults.length, expectedIterations);
  for (let it = 1; it < expectedIterations; it++) {
    assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
  }
});

timers.runAll()

تمت إضافتها في: v20.4.0, v18.19.0

يقوم بتشغيل جميع المؤقتات المحاكاة المعلقة على الفور. إذا تم أيضًا محاكاة كائن Date، فسيتم أيضًا تقديم كائن Date إلى أبعد وقت للمؤقت.

يوضح المثال أدناه تشغيل جميع المؤقتات المعلقة على الفور، مما يؤدي إلى تنفيذها دون أي تأخير.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('runAll functions following the given order', (context) => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const results = [];
  setTimeout(() => results.push(1), 9999);

  // Notice that if both timers have the same timeout,
  // the order of execution is guaranteed
  setTimeout(() => results.push(3), 8888);
  setTimeout(() => results.push(2), 8888);

  assert.deepStrictEqual(results, []);

  context.mock.timers.runAll();
  assert.deepStrictEqual(results, [3, 2, 1]);
  // The Date object is also advanced to the furthest timer's time
  assert.strictEqual(Date.now(), 9999);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('runAll functions following the given order', (context) => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const results = [];
  setTimeout(() => results.push(1), 9999);

  // Notice that if both timers have the same timeout,
  // the order of execution is guaranteed
  setTimeout(() => results.push(3), 8888);
  setTimeout(() => results.push(2), 8888);

  assert.deepStrictEqual(results, []);

  context.mock.timers.runAll();
  assert.deepStrictEqual(results, [3, 2, 1]);
  // The Date object is also advanced to the furthest timer's time
  assert.strictEqual(Date.now(), 9999);
});

ملاحظة: تم تصميم وظيفة runAll() خصيصًا لتشغيل المؤقتات في سياق محاكاة المؤقت. ليس لها أي تأثير على ساعات النظام في الوقت الفعلي أو المؤقتات الفعلية خارج بيئة المحاكاة.

timers.setTime(milliseconds)

تمت إضافتها في: v21.2.0, v20.11.0

يضبط الطابع الزمني الحالي لنظام Unix الذي سيتم استخدامه كمرجع لأي كائنات Date محاكاة.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('runAll functions following the given order', (context) => {
  const now = Date.now();
  const setTime = 1000;
  // Date.now is not mocked
  assert.deepStrictEqual(Date.now(), now);

  context.mock.timers.enable({ apis: ['Date'] });
  context.mock.timers.setTime(setTime);
  // Date.now is now 1000
  assert.strictEqual(Date.now(), setTime);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('setTime replaces current time', (context) => {
  const now = Date.now();
  const setTime = 1000;
  // Date.now is not mocked
  assert.deepStrictEqual(Date.now(), now);

  context.mock.timers.enable({ apis: ['Date'] });
  context.mock.timers.setTime(setTime);
  // Date.now is now 1000
  assert.strictEqual(Date.now(), setTime);
});

التواريخ والمؤقتات تعمل معًا

تعتمد كائنات التاريخ والمؤقت على بعضها البعض. إذا كنت تستخدم setTime() لتمرير الوقت الحالي إلى كائن Date الوهمي، فلن تتأثر المؤقتات المعينة باستخدام setTimeout و setInterval.

ومع ذلك، فإن طريقة tick ستقوم بتقديم كائن Date الوهمي.

js
import assert from 'node:assert';
import { test } from 'node:test';

test('تشغيل جميع الوظائف بالترتيب المحدد', (context) => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const results = [];
  setTimeout(() => results.push(1), 9999);

  assert.deepStrictEqual(results, []);
  context.mock.timers.setTime(12000);
  assert.deepStrictEqual(results, []);
  // يتم تقديم التاريخ ولكن المؤقتات لا تعمل
  assert.strictEqual(Date.now(), 12000);
});
js
const assert = require('node:assert');
const { test } = require('node:test');

test('تشغيل جميع الوظائف بالترتيب المحدد', (context) => {
  context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  const results = [];
  setTimeout(() => results.push(1), 9999);

  assert.deepStrictEqual(results, []);
  context.mock.timers.setTime(12000);
  assert.deepStrictEqual(results, []);
  // يتم تقديم التاريخ ولكن المؤقتات لا تعمل
  assert.strictEqual(Date.now(), 12000);
});

صنف: TestsStream

[تاريخ]

الإصدارالتغييرات
v20.0.0, v19.9.0, v18.17.0تمت إضافة النوع إلى أحداث test:pass و test:fail عندما يكون الاختبار مجموعة.
v18.9.0, v16.19.0تمت الإضافة في: v18.9.0, v16.19.0

ستؤدي المكالمة الناجحة لطريقة run() إلى إرجاع كائن <TestsStream> جديد، يقوم ببث سلسلة من الأحداث التي تمثل تنفيذ الاختبارات. سيصدر TestsStream الأحداث، بترتيب تعريف الاختبارات

يضمن إصدار بعض الأحداث بنفس ترتيب تعريف الاختبارات، بينما يتم إصدار البعض الآخر بالترتيب الذي يتم به تنفيذ الاختبارات.

الحدث: 'test:coverage'

  • data <Object>
    • summary <Object> كائن يحتوي على تقرير التغطية.

    • files <Array> مصفوفة من تقارير التغطية للملفات الفردية. كل تقرير هو كائن بالنموذج التالي:

    • path <string> المسار المطلق للملف.

    • totalLineCount <number> العدد الإجمالي للأسطر.

    • totalBranchCount <number> العدد الإجمالي للفروع.

    • totalFunctionCount <number> العدد الإجمالي للدوال.

    • coveredLineCount <number> عدد الأسطر المغطاة.

    • coveredBranchCount <number> عدد الفروع المغطاة.

    • coveredFunctionCount <number> عدد الدوال المغطاة.

    • coveredLinePercent <number> النسبة المئوية للأسطر المغطاة.

    • coveredBranchPercent <number> النسبة المئوية للفروع المغطاة.

    • coveredFunctionPercent <number> النسبة المئوية للدوال المغطاة.

    • functions <Array> مصفوفة من الدوال تمثل تغطية الدوال.

    • name <string> اسم الدالة.

    • line <number> رقم السطر حيث تم تعريف الدالة.

    • count <number> عدد مرات استدعاء الدالة.

    • branches <Array> مصفوفة من الفروع تمثل تغطية الفروع.

    • line <number> رقم السطر حيث تم تعريف الفرع.

    • count <number> عدد مرات اتخاذ الفرع.

    • lines <Array> مصفوفة من الأسطر تمثل أرقام الأسطر وعدد مرات تغطيتها.

    • line <number> رقم السطر.

    • count <number> عدد مرات تغطية السطر.

    • thresholds <Object> كائن يحتوي على ما إذا كانت التغطية لكل نوع تغطية.

    • function <number> حد تغطية الدالة.

    • branch <number> حد تغطية الفرع.

    • line <number> حد تغطية السطر.

    • totals <Object> كائن يحتوي على ملخص لتغطية جميع الملفات.

    • totalLineCount <number> العدد الإجمالي للأسطر.

    • totalBranchCount <number> العدد الإجمالي للفروع.

    • totalFunctionCount <number> العدد الإجمالي للدوال.

    • coveredLineCount <number> عدد الأسطر المغطاة.

    • coveredBranchCount <number> عدد الفروع المغطاة.

    • coveredFunctionCount <number> عدد الدوال المغطاة.

    • coveredLinePercent <number> النسبة المئوية للأسطر المغطاة.

    • coveredBranchPercent <number> النسبة المئوية للفروع المغطاة.

    • coveredFunctionPercent <number> النسبة المئوية للدوال المغطاة.

    • workingDirectory <string> دليل العمل عندما بدأت تغطية التعليمات البرمجية. هذا مفيد لعرض أسماء المسارات النسبية في حال غيرت الاختبارات دليل عمل عملية Node.js.

    • nesting <number> مستوى تداخل الاختبار.

يتم إصداره عند تمكين تغطية التعليمات البرمجية وعند اكتمال جميع الاختبارات.

الحدث: 'test:complete'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.

    • details <Object> بيانات تعريف تنفيذ إضافية.

    • passed <boolean> ما إذا كان الاختبار قد نجح أم لا.

    • duration_ms <number> مدة الاختبار بالمللي ثانية.

    • error <Error> | <undefined> خطأ يغلف الخطأ الذي تم طرحه بواسطة الاختبار إذا لم ينجح.

    • cause <Error> الخطأ الفعلي الذي تم طرحه بواسطة الاختبار.

    • type <string> | <undefined> نوع الاختبار، يستخدم للدلالة على ما إذا كانت هذه مجموعة اختبار.

    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.

    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.

    • name <string> اسم الاختبار.

    • nesting <number> مستوى تداخل الاختبار.

    • testNumber <number> الرقم الترتيبي للاختبار.

    • todo <string> | <boolean> | <undefined> موجود إذا تم استدعاء context.todo

    • skip <string> | <boolean> | <undefined> موجود إذا تم استدعاء context.skip

يتم إصداره عند اكتمال تنفيذ الاختبار. لا يتم إصدار هذا الحدث بنفس ترتيب تعريف الاختبارات. الأحداث ذات الصلة بالترتيب الإعلاني هي 'test:pass' و 'test:fail'.

الحدث: 'test:dequeue'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.
    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • name <string> اسم الاختبار.
    • nesting <number> مستوى تداخل الاختبار.

يتم إصداره عند إخراج اختبار من قائمة الانتظار، قبل تنفيذه مباشرة. لا يضمن هذا الحدث إصداره بنفس ترتيب تعريف الاختبارات. الحدث المرتب ذي الصلة هو 'test:start'.

الحدث: 'test:diagnostic'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.
    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • message <string> رسالة التشخيص.
    • nesting <number> مستوى تداخل الاختبار.

يتم إصداره عند استدعاء context.diagnostic. يضمن هذا الحدث إصداره بنفس ترتيب تعريف الاختبارات.

الحدث: 'test:enqueue'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.
    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • name <string> اسم الاختبار.
    • nesting <number> مستوى تداخل الاختبار.

يتم إصداره عندما يتم وضع اختبار في قائمة الانتظار للتنفيذ.

الحدث: 'test:fail'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.

    • details <Object> بيانات تعريف تنفيذ إضافية.

    • duration_ms <number> مدة الاختبار بالمللي ثانية.

    • error <Error> خطأ يغلف الخطأ الذي تم طرحه بواسطة الاختبار.

    • cause <Error> الخطأ الفعلي الذي تم طرحه بواسطة الاختبار.

    • type <string> | <undefined> نوع الاختبار، يستخدم للإشارة إلى ما إذا كانت هذه مجموعة اختبارات.

    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.

    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.

    • name <string> اسم الاختبار.

    • nesting <number> مستوى تداخل الاختبار.

    • testNumber <number> الرقم الترتيبي للاختبار.

    • todo <string> | <boolean> | <undefined> موجود إذا تم استدعاء context.todo

    • skip <string> | <boolean> | <undefined> موجود إذا تم استدعاء context.skip

يتم إصداره عند فشل اختبار. يتم ضمان إصدار هذا الحدث بنفس ترتيب تعريف الاختبارات. الحدث المقابل المرتب حسب التنفيذ هو 'test:complete'.

الحدث: 'test:pass'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.

    • details <Object> بيانات وصفية إضافية للتنفيذ.

    • duration_ms <number> مدة الاختبار بالمللي ثانية.

    • type <string> | <undefined> نوع الاختبار، يستخدم للدلالة على ما إذا كانت هذه مجموعة.

    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.

    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.

    • name <string> اسم الاختبار.

    • nesting <number> مستوى تداخل الاختبار.

    • testNumber <number> الرقم الترتيبي للاختبار.

    • todo <string> | <boolean> | <undefined> موجود إذا تم استدعاء context.todo

    • skip <string> | <boolean> | <undefined> موجود إذا تم استدعاء context.skip

يتم إصداره عند اجتياز الاختبار. يضمن إصدار هذا الحدث بنفس ترتيب تعريف الاختبارات. الحدث المقابل المرتب حسب التنفيذ هو 'test:complete'.

الحدث: 'test:plan'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.
    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • nesting <number> مستوى تداخل الاختبار.
    • count <number> عدد الاختبارات الفرعية التي تم تشغيلها.

يتم إصداره عند اكتمال جميع الاختبارات الفرعية لاختبار معين. يضمن إصدار هذا الحدث بنفس ترتيب تعريف الاختبارات.

الحدث: 'test:start'

  • data <Object>
    • column <number> | <undefined> رقم العمود حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • file <string> | <undefined> مسار ملف الاختبار، undefined إذا تم تشغيل الاختبار من خلال REPL.
    • line <number> | <undefined> رقم السطر حيث تم تعريف الاختبار، أو undefined إذا تم تشغيل الاختبار من خلال REPL.
    • name <string> اسم الاختبار.
    • nesting <number> مستوى تداخل الاختبار.

يتم إصداره عندما يبدأ الاختبار في الإبلاغ عن حالته وحالة اختباراته الفرعية. يضمن إصدار هذا الحدث بنفس ترتيب تعريف الاختبارات. حدث الترتيب المقابل للتنفيذ هو 'test:dequeue'.

الحدث: 'test:stderr'

  • data <Object>
    • file <string> مسار ملف الاختبار.
    • message <string> الرسالة المكتوبة إلى stderr.

يتم إصداره عندما يكتب اختبار قيد التشغيل إلى stderr. يتم إصدار هذا الحدث فقط إذا تم تمرير العلامة --test. لا يتم ضمان إصدار هذا الحدث بنفس الترتيب الذي يتم به تعريف الاختبارات.

الحدث: 'test:stdout'

  • data <Object>
    • file <string> مسار ملف الاختبار.
    • message <string> الرسالة المكتوبة إلى stdout.

يتم إصداره عندما يكتب اختبار قيد التشغيل إلى stdout. يتم إصدار هذا الحدث فقط إذا تم تمرير العلامة --test. لا يتم ضمان إصدار هذا الحدث بنفس الترتيب الذي يتم به تعريف الاختبارات.

الحدث: 'test:summary'

  • data <Object>
    • counts <Object> كائن يحتوي على عدد نتائج الاختبار المختلفة.

    • cancelled <number> العدد الإجمالي للاختبارات الملغاة.

    • failed <number> العدد الإجمالي للاختبارات الفاشلة.

    • passed <number> العدد الإجمالي للاختبارات الناجحة.

    • skipped <number> العدد الإجمالي للاختبارات التي تم تخطيها.

    • suites <number> العدد الإجمالي للأجنحة التي تم تشغيلها.

    • tests <number> العدد الإجمالي للاختبارات التي تم تشغيلها، باستثناء الأجنحة.

    • todo <number> العدد الإجمالي لاختبارات TODO.

    • topLevel <number> العدد الإجمالي للاختبارات والأجنحة ذات المستوى الأعلى.

    • duration_ms <number> مدة تشغيل الاختبار بالمللي ثانية.

    • file <string> | <undefined> مسار ملف الاختبار الذي أنشأ الملخص. إذا كان الملخص يتوافق مع ملفات متعددة، فستكون هذه القيمة undefined.

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

يتم إصداره عند اكتمال تشغيل الاختبار. يحتوي هذا الحدث على مقاييس تتعلق بتشغيل الاختبار المكتمل، وهو مفيد لتحديد ما إذا كان تشغيل الاختبار قد نجح أم فشل. إذا تم استخدام عزل الاختبار على مستوى العملية، فسيتم إنشاء حدث 'test:summary' لكل ملف اختبار بالإضافة إلى ملخص تراكمي نهائي.

الحدث: 'test:watch:drained'

يصدر عند عدم وجود المزيد من الاختبارات في قائمة الانتظار للتنفيذ في وضع المراقبة.

الصنف: TestContext

[السجل]

الإصدارالتغييرات
v20.1.0, v18.17.0تمت إضافة الدالة before إلى TestContext.
v18.0.0, v16.17.0تمت إضافتها في: v18.0.0, v16.17.0

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

context.before([fn][, options])

تمت إضافتها في: v20.1.0, v18.17.0

  • fn <Function> | <AsyncFunction> دالة الربط. الوسيط الأول لهذه الدالة هو كائن TestContext. إذا كانت أداة الربط تستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كوسيط ثانٍ. الافتراضي: دالة لا تفعل شيئًا.
  • options <Object> خيارات التكوين لأداة الربط. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإلغاء أداة ربط قيد التقدم.
    • timeout <number> عدد بالمللي ثانية تفشل أداة الربط بعده. إذا لم يتم تحديده، فإن الاختبارات الفرعية ترث هذه القيمة من الأصل. الافتراضي: Infinity.

تُستخدم هذه الدالة لإنشاء أداة ربط تعمل قبل الاختبار الفرعي للاختبار الحالي.

context.beforeEach([fn][, options])

تمت إضافتها في: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> دالة الربط. الوسيط الأول لهذه الدالة هو كائن TestContext. إذا كانت أداة الربط تستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كوسيط ثانٍ. الافتراضي: دالة لا تفعل شيئًا.
  • options <Object> خيارات التكوين لأداة الربط. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإلغاء أداة ربط قيد التقدم.
    • timeout <number> عدد بالمللي ثانية تفشل أداة الربط بعده. إذا لم يتم تحديده، فإن الاختبارات الفرعية ترث هذه القيمة من الأصل. الافتراضي: Infinity.

تُستخدم هذه الدالة لإنشاء أداة ربط تعمل قبل كل اختبار فرعي للاختبار الحالي.

js
test('اختبار المستوى الأعلى', async (t) => {
  t.beforeEach((t) => t.diagnostic(`على وشك تشغيل ${t.name}`));
  await t.test(
    'هذا اختبار فرعي',
    (t) => {
      assert.ok('بعض التأكيدات ذات الصلة هنا');
    },
  );
});

context.after([fn][, options])

أُضيف في: v19.3.0, v18.13.0

  • fn <Function> | <AsyncFunction> دالة الخطاف. الوسيط الأول لهذه الدالة هو كائن TestContext. إذا كان الخطاف يستخدم ردود النداء، فسيتم تمرير دالة رد النداء كوسيط ثانٍ. افتراضي: دالة لا تفعل شيئًا.
  • options <Object> خيارات تكوين الخطاف. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإلغاء خطاف قيد التقدم.
    • timeout <number> عدد المللي ثانية التي سيفشل بعدها الخطاف. إذا لم يتم تحديده، فسوف ترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. افتراضي: Infinity.

تُستخدم هذه الدالة لإنشاء خطاف يعمل بعد انتهاء الاختبار الحالي.

js
test('اختبار المستوى الأعلى', async (t) => {
  t.after((t) => t.diagnostic(`تم الانتهاء من تشغيل ${t.name}`));
  assert.ok('بعض التأكيدات ذات الصلة هنا');
});

context.afterEach([fn][, options])

أُضيف في: v18.8.0, v16.18.0

  • fn <Function> | <AsyncFunction> دالة الخطاف. الوسيط الأول لهذه الدالة هو كائن TestContext. إذا كان الخطاف يستخدم ردود النداء، فسيتم تمرير دالة رد النداء كوسيط ثانٍ. افتراضي: دالة لا تفعل شيئًا.
  • options <Object> خيارات تكوين الخطاف. الخصائص التالية مدعومة:
    • signal <AbortSignal> يسمح بإلغاء خطاف قيد التقدم.
    • timeout <number> عدد المللي ثانية التي سيفشل بعدها الخطاف. إذا لم يتم تحديده، فسوف ترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. افتراضي: Infinity.

تُستخدم هذه الدالة لإنشاء خطاف يعمل بعد كل اختبار فرعي للاختبار الحالي.

js
test('اختبار المستوى الأعلى', async (t) => {
  t.afterEach((t) => t.diagnostic(`تم الانتهاء من تشغيل ${t.name}`));
  await t.test(
    'هذا اختبار فرعي',
    (t) => {
      assert.ok('بعض التأكيدات ذات الصلة هنا');
    },
  );
});

context.assert

تمت الإضافة في: v22.2.0, v20.15.0

كائن يحتوي على أساليب التأكيد المرتبطة بـ context. يتم عرض الدوال ذات المستوى الأعلى من وحدة node:assert هنا لغرض إنشاء خطط الاختبار.

js
test('test', (t) => {
  t.plan(1);
  t.assert.strictEqual(true, true);
});

context.assert.snapshot(value[, options])

تمت الإضافة في: v22.3.0

[مستقر: 1 - تجريبي]

مستقر: 1 الاستقرار: 1.0 - تطوير مبكر

  • value <any> قيمة يتم تسلسلها إلى سلسلة. إذا تم بدء Node.js باستخدام العلامة --test-update-snapshots، فستتم كتابة القيمة المسلسلة في ملف اللقطة. وإلا، تتم مقارنة القيمة المسلسلة بالقيمة المقابلة في ملف اللقطة الموجود.
  • options <Object> خيارات التكوين الاختيارية. الخصائص التالية مدعومة:
    • serializers <Array> مصفوفة من الدوال المتزامنة المستخدمة لتسلسل value إلى سلسلة. يتم تمرير value كوسيطة وحيدة إلى دالة التسلسل الأولى. يتم تمرير القيمة المرجعة لكل مسلسِل كمدخل للمسلسِل التالي. بمجرد تشغيل جميع المسلسلات، يتم إجبار القيمة الناتجة على سلسلة. الافتراضي: إذا لم يتم توفير أي مسلسلات، فسيتم استخدام المسلسلات الافتراضية لتشغيل الاختبار.

تنفذ هذه الدالة تأكيدات لاختبار اللقطات.

js
test('snapshot test with default serialization', (t) => {
  t.assert.snapshot({ value1: 1, value2: 2 });
});

test('snapshot test with custom serialization', (t) => {
  t.assert.snapshot({ value3: 3, value4: 4 }, {
    serializers: [(value) => JSON.stringify(value)],
  });
});

context.diagnostic(message)

أضيف في: v18.0.0, v16.17.0

  • message <string> الرسالة التي سيتم الإبلاغ عنها.

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

js
test('top level test', (t) => {
  t.diagnostic('A diagnostic message');
});

context.filePath

أضيف في: v22.6.0, v20.16.0

المسار المطلق لملف الاختبار الذي أنشأ الاختبار الحالي. إذا استورد ملف اختبار وحدات نمطية إضافية تولد اختبارات، فستُرجع الاختبارات المستوردة مسار ملف الاختبار الجذر.

context.fullName

أضيف في: v22.3.0

اسم الاختبار وكل من أسلافه، مفصولة بـ \>.

context.name

أضيف في: v18.8.0, v16.18.0

اسم الاختبار.

context.plan(count)

[سجل التغييرات]

الإصدارالتغييرات
v23.4.0هذه الدالة لم تعد تجريبية.
v22.2.0, v20.15.0أضيف في: v22.2.0, v20.15.0
  • count <number> عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها.

تُستخدم هذه الدالة لتعيين عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها داخل الاختبار. إذا كان عدد التأكيدات والاختبارات الفرعية التي يتم تشغيلها لا يتطابق مع العدد المتوقع، فسيفشل الاختبار.

js
test('top level test', (t) => {
  t.plan(2);
  t.assert.ok('some relevant assertion here');
  t.test('subtest', () => {});
});

عند العمل مع التعليمات البرمجية غير المتزامنة، يمكن استخدام دالة plan للتأكد من تشغيل العدد الصحيح من التأكيدات:

js
test('planning with streams', (t, done) => {
  function* generate() {
    yield 'a';
    yield 'b';
    yield 'c';
  }
  const expected = ['a', 'b', 'c'];
  t.plan(expected.length);
  const stream = Readable.from(generate());
  stream.on('data', (chunk) => {
    t.assert.strictEqual(chunk, expected.shift());
  });

  stream.on('end', () => {
    done();
  });
});

context.runOnly(shouldRunOnlyTests)

تمت الإضافة في: الإصدار 18.0.0، الإصدار 16.17.0

  • shouldRunOnlyTests<boolean> سواء كان سيتم تشغيل اختبارات only أم لا.

إذا كانت قيمة shouldRunOnlyTests صالحة، فسياق الاختبار سيشغل فقط الاختبارات التي تم تعيين خيار only لها. بخلاف ذلك، يتم تشغيل جميع الاختبارات. إذا لم يتم بدء Node.js باستخدام خيار سطر الأوامر --test-only، فإن هذه الوظيفة لا تفعل شيئًا.

js
test('اختبار المستوى الأعلى', (t) => {
  // يمكن ضبط سياق الاختبار لتشغيل الاختبارات الفرعية بخيار 'only'.
  t.runOnly(true);
  return Promise.all([
    t.test('هذا الاختبار الفرعي يتم تخطيه الآن'),
    t.test('يتم تشغيل هذا الاختبار الفرعي', { only: true }),
  ]);
});

context.signal

تمت الإضافة في: الإصدار 18.7.0، الإصدار 16.17.0

يمكن استخدامه لإلغاء مهام الاختبار الفرعية عندما يتم إلغاء الاختبار.

js
test('اختبار المستوى الأعلى', async (t) => {
  await fetch('some/uri', { signal: t.signal });
});

context.skip([message])

تمت الإضافة في: الإصدار 18.0.0، الإصدار 16.17.0

  • message<string> رسالة تخطي اختيارية.

تتسبب هذه الوظيفة في إشارة مخرجات الاختبار إلى الاختبار على أنه تم تخطيه. إذا تم توفير message، فسيتم تضمينها في المخرجات. استدعاء skip() لا ينهي تنفيذ وظيفة الاختبار. لا تُرجع هذه الوظيفة قيمة.

js
test('اختبار المستوى الأعلى', (t) => {
  // تأكد من الإرجاع هنا أيضًا إذا كان الاختبار يحتوي على منطق إضافي.
  t.skip('تم تخطي هذا');
});

context.todo([message])

تمت الإضافة في: الإصدار 18.0.0، الإصدار 16.17.0

  • message<string> رسالة TODO اختيارية.

تضيف هذه الوظيفة توجيه TODO إلى مخرجات الاختبار. إذا تم توفير message، فسيتم تضمينها في المخرجات. استدعاء todo() لا ينهي تنفيذ وظيفة الاختبار. لا تُرجع هذه الوظيفة قيمة.

js
test('اختبار المستوى الأعلى', (t) => {
  // تم وضع علامة `TODO` على هذا الاختبار
  t.todo('هذا عنصر يجب تنفيذه لاحقًا');
});

context.test([name][, options][, fn])

[السجل]

الإصدارالتغييرات
v18.8.0, v16.18.0إضافة خيار signal.
v18.7.0, v16.17.0إضافة خيار timeout.
v18.0.0, v16.17.0أُضيف في: v18.0.0, v16.17.0
  • name <string> اسم الاختبار الفرعي، والذي يتم عرضه عند الإبلاغ عن نتائج الاختبار. الافتراضي: الخاصية name لـ fn، أو '\<anonymous\>' إذا لم يكن لـ fn اسم.

  • options <Object> خيارات التهيئة للاختبار الفرعي. الخصائص التالية مدعومة:

    • concurrency <number> | <boolean> | <null> إذا تم توفير رقم، فسيتم تشغيل هذا العدد من الاختبارات بالتوازي داخل مؤشر ترابط التطبيق. إذا كانت true، فسيتم تشغيل جميع الاختبارات الفرعية بالتوازي. إذا كانت false، فسيتم تشغيل اختبار واحد فقط في كل مرة. إذا لم يتم تحديدها، فسوف ترث الاختبارات الفرعية هذه القيمة من أصلها. الافتراضي: null.
    • only <boolean> إذا كانت صحيحة، وتم تكوين سياق الاختبار لتشغيل اختبارات only، فسيتم تشغيل هذا الاختبار. بخلاف ذلك، يتم تخطي الاختبار. الافتراضي: false.
    • signal <AbortSignal> يسمح بإلغاء اختبار قيد التقدم.
    • skip <boolean> | <string> إذا كانت صحيحة، يتم تخطي الاختبار. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لتخطي الاختبار. الافتراضي: false.
    • todo <boolean> | <string> إذا كانت صحيحة، يتم وضع علامة على الاختبار كـ TODO. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لكون الاختبار TODO. الافتراضي: false.
    • timeout <number> عدد بالميلي ثانية سيفشل الاختبار بعده. إذا لم يتم تحديدها، فسوف ترث الاختبارات الفرعية هذه القيمة من أصلها. الافتراضي: Infinity.
    • plan <number> عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها في الاختبار. إذا كان عدد التأكيدات التي تم تشغيلها في الاختبار لا يتطابق مع الرقم المحدد في الخطة، فسيفشل الاختبار. الافتراضي: undefined.
  • fn <Function> | <AsyncFunction> الدالة قيد الاختبار. الوسيطة الأولى لهذه الدالة هي كائن TestContext. إذا كان الاختبار يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كوسيطة ثانية. الافتراضي: دالة لا تفعل شيئًا.

  • Returns: <Promise> مُحقق بـ undefined بمجرد اكتمال الاختبار.

تُستخدم هذه الدالة لإنشاء اختبارات فرعية ضمن الاختبار الحالي. تتصرف هذه الدالة بنفس طريقة دالة test() ذات المستوى الأعلى.

js
test('اختبار المستوى الأعلى', async (t) => {
  await t.test(
    'هذا اختبار فرعي',
    { only: false, skip: false, concurrency: 1, todo: false, plan: 1 },
    (t) => {
      t.assert.ok('بعض التأكيدات ذات الصلة هنا');
    },
  );
});

الفئة: SuiteContext

تمت الإضافة في: v18.7.0, v16.17.0

يتم تمرير نسخة من SuiteContext إلى كل دالة مجموعة اختبار للتفاعل مع مُشغِّل الاختبارات. ومع ذلك، فإن مُنشئ SuiteContext غير معروض كجزء من واجهة برمجة التطبيقات (API).

context.filePath

تمت الإضافة في: v22.6.0

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

context.name

تمت الإضافة في: v18.8.0, v16.18.0

اسم المجموعة.

context.signal

تمت الإضافة في: v18.7.0, v16.17.0

يمكن استخدامه لإلغاء مهام الاختبار الفرعية عند إلغاء الاختبار.