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() مع كائن Error ويُفشل الاختبار.
  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
// يتم استخدام خيار skip ، ولكن لم يتم توفير رسالة.
test('خيار skip', { skip: true }, t => {
  // هذه الكود لا يتم تنفيذه أبدًا.
})

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

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

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

اختبارات TODO

يمكن تمييز الاختبارات الفردية على أنها غير مستقرة أو غير مكتملة عن طريق تمرير خيار todo إلى الاختبار، أو عن طريق استدعاء طريقة todo() لسياق الاختبار، كما هو موضح في المثال التالي. تمثل هذه الاختبارات تنفيذًا معلقًا أو خطأ يحتاج إلى إصلاح. يتم تنفيذ اختبارات TODO ، ولكن لا يتم التعامل معها على أنها أخطاء في الاختبار، وبالتالي لا تؤثر على رمز خروج العملية. إذا تم تمييز اختبار على أنه TODO و skipped في نفس الوقت، يتم تجاهل خيار 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('A thing', () => {
  it('should work', () => {
    assert.strictEqual(1, 1)
  })

  it('should be ok', () => {
    assert.strictEqual(2, 2)
  })

  describe('a nested thing', () => {
    it('should work', () => {
      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('this test is run', { only: true }, async t => {
  // ضمن هذا الاختبار، يتم تشغيل جميع الاختبارات الفرعية افتراضيًا.
  await t.test('running subtest')

  // يمكن تحديث سياق الاختبار لتشغيل الاختبارات الفرعية بخيار "only".
  t.runOnly(true)
  await t.test('this subtest is now skipped')
  await t.test('this subtest is run', { only: true })

  // قم بتغيير السياق مرة أخرى لتنفيذ جميع الاختبارات.
  t.runOnly(false)
  await t.test('this subtest is now run')

  // صراحةً، لا تقم بتشغيل هذه الاختبارات.
  await t.test('skipped subtest 3', { only: false })
  await t.test('skipped subtest 4', { skip: true })
})

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

describe('a suite', () => {
  // تم تعيين خيار "only"، لذلك يتم تشغيل هذا الاختبار.
  it('this test is run', { only: true }, () => {
    // تم تشغيل هذا الكود.
  })

  it('this test is not run', () => {
    // لم يتم تشغيل هذا الكود.
    throw new Error('fail')
  })
})

describe.only('a suite', () => {
  // تم تعيين خيار "only"، لذلك يتم تشغيل هذا الاختبار.
  it('this test is run', () => {
    // تم تشغيل هذا الكود.
  })

  it('this test is run', () => {
    // تم تشغيل هذا الكود.
  })
})

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

يمكن استخدام خيار سطر الأوامر --test-name-pattern لتشغيل الاختبارات التي يتطابق اسمها مع النمط المقدم فقط، ويمكن استخدام خيار --test-skip-pattern لتخطي الاختبارات التي يتطابق اسمها مع النمط المقدم. تُفسّر أنماط أسماء الاختبارات كتعبيرات عادية في جافا سكريبت. يمكن تحديد خياري --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('هذا لن يتم تنفيذه أبدًا')
}
/* node:coverage enable */

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

js
/* node:coverage ignore next */
if (anAlwaysFalseCondition) {
  console.log('هذا لن يتم تنفيذه أبدًا')
}

/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
  console.log('هذا لن يتم تنفيذه أبدًا')
}

مُدوِّنات التغطية

ستقوم مُدوِّنات 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('spies on a function', () => {
  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('spies on a function', () => {
  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('spies on an object method', 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' غير مدعوم حاليًا بواسطة هذا API.

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

test('محاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', () => {
  const fn = mock.fn()

  // اختيار ما يجب محاكاته (اختياري)
  mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // التقدم في الزمن
  mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)

  // إعادة تعيين المحاكيات المُتَبَعة عالميًا.
  mock.timers.reset()

  // إذا قمت باستدعاء إعادة تعيين مثيل المحاكاة، فسيتم أيضًا إعادة تعيين مثيل المؤقتات
  mock.reset()
})
js
const assert = require('node:assert')
const { mock, test } = require('node:test')

test('محاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', () => {
  const fn = mock.fn()

  // اختيار ما يجب محاكاته (اختياري)
  mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // التقدم في الزمن
  mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)

  // إعادة تعيين المحاكيات المُتَبَعة عالميًا.
  mock.timers.reset()

  // إذا قمت باستدعاء إعادة تعيين مثيل المحاكاة، فسيتم أيضًا إعادة تعيين مثيل المؤقتات
  mock.reset()
})

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

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

test('محاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', context => {
  const fn = context.mock.fn()

  // اختيار ما يجب محاكاته (اختياري)
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // التقدم في الزمن
  context.mock.timers.tick(9999)
  assert.strictEqual(fn.mock.callCount(), 1)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('محاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', context => {
  const fn = context.mock.fn()

  // اختيار ما يجب محاكاته (اختياري)
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(fn, 9999)
  assert.strictEqual(fn.mock.callCount(), 0)

  // التقدم في الزمن
  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 في عصر يونيكس. وهو 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('suite of snapshot tests', () => {
  test('snapshot test', t => {
    t.assert.snapshot({ value1: 1, value2: 2 })
    t.assert.snapshot(5)
  })
})

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

js
exports[`suite of snapshot tests > snapshot test 1`] = `
{
  "value1": 1,
  "value2": 2
}
`

exports[`suite of snapshot tests > snapshot test 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 نتائج الاختبار بتنسيق XML من jUnit
  • 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])

[History]

الإصدارالتغييرات
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> مصفوفة من أعلام سطر الأوامر التي سيتم تمريرها إلى قابل التنفيذ node عند إنشاء العمليات الفرعية. لا يؤثر هذا الخيار عندما يكون isolation هو 'none'. الافتراضي: []

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

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

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

    • testSkipPatterns <string> | <RegExp> | <Array> سلسلة، أو تعبير عادي، أو مصفوفة تعابير عادية، يمكن استخدامها لاستبعاد تشغيل الاختبارات التي يطابق اسمها النمط المقدم. يتم تفسير أنماط أسماء الاختبارات على أنها تعابير عادية لـ 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])

[History]

الإصدارالتغييرات
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 => {
  // سيؤدي استخدام setTimeout() في الاختبار الفرعي التالي إلى جعله يعيش لفترة أطول من اختبار الوالد إذا تمت إزالة 'await' في السطر التالي. بمجرد اكتمال اختبار الوالد، فإنه سيلغي أي اختبارات فرعية قيد التنفيذ.
  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])

أضيف في: v19.8.0، v18.15.0

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

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

[السجل]

الإصدارالتغييرات
v19.8.0، v18.16.0أصبح استدعاء it() مكافئًا لاستدعاء test().
v18.6.0، v16.17.0أضيف في: v18.6.0، v16.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])

أضيف في: v19.8.0، v18.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> دالة الخطاف. إذا استخدم الخطاف وظائف الاستدعاء، فسيتم تمرير دالة الاستدعاء كحجة ثانية. الافتراضي: دالة لا تعمل.
  • 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> دالة الخطاف. إذا استخدم الخطاف وظائف الاستدعاء، فسيتم تمرير دالة الاستدعاء كحجة ثانية. الافتراضي: دالة لا تعمل.
  • 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

عامل حصول يعيد نسخة من المصفوفة الداخلية المستخدمة لتتبع المكالمات للمحاكي. كل إدخال في المصفوفة هو كائن به الخصائص التالية.

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

ctx.callCount()

مضاف في: v19.1.0، v18.13.0

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

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

ctx.mockImplementation(implementation)

مُضاف في: v19.1.0، v18.13.0

  • implementation <Function> | <AsyncFunction> الدالة التي سيتم استخدامها كتنفيذ جديد للمحاكاة.

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

يوضح المثال التالي إنشاء دالة محاكاة باستخدام t.mock.fn()، و استدعاء دالة المحاكاة، ثم تغيير تنفيذ المحاكاة إلى دالة مختلفة.

js
test('changes a mock behavior', 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('changes a mock behavior once', 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] كـ getter. لا يمكن استخدام هذا الخيار مع خيار setter. الافتراضي: false.
    • setter <boolean> إذا كانت true، فسيتم التعامل مع object[methodName] كـ setter. لا يمكن استخدام هذا الخيار مع خيار getter. الافتراضي: false.
    • times <integer> عدد المرات التي ستستخدم فيها المحاكاة سلوك implementation. بمجرد استدعاء الطريقة المحاكاة times مرات، سيتم استعادة السلوك الأصلي تلقائيًا. يجب أن تكون هذه القيمة عددًا صحيحًا أكبر من الصفر. الافتراضي: Infinity.
  • القيمة المعادة: <Proxy> الطريقة المحاكاة. تحتوي الطريقة المحاكاة على خاصية mock خاصة، وهي مثيل لـ MockFunctionContext، ويمكن استخدامها لفحص وتغيير سلوك الطريقة المحاكاة.

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

js
test('spies on an object method', 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.

Class: MockTimers

[السجل]

الإصدارالتغييرات
v23.1.0أصبحت مؤقتات المحاكاة مستقرة الآن.
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)
})

استخدام دوال التصفية

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

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

test('تقوم بمحاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', context => {
  const fn = context.mock.fn()

  // اختيار ما يجب محاكاته اختياريًا
  context.mock.timers.enable({ apis: ['setTimeout'] })
  const id = setTimeout(fn, 9999)

  // يتم محاكاتها ضمنيًا أيضًا
  clearTimeout(id)
  context.mock.timers.tick(9999)

  // بما أن setTimeout تم مسحه، فلن يتم استدعاء دالة المحاكاة أبدًا
  assert.strictEqual(fn.mock.callCount(), 0)
})
js
const assert = require('node:assert')
const { test } = require('node:test')

test('تقوم بمحاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', context => {
  const fn = context.mock.fn()

  // اختيار ما يجب محاكاته اختياريًا
  context.mock.timers.enable({ apis: ['setTimeout'] })
  const id = setTimeout(fn, 9999)

  // يتم محاكاتها ضمنيًا أيضًا
  clearTimeout(id)
  context.mock.timers.tick(9999)

  // بما أن setTimeout تم مسحه، فلن يتم استدعاء دالة المحاكاة أبدًا
  assert.strictEqual(fn.mock.callCount(), 0)
})

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

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

ملاحظة: لا يدعم هذا API حاليًا دوال التفكيك مثل 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('تقوم بمحاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', async context => {
  const globalTimeoutObjectSpy = context.mock.fn()
  const nodeTimerSpy = context.mock.fn()
  const nodeTimerPromiseSpy = context.mock.fn()

  // اختيار ما يجب محاكاته اختياريًا
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(globalTimeoutObjectSpy, 9999)
  nodeTimers.setTimeout(nodeTimerSpy, 9999)

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

  // التقدم في الزمن
  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('تقوم بمحاكاة setTimeout ليتم تنفيذه بشكل متزامن دون الحاجة إلى الانتظار الفعلي له', async context => {
  const globalTimeoutObjectSpy = context.mock.fn()
  const nodeTimerSpy = context.mock.fn()
  const nodeTimerPromiseSpy = context.mock.fn()

  // اختيار ما يجب محاكاته اختياريًا
  context.mock.timers.enable({ apis: ['setTimeout'] })
  setTimeout(globalTimeoutObjectSpy, 9999)
  nodeTimers.setTimeout(nodeTimerSpy, 9999)

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

  // التقدم في الزمن
  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 ويدعمه هذا API أيضًا:

js
import assert from 'node:assert'
import { test } from 'node:test'
import nodeTimersPromises from 'node:timers/promises'
test('يجب أن ينقر خمس مرات لاختبار حالة استخدام حقيقية', 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('يجب أن ينقر خمس مرات لاختبار حالة استخدام حقيقية', 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)

  // لاحظ أنه إذا كان لكل من المؤقتين نفس مهلة الوقت،
  // يُضمن ترتيب التنفيذ
  setTimeout(() => results.push(3), 8888)
  setTimeout(() => results.push(2), 8888)

  assert.deepStrictEqual(results, [])

  context.mock.timers.runAll()
  assert.deepStrictEqual(results, [3, 2, 1])
  // يتم أيضًا تحسين كائن Date إلى أقصى وقت للمؤقت
  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)

  // لاحظ أنه إذا كان لكل من المؤقتين نفس مهلة الوقت،
  // يُضمن ترتيب التنفيذ
  setTimeout(() => results.push(3), 8888)
  setTimeout(() => results.push(2), 8888)

  assert.deepStrictEqual(results, [])

  context.mock.timers.runAll()
  assert.deepStrictEqual(results, [3, 2, 1])
  // يتم أيضًا تحسين كائن Date إلى أقصى وقت للمؤقت
  assert.strictEqual(Date.now(), 9999)
})

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

timers.setTime(milliseconds)

أضيف في: v21.2.0، v20.11.0

يُعيّن طابع زمني يونكس الحالي الذي سيتم استخدامه كمرجع لأي كائنات 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
  assert.deepStrictEqual(Date.now(), now)

  context.mock.timers.enable({ apis: ['Date'] })
  context.mock.timers.setTime(setTime)
  // أصبح Date.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
  assert.deepStrictEqual(Date.now(), now)

  context.mock.timers.enable({ apis: ['Date'] })
  context.mock.timers.setTime(setTime)
  // أصبح Date.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('runAll functions following the given order', 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('runAll functions following the given order', 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تمت إضافة نوع إلى اختبار: اجتياز واختبار: أحداث الفشل عندما يكون الاختبار عبارة عن مجموعة.
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('top level test', async t => {
  t.after(t => t.diagnostic(`finished running ${t.name}`))
  assert.ok('some relevant assertion here')
})

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

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

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

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

js
test('top level test', async t => {
  t.afterEach(t => t.diagnostic(`finished running ${t.name}`))
  await t.test('This is a subtest', t => {
    assert.ok('some relevant assertion here')
  })
})

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 <أي> قيمة لتحويلها إلى سلسلة. إذا تم تشغيل Node.js باستخدام علم --test-update-snapshots، فسيتم كتابة القيمة المُسلسلة إلى ملف اللقطة. خلاف ذلك، يتم مقارنة القيمة المُسلسلة بالقيمة المقابلة في ملف اللقطة الحالي.
  • options <كائن> خيارات تكوين اختيارية. يتم دعم الخصائص التالية:
    • serializers <مصفوفة> مصفوفة من الدوال المتزامنة المستخدمة لتحويل 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)

تم الإضافة في: v18.0.0، v16.17.0

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

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

js
test('top level test', t => {
  // يمكن تعيين سياق الاختبار لتشغيل اختبارات فرعية باستخدام خيار 'only'.
  t.runOnly(true)
  return Promise.all([t.test('this subtest is now skipped'), t.test('this subtest is run', { only: true })])
})

context.signal

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

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

js
test('top level test', async t => {
  await fetch('some/uri', { signal: t.signal })
})

context.skip([message])

تم الإضافة في: v18.0.0، v16.17.0

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

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

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

context.todo([message])

تم الإضافة في: v18.0.0، v16.17.0

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

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

js
test('top level test', t => {
  // تم تمييز هذا الاختبار على أنه `TODO`
  t.todo('this is a todo')
})

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

[History]

الإصدارالتغييرات
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. إذا كان الاختبار يستخدم عمليات الاستدعاء العكسية، فسيتم تمرير دالة الاستدعاء العكسي كوسيط ثاني. الافتراضي: دالة لا تعمل.

  • القيمة المرجعة: <Promise> مكتملة مع undefined بمجرد اكتمال الاختبار.

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

js
test('top level test', async t => {
  await t.test('This is a subtest', { only: false, skip: false, concurrency: 1, todo: false, plan: 1 }, t => {
    t.assert.ok('some relevant assertion here')
  })
})

الصنف: SuiteContext

مضاف في: v18.7.0، v16.17.0

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

context.filePath

مضاف في: v22.6.0

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

context.name

مضاف في: v18.8.0، v16.18.0

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

context.signal

مضاف في: v18.7.0، v16.17.0

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