مُشَغِّل الاختبار
[التاريخ]
الإصدار | التغييرات |
---|---|
v20.0.0 | مُشَغِّل الاختبار الآن مستقر. |
v18.0.0, v16.17.0 | تمت إضافته في: v18.0.0, v16.17.0 |
[مستقر: 2 - مستقر]
مستقر: 2 الاستقرار: 2 - مستقر
الكود المصدري: lib/test.js
تُسهِّل وحدة node:test
إنشاء اختبارات JavaScript. للوصول إليها:
import test from 'node:test';
const test = require('node:test');
هذه الوحدة متاحة فقط ضمن نظام node:
.
تتكون الاختبارات التي تم إنشاؤها عبر وحدة test
من دالة واحدة تتم معالجتها بإحدى ثلاث طرق:
يوضح المثال التالي كيفية كتابة الاختبارات باستخدام وحدة test
.
test('اختبار تمرير متزامن', (t) => {
// ينجح هذا الاختبار لأنه لا يطرح استثناءً.
assert.strictEqual(1, 1);
});
test('اختبار فشل متزامن', (t) => {
// يفشل هذا الاختبار لأنه يطرح استثناءً.
assert.strictEqual(1, 2);
});
test('اختبار تمرير غير متزامن', async (t) => {
// ينجح هذا الاختبار لأن الوعد الذي تم إرجاعه بواسطة الدالة غير المتزامنة
// قد تم تسويته ولم يتم رفضه.
assert.strictEqual(1, 1);
});
test('اختبار فشل غير متزامن', async (t) => {
// يفشل هذا الاختبار لأن الوعد الذي تم إرجاعه بواسطة الدالة غير المتزامنة
// قد تم رفضه.
assert.strictEqual(1, 2);
});
test('اختبار فاشل باستخدام الوعود', (t) => {
// يمكن استخدام الوعود مباشرة أيضًا.
return new Promise((resolve, reject) => {
setImmediate(() => {
reject(new Error('سيتسبب هذا في فشل الاختبار'));
});
});
});
test('اختبار تمرير رد نداء', (t, done) => {
// done() هي دالة رد النداء. عندما يتم تشغيل setImmediate()، فإنها تستدعي
// done() بدون وسائط.
setImmediate(done);
});
test('اختبار فشل رد نداء', (t, done) => {
// عندما يتم تشغيل setImmediate()، يتم استدعاء done() بكائن خطأ و
// يفشل الاختبار.
setImmediate(() => {
done(new Error('فشل رد النداء'));
});
});
إذا فشلت أي اختبارات، فسيتم تعيين رمز خروج العملية إلى 1
.
الاختبارات الفرعية
تسمح طريقة test()
في سياق الاختبار بإنشاء اختبارات فرعية. فهي تسمح لك بتنظيم اختباراتك بطريقة هرمية، حيث يمكنك إنشاء اختبارات متداخلة داخل اختبار أكبر. تتصرف هذه الطريقة بشكل مماثل لوظيفة test()
ذات المستوى الأعلى. يوضح المثال التالي إنشاء اختبار على مستوى أعلى مع اختبارين فرعيين.
test('اختبار المستوى الأعلى', async (t) => {
await t.test('الاختبار الفرعي 1', (t) => {
assert.strictEqual(1, 1);
});
await t.test('الاختبار الفرعي 2', (t) => {
assert.strictEqual(2, 2);
});
});
في هذا المثال، يتم استخدام await
للتأكد من اكتمال كلا الاختبارين الفرعيين. هذا ضروري لأن الاختبارات لا تنتظر اكتمال اختباراتها الفرعية، على عكس الاختبارات التي تم إنشاؤها داخل المجموعات. يتم إلغاء أي اختبارات فرعية لا تزال معلقة عند انتهاء الاختبار الأصل، وتعتبر فاشلة. أي فشل في الاختبارات الفرعية يتسبب في فشل الاختبار الأصل.
تخطي الاختبارات
يمكن تخطي الاختبارات الفردية عن طريق تمرير خيار skip
إلى الاختبار، أو عن طريق استدعاء طريقة skip()
في سياق الاختبار كما هو موضح في المثال التالي.
// يتم استخدام خيار التخطي، ولكن لم يتم تقديم أي رسالة.
test('خيار التخطي', { skip: true }, (t) => {
// لن يتم تنفيذ هذا الكود.
});
// يتم استخدام خيار التخطي، ويتم تقديم رسالة.
test('خيار التخطي مع رسالة', { skip: 'تم تخطي هذا' }, (t) => {
// لن يتم تنفيذ هذا الكود.
});
test('طريقة skip()', (t) => {
// تأكد من العودة هنا أيضًا إذا كان الاختبار يحتوي على منطق إضافي.
t.skip();
});
test('طريقة skip() مع رسالة', (t) => {
// تأكد من العودة هنا أيضًا إذا كان الاختبار يحتوي على منطق إضافي.
t.skip('تم تخطي هذا');
});
اختبارات TODO
يمكن وضع علامة على الاختبارات الفردية على أنها متقلبة أو غير مكتملة عن طريق تمرير خيار todo
إلى الاختبار، أو عن طريق استدعاء طريقة todo()
في سياق الاختبار، كما هو موضح في المثال التالي. تمثل هذه الاختبارات تنفيذًا معلقًا أو خطأ يحتاج إلى إصلاح. يتم تنفيذ اختبارات TODO، ولكن لا يتم التعامل معها على أنها حالات فشل في الاختبار، وبالتالي لا تؤثر على رمز إنهاء العملية. إذا تم وضع علامة على الاختبار على أنه TODO وتم تخطيه في نفس الوقت، فسيتم تجاهل خيار TODO.
// يتم استخدام خيار 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()
.
describe('شيء ما', () => {
it('يجب أن يعمل', () => {
assert.strictEqual(1, 1);
});
it('يجب أن يكون على ما يرام', () => {
assert.strictEqual(2, 2);
});
describe('شيء متداخل', () => {
it('يجب أن يعمل', () => {
assert.strictEqual(3, 3);
});
});
});
يتم استيراد describe()
و it()
من الوحدة النمطية node:test
.
import { describe, it } from 'node:test';
const { describe, it } = require('node:test');
اختبارات only
إذا بدأ Node.js باستخدام خيار سطر الأوامر --test-only
، أو تم تعطيل عزل الاختبار، فمن الممكن تخطي جميع الاختبارات باستثناء مجموعة فرعية محددة عن طريق تمرير الخيار only
إلى الاختبارات التي يجب تشغيلها. عند تعيين اختبار بالخيار only
، يتم تشغيل جميع الاختبارات الفرعية أيضًا. إذا كانت المجموعة تحتوي على الخيار only
، فسيتم تشغيل جميع الاختبارات داخل المجموعة، إلا إذا كان لديها أحفاد تم تعيين الخيار only
عليها، وفي هذه الحالة يتم تشغيل هذه الاختبارات فقط.
عند استخدام الاختبارات الفرعية داخل test()
/it()
، فمن الضروري وضع علامة على جميع اختبارات الأصل بالخيار only
لتشغيل مجموعة فرعية محددة فقط من الاختبارات.
يمكن استخدام طريقة runOnly()
لسياق الاختبار لتنفيذ نفس السلوك على مستوى الاختبار الفرعي. يتم حذف الاختبارات التي لم يتم تنفيذها من ناتج مشغل الاختبار.
// افترض أن Node.js يتم تشغيله باستخدام خيار سطر الأوامر --test-only.
// تم تعيين الخيار 'only' للمجموعة، لذلك يتم تشغيل هذه الاختبارات.
test('يتم تشغيل هذا الاختبار', { only: true }, async (t) => {
// ضمن هذا الاختبار، يتم تشغيل جميع الاختبارات الفرعية افتراضيًا.
await t.test('تشغيل اختبار فرعي');
// يمكن تحديث سياق الاختبار لتشغيل الاختبارات الفرعية بالخيار 'only'.
t.runOnly(true);
await t.test('تم تخطي هذا الاختبار الفرعي الآن');
await t.test('يتم تشغيل هذا الاختبار الفرعي', { only: true });
// قم بتبديل السياق مرة أخرى لتنفيذ جميع الاختبارات.
t.runOnly(false);
await t.test('يتم تشغيل هذا الاختبار الفرعي الآن');
// لا تقم بتشغيل هذه الاختبارات بشكل صريح.
await t.test('تم تخطي الاختبار الفرعي 3', { only: false });
await t.test('تم تخطي الاختبار الفرعي 4', { skip: true });
});
// لم يتم تعيين الخيار 'only'، لذلك يتم تخطي هذا الاختبار.
test('لم يتم تشغيل هذا الاختبار', () => {
// لم يتم تشغيل هذا الكود.
throw new Error('فشل');
});
describe('مجموعة', () => {
// تم تعيين الخيار 'only'، لذلك يتم تشغيل هذا الاختبار.
it('يتم تشغيل هذا الاختبار', { only: true }, () => {
// يتم تشغيل هذا الكود.
});
it('لم يتم تشغيل هذا الاختبار', () => {
// لم يتم تشغيل هذا الكود.
throw new Error('فشل');
});
});
describe.only('مجموعة', () => {
// تم تعيين الخيار 'only'، لذلك يتم تشغيل هذا الاختبار.
it('يتم تشغيل هذا الاختبار', () => {
// يتم تشغيل هذا الكود.
});
it('يتم تشغيل هذا الاختبار', () => {
// يتم تشغيل هذا الكود.
});
});
تصفية الاختبارات بالاسم
يمكن استخدام خيار سطر الأوامر --test-name-pattern
لتشغيل الاختبارات التي يتطابق اسمها فقط مع النمط المقدم، ويمكن استخدام الخيار --test-skip-pattern
لتخطي الاختبارات التي يتطابق اسمها مع النمط المقدم. يتم تفسير أنماط أسماء الاختبارات على أنها تعبيرات JavaScript منتظمة. يمكن تحديد الخيارين --test-name-pattern
و --test-skip-pattern
عدة مرات لتشغيل الاختبارات المتداخلة. لكل اختبار يتم تنفيذه، يتم أيضًا تشغيل أي خطافات اختبار مقابلة، مثل beforeEach()
. يتم حذف الاختبارات التي لم يتم تنفيذها من إخراج مشغل الاختبار.
بالنظر إلى ملف الاختبار التالي، سيؤدي بدء تشغيل Node.js باستخدام الخيار --test-name-pattern="test [1-3]"
إلى قيام مشغل الاختبار بتنفيذ test 1
و test 2
و test 3
. إذا لم يتطابق test 1
مع نمط اسم الاختبار، فلن يتم تنفيذ اختباراته الفرعية، على الرغم من مطابقتها للنمط. يمكن أيضًا تنفيذ نفس مجموعة الاختبارات عن طريق تمرير --test-name-pattern
عدة مرات (على سبيل المثال، --test-name-pattern="test 1"
، --test-name-pattern="test 2"
، إلخ.).
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
لأن النمط غير حساس لحالة الأحرف.
لمطابقة اختبار واحد بنمط، يمكنك إضافة بادئة إليه بجميع أسماء الاختبار الأصلية مفصولة بمسافة، للتأكد من أنه فريد. على سبيل المثال، بالنظر إلى ملف الاختبار التالي:
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>.
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
:
node --test --watch
في وضع المراقبة، سيراقب مُشغّل الاختبار التغييرات التي تطرأ على ملفات الاختبار والتبعيات الخاصة بها. عند اكتشاف تغيير، سيعيد مُشغّل الاختبار تشغيل الاختبارات المتأثرة بالتغيير. سيستمر مُشغّل الاختبار في التشغيل حتى يتم إنهاء العملية.
تشغيل الاختبارات من سطر الأوامر
يمكن استدعاء مُشغّل اختبار Node.js من سطر الأوامر عن طريق تمرير العلامة --test
:
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، مما قد يقلل من إمكانية النقل عبر الأنظمة.
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'
.
يمكن تعطيل التغطية على سلسلة من الأسطر باستخدام بنية التعليقات التالية:
/* node:coverage disable */
if (anAlwaysFalseCondition) {
// لن يتم تنفيذ الكود في هذا الفرع أبدًا، ولكن يتم تجاهل الأسطر لأغراض التغطية. يتم تجاهل جميع الأسطر التي تلي تعليق "disable"
// حتى تتم مصادفة تعليق "enable" مطابق.
console.log('this is never executed');
}
/* node:coverage enable */
يمكن أيضًا تعطيل التغطية لعدد محدد من الأسطر. بعد العدد المحدد من الأسطر، سيتم إعادة تمكين التغطية تلقائيًا. إذا لم يتم توفير عدد الأسطر بشكل صريح، فسيتم تجاهل سطر واحد.
/* node:coverage ignore next */
if (anAlwaysFalseCondition) { console.log('this is never executed'); }
/* node:coverage ignore next 3 */
if (anAlwaysFalseCondition) {
console.log('this is never executed');
}
مراسلو التغطية
سيقوم مراسلو tap و spec بطباعة ملخص لإحصائيات التغطية. يوجد أيضًا مراسل lcov سيقوم بإنشاء ملف lcov يمكن استخدامه كتقرير تغطية متعمق.
node --test --experimental-test-coverage --test-reporter=lcov --test-reporter-destination=lcov.info
- لا يتم الإبلاغ عن أي نتائج اختبار بواسطة هذا المراسل.
- من الناحية المثالية، يجب استخدام هذا المراسل جنبًا إلى جنب مع مراسل آخر.
المحاكاة
تدعم الوحدة node:test
المحاكاة أثناء الاختبار عبر كائن mock
ذي مستوى أعلى. ينشئ المثال التالي تجسسًا على دالة تجمع رقمين معًا. ثم يتم استخدام التجسس للتأكد من استدعاء الدالة كما هو متوقع.
import assert from 'node:assert';
import { mock, test } from 'node:test';
test('يتجسس على دالة', () => {
const sum = mock.fn((a, b) => {
return a + b;
});
assert.strictEqual(sum.mock.callCount(), 0);
assert.strictEqual(sum(3, 4), 7);
assert.strictEqual(sum.mock.callCount(), 1);
const call = sum.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3, 4]);
assert.strictEqual(call.result, 7);
assert.strictEqual(call.error, undefined);
// إعادة تعيين عمليات المحاكاة المتعقبة عالميًا.
mock.reset();
});
'use strict';
const assert = require('node:assert');
const { mock, test } = require('node:test');
test('يتجسس على دالة', () => {
const sum = mock.fn((a, b) => {
return a + b;
});
assert.strictEqual(sum.mock.callCount(), 0);
assert.strictEqual(sum(3, 4), 7);
assert.strictEqual(sum.mock.callCount(), 1);
const call = sum.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3, 4]);
assert.strictEqual(call.result, 7);
assert.strictEqual(call.error, undefined);
// إعادة تعيين عمليات المحاكاة المتعقبة عالميًا.
mock.reset();
});
يتم أيضًا عرض نفس وظيفة المحاكاة على كائن TestContext
الخاص بكل اختبار. ينشئ المثال التالي تجسسًا على طريقة كائن باستخدام واجهة برمجة التطبيقات المعروضة على TestContext
. تتمثل فائدة المحاكاة عبر سياق الاختبار في أن مشغل الاختبار سيستعيد تلقائيًا جميع الوظائف المحاكاة بمجرد انتهاء الاختبار.
test('يتجسس على طريقة كائن', (t) => {
const number = {
value: 5,
add(a) {
return this.value + a;
},
};
t.mock.method(number, 'add');
assert.strictEqual(number.add.mock.callCount(), 0);
assert.strictEqual(number.add(3), 8);
assert.strictEqual(number.add.mock.callCount(), 1);
const call = number.add.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3]);
assert.strictEqual(call.result, 8);
assert.strictEqual(call.target, undefined);
assert.strictEqual(call.this, number);
});
المؤقتات
تعتبر المؤقتات الوهمية تقنية شائعة الاستخدام في اختبار البرامج لمحاكاة والتحكم في سلوك المؤقتات، مثل setInterval
و setTimeout
، دون الانتظار فعليًا للفترات الزمنية المحددة.
راجع الفئة MockTimers
للحصول على قائمة كاملة بالطرق والميزات.
يتيح ذلك للمطورين كتابة اختبارات أكثر موثوقية وقابلية للتنبؤ للوظائف التي تعتمد على الوقت.
يوضح المثال أدناه كيفية محاكاة setTimeout
. باستخدام .enable({ apis: ['setTimeout'] });
سيقوم بمحاكاة وظائف setTimeout
في وحدات node:timers و node:timers/promises، وكذلك من سياق Node.js العام.
ملاحظة: لا يتم دعم تفكيك الدوال مثل import { setTimeout } from 'node:timers'
حاليًا بواسطة واجهة برمجة التطبيقات هذه.
import assert from 'node:assert';
import { mock, test } from 'node:test';
test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => {
const fn = mock.fn();
// Optionally choose what to mock
mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Advance in time
mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
// Reset the globally tracked mocks.
mock.timers.reset();
// If you call reset mock instance, it will also reset timers instance
mock.reset();
});
const assert = require('node:assert');
const { mock, test } = require('node:test');
test('mocks setTimeout to be executed synchronously without having to actually wait for it', () => {
const fn = mock.fn();
// Optionally choose what to mock
mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Advance in time
mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
// Reset the globally tracked mocks.
mock.timers.reset();
// If you call reset mock instance, it will also reset timers instance
mock.reset();
});
يتم أيضًا عرض نفس وظيفة المحاكاة في خاصية mock على كائن TestContext
لكل اختبار. الفائدة من المحاكاة عبر سياق الاختبار هي أن مشغل الاختبار سيستعيد تلقائيًا جميع وظائف المؤقتات المحاكاة بمجرد انتهاء الاختبار.
import assert from 'node:assert';
import { test } from 'node:test';
test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
const fn = context.mock.fn();
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
const fn = context.mock.fn();
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
});
التواريخ
تسمح واجهة برمجة تطبيقات المؤقتات الوهمية أيضًا بمحاكاة كائن Date
. هذه ميزة مفيدة لاختبار الوظائف التي تعتمد على الوقت، أو لمحاكاة وظائف التقويم الداخلية مثل Date.now()
.
يعد تطبيق التواريخ أيضًا جزءًا من فئة MockTimers
. ارجع إليها للحصول على قائمة كاملة بالطرق والميزات.
ملاحظة: تعتمد التواريخ والمؤقتات على بعضها البعض عند محاكاتها معًا. هذا يعني أنه إذا كان لديك كل من Date
و setTimeout
محاكيين، فإن تقديم الوقت سيقدم أيضًا التاريخ المحاكى لأنهما يحاكيان ساعة داخلية واحدة.
يوضح المثال أدناه كيفية محاكاة كائن Date
والحصول على قيمة Date.now()
الحالية.
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);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('mocks the Date object', (context) => {
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['Date'] });
// If not specified, the initial date will be based on 0 in the UNIX epoch
assert.strictEqual(Date.now(), 0);
// Advance in time will also advance the date
context.mock.timers.tick(9999);
assert.strictEqual(Date.now(), 9999);
});
إذا لم يتم تعيين أي حقبة أولية، فسيعتمد التاريخ الأولي على 0 في حقبة Unix. هذا هو 1 يناير 1970، 00:00:00 بالتوقيت العالمي المنسق. يمكنك تعيين تاريخ أولي عن طريق تمرير خاصية now
إلى طريقة .enable()
. سيتم استخدام هذه القيمة كتاريخ أولي لكائن Date
المحاكى. يمكن أن يكون إما عددًا صحيحًا موجبًا، أو كائن تاريخ آخر.
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);
});
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()
لنقل التاريخ المحاكى يدويًا إلى وقت آخر. تقبل هذه الطريقة عددًا صحيحًا موجبًا فقط.
ملاحظة: ستنفذ هذه الطريقة أي مؤقتات محاكية موجودة في الماضي من الوقت الجديد.
في المثال أدناه، نقوم بتعيين وقت جديد للتاريخ المحاكى.
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);
});
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()
. هذا مفيد إذا كنت تريد اختبار الوظائف التي تعتمد على الوقت والتي حدثت بالفعل في الماضي.
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);
});
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()
إلى تنفيذ جميع المؤقتات الموجودة حاليًا في قائمة الانتظار. سيؤدي هذا أيضًا إلى تقديم التاريخ المحاكى إلى وقت آخر مؤقت تم تنفيذه كما لو كان الوقت قد مر.
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);
});
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()
. يتوافق كل تأكيد للقطة مع تصدير في ملف اللقطة.
يظهر مثال على اختبار اللقطة أدناه. في المرة الأولى التي يتم فيها تنفيذ هذا الاختبار، سيفشل لأن ملف اللقطة المقابل غير موجود.
// test.js
suite('مجموعة اختبارات اللقطات', () => {
test('اختبار اللقطة', (t) => {
t.assert.snapshot({ value1: 1, value2: 2 });
t.assert.snapshot(5);
});
});
قم بإنشاء ملف اللقطة عن طريق تشغيل ملف الاختبار باستخدام --test-update-snapshots
. يجب أن يجتاز الاختبار، ويتم إنشاء ملف باسم test.js.snapshot
في نفس الدليل الذي يوجد به ملف الاختبار. يظهر محتوى ملف اللقطة أدناه. يتم تحديد كل لقطة بالاسم الكامل للاختبار وعداد للتمييز بين اللقطات في نفس الاختبار.
exports[`مجموعة اختبارات اللقطات > اختبار اللقطة 1`] = `
{
"value1": 1,
"value2": 2
}
`;
exports[`مجموعة اختبارات اللقطات > اختبار اللقطة 2`] = `
5
`;
بمجرد إنشاء ملف اللقطة، قم بتشغيل الاختبارات مرة أخرى بدون علامة --test-update-snapshots
. يجب أن تجتاز الاختبارات الآن.
مراسلو الاختبار
[تاريخ]
الإصدار | التغييرات |
---|---|
v19.9.0, v18.17.0 | يتم الآن عرض المراسلين في node:test/reporters . |
v19.6.0, v18.15.0 | تمت إضافته في: v19.6.0, v18.15.0 |
تدعم الوحدة node:test
تمرير علامات --test-reporter
ليستخدم عداء الاختبار مراسلًا محددًا.
المراسلون المضمنون التاليون مدعومون:
spec
يُخرج المراسلspec
نتائج الاختبار بتنسيق يمكن للبشر قراءته. هذا هو المراسل الافتراضي.tap
يُخرج المراسلtap
نتائج الاختبار بتنسيق TAP.dot
يُخرج المراسلdot
نتائج الاختبار بتنسيق مضغوط، حيث يتم تمثيل كل اختبار ناجح بـ.
، ويتم تمثيل كل اختبار فاشل بـX
.junit
يُخرج المراسلjunit
نتائج الاختبار بتنسيق jUnit XMLlcov
يُخرج المراسلlcov
تغطية الاختبار عند استخدامه مع علامة--experimental-test-coverage
.
الإخراج الدقيق لهؤلاء المراسلين عرضة للتغيير بين إصدارات Node.js، ولا ينبغي الاعتماد عليه برمجيًا. إذا كانت هناك حاجة للوصول البرمجي إلى إخراج عداء الاختبار، فاستخدم الأحداث التي تنبعث من <TestsStream>.
تتوفر المراسلون عبر الوحدة node:test/reporters
:
import { tap, spec, dot, junit, lcov } from 'node:test/reporters';
const { tap, spec, dot, junit, lcov } = require('node:test/reporters');
مراسلون مخصصون
يمكن استخدام --test-reporter
لتحديد مسار إلى مراسل مخصص. المراسل المخصص هو وحدة تصدر قيمة مقبولة بواسطة stream.compose. يجب أن تحول المراسلون الأحداث التي تنبعث من <TestsStream>
مثال على مراسل مخصص باستخدام <stream.Transform>:
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;
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;
مثال على مراسل مخصص باستخدام دالة مولد:
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;
}
}
}
}
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
:
node --test-reporter=spec --test-reporter=dot --test-reporter-destination=stdout --test-reporter-destination=file.txt
عند تحديد مراسل واحد، ستكون الوجهة افتراضيًا stdout
، ما لم يتم توفير وجهة بشكل صريح.
run([options])
[سجل التغييرات]
الإصدار | التغييرات |
---|---|
v23.0.0 | تمت إضافة خيار cwd . |
v23.0.0 | تمت إضافة خيارات التغطية. |
v22.8.0 | تمت إضافة خيار isolation . |
v22.6.0 | تمت إضافة خيار globPatterns . |
v22.0.0, v20.14.0 | تمت إضافة خيار forceExit . |
v20.1.0, v18.17.0 | تمت إضافة خيار testNamePatterns. |
v18.9.0, v16.19.0 | تمت إضافته في: v18.9.0, v16.19.0 |
options
<Object> خيارات تكوين لتشغيل الاختبارات. الخصائص التالية مدعومة:concurrency
<number> | <boolean> إذا تم توفير رقم، فسيتم تشغيل هذا العدد من عمليات الاختبار بالتوازي، حيث تتوافق كل عملية مع ملف اختبار واحد. إذا كانtrue
، فسيتم تشغيلos.availableParallelism() - 1
ملف اختبار بالتوازي. إذا كانfalse
، فسيتم تشغيل ملف اختبار واحد فقط في كل مرة. افتراضي:false
.cwd
: <string> يحدد دليل العمل الحالي الذي سيستخدمه مشغل الاختبار. يعمل كمسار أساسي لحل الملفات وفقًا لـ نموذج تنفيذ مشغل الاختبار. افتراضي:process.cwd()
.files
: <Array> مصفوفة تحتوي على قائمة الملفات المراد تشغيلها. افتراضي: مطابقة الملفات من نموذج تنفيذ مشغل الاختبار.forceExit
: <boolean> يقوم بتكوين مشغل الاختبار للخروج من العملية بمجرد انتهاء جميع الاختبارات المعروفة من التنفيذ حتى إذا ظلت حلقة الأحداث نشطة بخلاف ذلك. افتراضي:false
.globPatterns
: <Array> مصفوفة تحتوي على قائمة أنماط glob لمطابقة ملفات الاختبار. لا يمكن استخدام هذا الخيار معfiles
. افتراضي: مطابقة الملفات من نموذج تنفيذ مشغل الاختبار.inspectPort
<number> | <Function> يعين منفذ الفحص لعملية اختبار فرعية. يمكن أن يكون هذا رقمًا أو دالة لا تأخذ أي وسيطات وترجع رقمًا. إذا تم توفير قيمة خالية، فستحصل كل عملية على منفذ خاص بها، يتم زيادته منprocess.debugPort
الرئيسي. يتم تجاهل هذا الخيار إذا تم تعيين خيارisolation
على'none'
حيث لا يتم إنشاء أي عمليات فرعية. افتراضي:undefined
.isolation
<string> يقوم بتكوين نوع عزل الاختبار. إذا تم تعيينه على'process'
، فسيتم تشغيل كل ملف اختبار في عملية فرعية منفصلة. إذا تم تعيينه على'none'
، فسيتم تشغيل جميع ملفات الاختبار في العملية الحالية. افتراضي:'process'
.only
: <boolean> إذا كانت القيمة صحيحة، فسياق الاختبار سيقوم فقط بتشغيل الاختبارات التي تم تعيين خيارonly
لهاsetup
<Function> دالة تقبل مثيلTestsStream
ويمكن استخدامها لإعداد المستمعين قبل تشغيل أي اختبارات. افتراضي:undefined
.execArgv
<Array> مصفوفة من علامات CLI لتمريرها إلى الملف التنفيذيnode
عند إنشاء العمليات الفرعية. ليس لهذا الخيار أي تأثير عندما يكونisolation
هو'none'
. افتراضي:[]
argv
<Array> مصفوفة من علامات CLI لتمريرها إلى كل ملف اختبار عند إنشاء العمليات الفرعية. ليس لهذا الخيار أي تأثير عندما يكونisolation
هو'none'
. افتراضي:[]
.signal
<AbortSignal> يسمح بإجهاض تنفيذ اختبار قيد التقدم.testNamePatterns
<string> | <RegExp> | <Array> سلسلة أو تعبير RegExp أو مصفوفة RegExp، يمكن استخدامها لتشغيل الاختبارات فقط التي يتطابق اسمها مع النمط المقدم. يتم تفسير أنماط أسماء الاختبارات كتعبيرات JavaScript منتظمة. لكل اختبار يتم تنفيذه، يتم أيضًا تشغيل أي خطافات اختبار مقابلة، مثلbeforeEach()
. افتراضي:undefined
.testSkipPatterns
<string> | <RegExp> | <Array> سلسلة أو تعبير RegExp أو مصفوفة RegExp، يمكن استخدامها لاستبعاد تشغيل الاختبارات التي يتطابق اسمها مع النمط المقدم. يتم تفسير أنماط أسماء الاختبارات كتعبيرات JavaScript منتظمة. لكل اختبار يتم تنفيذه، يتم أيضًا تشغيل أي خطافات اختبار مقابلة، مثلbeforeEach()
. افتراضي:undefined
.timeout
<number> عدد بالمللي ثانية سيفشل تنفيذ الاختبار بعده. إذا لم يتم تحديده، فسوف ترث الاختبارات الفرعية هذه القيمة من الأصل. افتراضي:Infinity
.watch
<boolean> ما إذا كان سيتم التشغيل في وضع المراقبة أم لا. افتراضي:false
.shard
<Object> تشغيل الاختبارات في جزء معين. افتراضي:undefined
.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
، المصمم لتكرار التعليمات البرمجية السريع عن طريق إعادة تشغيل الاختبارات تلقائيًا عند تغيير الملفات.
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);
const { tap } = require('node:test/reporters');
const { run } = require('node:test');
const path = require('node:path');
run({ files: [path.resolve('./tests/test.js')] })
.on('test:fail', () => {
process.exitCode = 1;
})
.compose(tap)
.pipe(process.stdout);
suite([name][, options][, fn])
تمت الإضافة في: v22.0.0, v20.13.0
name
<string> اسم المجموعة، والذي يتم عرضه عند الإبلاغ عن نتائج الاختبار. افتراضي: خاصيةname
الخاصة بـfn
، أو'\<anonymous\>'
إذا لم يكن لـfn
اسم.options
<Object> خيارات تكوين اختيارية للمجموعة. يدعم هذا نفس خياراتtest([name][, options][, fn])
.fn
<Function> | <AsyncFunction> دالة المجموعة التي تعلن عن الاختبارات والمجموعات المتداخلة. الوسيطة الأولى لهذه الدالة هي كائنSuiteContext
. افتراضي: دالة لا تقوم بأي عملية.- الإرجاع: <Promise> تم تحقيقه على الفور بـ
undefined
.
يتم استيراد الدالة suite()
من الوحدة node:test
.
suite.skip([name][, options][, fn])
تمت الإضافة في: v22.0.0, v20.13.0
اختصار لتخطي مجموعة. هذا هو نفسه suite([name], { skip: true }[, fn])
.
suite.todo([name][, options][, fn])
تمت الإضافة في: v22.0.0, v20.13.0
اختصار لتعليم مجموعة على أنها TODO
. هذا هو نفسه suite([name], { todo: true }[, fn])
.
suite.only([name][, options][, fn])
تمت الإضافة في: v22.0.0, v20.13.0
اختصار لتعليم مجموعة على أنها only
. هذا هو نفسه suite([name], { only: true }[, fn])
.
test([name][, options][, fn])
[سجل التغييرات]
الإصدار | التغييرات |
---|---|
v20.2.0, v18.17.0 | تمت إضافة الاختصارات skip و todo و only . |
v18.8.0, v16.18.0 | إضافة خيار signal . |
v18.7.0, v16.17.0 | إضافة خيار timeout . |
v18.0.0, v16.17.0 | تمت الإضافة في: v18.0.0, v16.17.0 |
name
<string> اسم الاختبار، والذي يتم عرضه عند الإبلاغ عن نتائج الاختبار. افتراضي: خاصيةname
الخاصة بـfn
، أو'\<anonymous\>'
إذا لم يكن لـfn
اسم.options
<Object> خيارات تكوين للاختبار. يتم دعم الخصائص التالية:concurrency
<number> | <boolean> إذا تم توفير رقم، فسيتم تشغيل هذا العدد من الاختبارات بالتوازي داخل سلسلة عمليات التطبيق. إذا كانتtrue
، فسيتم تشغيل جميع الاختبارات غير المتزامنة المجدولة بالتوازي داخل سلسلة العمليات. إذا كانتfalse
، فسيتم تشغيل اختبار واحد فقط في كل مرة. إذا لم يتم تحديده، فستَرِث الاختبارات الفرعية هذه القيمة من أصلها. افتراضي:false
.only
<boolean> إذا كانت قيمة حقيقية، وتم تكوين سياق الاختبار لتشغيل اختباراتonly
، فسيتم تشغيل هذا الاختبار. وإلا، فسيتم تخطي الاختبار. افتراضي:false
.signal
<AbortSignal> يسمح بإحباط اختبار قيد التقدم.skip
<boolean> | <string> إذا كانت قيمة حقيقية، فسيتم تخطي الاختبار. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لتخطي الاختبار. افتراضي:false
.todo
<boolean> | <string> إذا كانت قيمة حقيقية، فسيتم تعليم الاختبار على أنهTODO
. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لكون الاختبارTODO
. افتراضي:false
.timeout
<number> عدد بالمللي ثانية سيفشل الاختبار بعده. إذا لم يتم تحديده، فستَرِث الاختبارات الفرعية هذه القيمة من أصلها. افتراضي:Infinity
.plan
<number> عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها في الاختبار. إذا كان عدد التأكيدات التي تم تشغيلها في الاختبار لا يتطابق مع الرقم المحدد في الخطة، فسيفشل الاختبار. افتراضي:undefined
.
fn
<Function> | <AsyncFunction> الدالة قيد الاختبار. الوسيطة الأولى لهذه الدالة هي كائنTestContext
. إذا كان الاختبار يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كوسيطة ثانية. افتراضي: دالة لا تقوم بأي عملية.الإرجاع: <Promise> تم تحقيقه بـ
undefined
بمجرد اكتمال الاختبار، أو على الفور إذا تم تشغيل الاختبار داخل مجموعة.
الدالة test()
هي القيمة المستوردة من الوحدة test
. يؤدي كل استدعاء لهذه الدالة إلى الإبلاغ عن الاختبار إلى <TestsStream>.
يمكن استخدام كائن TestContext
الذي تم تمريره إلى الوسيطة fn
لتنفيذ الإجراءات المتعلقة بالاختبار الحالي. تتضمن الأمثلة تخطي الاختبار أو إضافة معلومات تشخيصية إضافية أو إنشاء اختبارات فرعية.
تُرجع test()
Promise
يتم تحقيقه بمجرد اكتمال الاختبار. إذا تم استدعاء test()
داخل مجموعة، فإنه يتحقق على الفور. يمكن عادةً تجاهل القيمة المرجعة للاختبارات ذات المستوى الأعلى. ومع ذلك، يجب استخدام القيمة المرجعة من الاختبارات الفرعية لمنع الاختبار الأصل من الانتهاء أولاً وإلغاء الاختبار الفرعي كما هو موضح في المثال التالي.
test('top level test', async (t) => {
// The setTimeout() in the following subtest would cause it to outlive its
// parent test if 'await' is removed on the next line. Once the parent test
// completes, it will cancel any outstanding subtests.
await t.test('longer running subtest', async (t) => {
return new Promise((resolve, reject) => {
setTimeout(resolve, 1000);
});
});
});
يمكن استخدام الخيار timeout
لإفشال الاختبار إذا استغرق إكماله وقتًا أطول من timeout
بالمللي ثانية. ومع ذلك، فهي ليست آلية موثوقة لإلغاء الاختبارات لأن الاختبار قيد التشغيل قد يحظر سلسلة عمليات التطبيق وبالتالي يمنع الإلغاء المجدول.
test.skip([name][, options][, fn])
اختصار لتخطي اختبار، نفس test([name], { skip: true }[, fn])
.
test.todo([name][, options][, fn])
اختصار لتعليم اختبار كـ TODO
، نفس test([name], { todo: true }[, fn])
.
test.only([name][, options][, fn])
اختصار لتعليم اختبار كـ only
، نفس test([name], { only: true }[, fn])
.
describe([name][, options][, fn])
اسم مستعار لـ suite()
.
يتم استيراد الدالة describe()
من الوحدة node:test
.
describe.skip([name][, options][, fn])
اختصار لتخطي مجموعة اختبار. هذا هو نفسه describe([name], { skip: true }[, fn])
.
describe.todo([name][, options][, fn])
اختصار لتعليم مجموعة اختبار كـ TODO
. هذا هو نفسه describe([name], { todo: true }[, fn])
.
describe.only([name][, options][, fn])
أضيف في: الإصدار 19.8.0، الإصدار 18.15.0
اختصار لتعليم مجموعة اختبار كـ only
. هذا هو نفسه describe([name], { only: true }[, fn])
.
it([name][, options][, fn])
[سجل التغييرات]
الإصدار | التغييرات |
---|---|
الإصدار 19.8.0، الإصدار 18.16.0 | استدعاء it() الآن مكافئ لاستدعاء test() . |
الإصدار 18.6.0، الإصدار 16.17.0 | أضيف في: الإصدار 18.6.0، الإصدار 16.17.0 |
اسم مستعار لـ test()
.
يتم استيراد الدالة it()
من الوحدة node:test
.
it.skip([name][, options][, fn])
اختصار لتخطي اختبار، نفس it([name], { skip: true }[, fn])
.
it.todo([name][, options][, fn])
اختصار لتعليم اختبار كـ TODO
، نفس it([name], { todo: true }[, fn])
.
it.only([name][, options][, fn])
أضيف في: الإصدار 19.8.0، الإصدار 18.15.0
اختصار لتعليم اختبار كـ only
، نفس it([name], { only: true }[, fn])
.
before([fn][, options])
تمت الإضافة في: v18.8.0، v16.18.0
fn
<Function> | <AsyncFunction> دالة الربط. إذا كان الربط يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كمعامل ثاني. افتراضي: دالة لا تفعل شيئًا.options
<Object> خيارات التكوين للربط. الخصائص التالية مدعومة:signal
<AbortSignal> يسمح بإلغاء ربط قيد التقدم.timeout
<number> عدد المللي ثانية التي سيفشل بعدها الربط. إذا لم يتم تحديده، فسترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. افتراضي:Infinity
.
تقوم هذه الدالة بإنشاء ربط يتم تشغيله قبل تنفيذ مجموعة.
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
.
تقوم هذه الدالة بإنشاء ربط يتم تشغيله بعد تنفيذ مجموعة.
describe('tests', async () => {
after(() => console.log('finished running tests'));
it('is a subtest', () => {
assert.ok('some relevant assertion here');
});
});
ملاحظة: يتم ضمان تشغيل الربط after
، حتى إذا فشلت الاختبارات داخل المجموعة.
beforeEach([fn][, options])
أُضيف في: v18.8.0، v16.18.0
fn
<Function> | <AsyncFunction> دالة الخطاف (hook). إذا كان الخطاف يستخدم ردود النداء (callbacks)، يتم تمرير دالة رد النداء كمعامل ثانٍ. الافتراضي: دالة فارغة (no-op).options
<Object> خيارات التكوين للخطاف. الخصائص التالية مدعومة:signal
<AbortSignal> يسمح بإجهاض خطاف قيد التقدم.timeout
<number> عدد من المللي ثانية سيفشل الخطاف بعدها. إذا لم يتم تحديده، سترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. الافتراضي:Infinity
.
تقوم هذه الدالة بإنشاء خطاف يتم تشغيله قبل كل اختبار في المجموعة الحالية.
describe('tests', async () => {
beforeEach(() => console.log('about to run a test'));
it('is a subtest', () => {
assert.ok('some relevant assertion here');
});
});
afterEach([fn][, options])
أُضيف في: v18.8.0، v16.18.0
fn
<Function> | <AsyncFunction> دالة الخطاف (hook). إذا كان الخطاف يستخدم ردود النداء (callbacks)، يتم تمرير دالة رد النداء كمعامل ثانٍ. الافتراضي: دالة فارغة (no-op).options
<Object> خيارات التكوين للخطاف. الخصائص التالية مدعومة:signal
<AbortSignal> يسمح بإجهاض خطاف قيد التقدم.timeout
<number> عدد من المللي ثانية سيفشل الخطاف بعدها. إذا لم يتم تحديده، سترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. الافتراضي:Infinity
.
تقوم هذه الدالة بإنشاء خطاف يتم تشغيله بعد كل اختبار في المجموعة الحالية. يتم تشغيل خطاف afterEach()
حتى إذا فشل الاختبار.
describe('tests', async () => {
afterEach(() => console.log('finished running a test'));
it('is a subtest', () => {
assert.ok('some relevant assertion here');
});
});
snapshot
أُضيف في: الإصدار v22.3.0
كائن تُستخدم طرقه لتكوين إعدادات اللقطات الافتراضية في العملية الحالية. من الممكن تطبيق نفس التكوين على جميع الملفات عن طريق وضع كود التكوين الشائع في وحدة تم تحميلها مسبقًا باستخدام --require
أو --import
.
snapshot.setDefaultSnapshotSerializers(serializers)
أُضيف في: الإصدار v22.3.0
serializers
<Array> مصفوفة من الدوال المتزامنة المستخدمة كمسلسلات افتراضية لاختبارات اللقطات.
تُستخدم هذه الدالة لتخصيص آلية التسلسل الافتراضية المستخدمة من قِبل مُشغِّل الاختبار. بشكل افتراضي، يقوم مُشغِّل الاختبار بتنفيذ التسلسل عن طريق استدعاء JSON.stringify(value, null, 2)
على القيمة المُقدَّمة. JSON.stringify()
لديها قيود فيما يتعلق بالهياكل الدائرية وأنواع البيانات المدعومة. إذا كانت هناك حاجة إلى آلية تسلسل أكثر قوة، فيجب استخدام هذه الدالة.
snapshot.setResolveSnapshotPath(fn)
أُضيف في: الإصدار v22.3.0
fn
<Function> دالة تُستخدم لحساب موقع ملف اللقطة. تتلقى الدالة مسار ملف الاختبار كوسيطتها الوحيدة. إذا لم يكن الاختبار مرتبطًا بملف (على سبيل المثال في REPL)، يكون الإدخال غير مُعرَّف. يجب أن تُرجعfn()
سلسلة تحدد موقع ملف اللقطة.
تُستخدم هذه الدالة لتخصيص موقع ملف اللقطة المستخدم لاختبار اللقطات. بشكل افتراضي، يكون اسم ملف اللقطة هو نفسه اسم ملف نقطة الإدخال بامتداد ملف .snapshot
.
الفئة: MockFunctionContext
تمت الإضافة في: الإصدار v19.1.0، v18.13.0
تُستخدم الفئة MockFunctionContext
لفحص أو معالجة سلوك النماذج الوهمية التي تم إنشاؤها عبر واجهات برمجة التطبيقات MockTracker
.
ctx.calls
تمت الإضافة في: الإصدار v19.1.0، v18.13.0
دالة جلب (getter) تُرجع نسخة من المصفوفة الداخلية المستخدمة لتتبع استدعاءات النموذج الوهمي. كل إدخال في المصفوفة هو كائن له الخصائص التالية.
arguments
<Array> مصفوفة من الوسائط التي تم تمريرها إلى الدالة الوهمية.error
<any> إذا أطلقت الدالة الوهمية استثناءً، فستحتوي هذه الخاصية على القيمة التي تم إطلاقها. افتراضي:undefined
.result
<any> القيمة التي تم إرجاعها بواسطة الدالة الوهمية.stack
<Error> كائنError
يمكن استخدام مكدسه لتحديد موقع الاستدعاء لاستدعاء الدالة الوهمية.target
<Function> | <undefined> إذا كانت الدالة الوهمية هي دالة إنشاء (constructor)، فسيحتوي هذا الحقل على الفئة التي يتم إنشاؤها. بخلاف ذلك، سيكون هذاundefined
.this
<any> قيمةthis
الخاصة بالدالة الوهمية.
ctx.callCount()
تمت الإضافة في: الإصدار v19.1.0، v18.13.0
- الإرجاع: <integer> عدد المرات التي تم فيها استدعاء هذا النموذج الوهمي.
تُرجع هذه الدالة عدد المرات التي تم فيها استدعاء هذا النموذج الوهمي. هذه الدالة أكثر كفاءة من التحقق من ctx.calls.length
لأن ctx.calls
هي دالة جلب (getter) تنشئ نسخة من مصفوفة تتبع الاستدعاءات الداخلية.
ctx.mockImplementation(implementation)
أُضيف في: v19.1.0، v18.13.0
implementation
<Function> | <AsyncFunction> الدالة التي ستستخدم كتطبيق جديد للنموذج.
تُستخدم هذه الدالة لتغيير سلوك نموذج موجود.
ينشئ المثال التالي دالة نموذجية باستخدام t.mock.fn()
، ويستدعي الدالة النموذجية، ثم يغير تطبيق النموذج إلى دالة مختلفة.
test('يغير سلوك النموذج', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
cnt += 2;
return cnt;
}
const fn = t.mock.fn(addOne);
assert.strictEqual(fn(), 1);
fn.mock.mockImplementation(addTwo);
assert.strictEqual(fn(), 3);
assert.strictEqual(fn(), 5);
});
ctx.mockImplementationOnce(implementation[, onCall])
أُضيف في: v19.1.0، v18.13.0
implementation
<Function> | <AsyncFunction> الدالة التي ستستخدم كتطبيق للنموذج لرقم الاستدعاء المحدد بواسطةonCall
.onCall
<integer> رقم الاستدعاء الذي سيستخدمimplementation
. إذا حدث الاستدعاء المحدد بالفعل، فسيتم طرح استثناء. افتراضي: عدد الاستدعاء التالي.
تُستخدم هذه الدالة لتغيير سلوك نموذج موجود لاستدعاء واحد. بمجرد حدوث الاستدعاء onCall
، سيعود النموذج إلى أي سلوك كان سيستخدمه لو لم يتم استدعاء mockImplementationOnce()
.
ينشئ المثال التالي دالة نموذجية باستخدام t.mock.fn()
، ويستدعي الدالة النموذجية، ويغير تطبيق النموذج إلى دالة مختلفة للاستدعاء التالي، ثم يستأنف سلوكه السابق.
test('يغير سلوك النموذج مرة واحدة', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
cnt += 2;
return cnt;
}
const fn = t.mock.fn(addOne);
assert.strictEqual(fn(), 1);
fn.mock.mockImplementationOnce(addTwo);
assert.strictEqual(fn(), 3);
assert.strictEqual(fn(), 4);
});
ctx.resetCalls()
أُضيف في: v19.3.0، v18.13.0
يعيد ضبط سجل الاستدعاءات للدالة الوهمية.
ctx.restore()
أُضيف في: v19.1.0، v18.13.0
يعيد ضبط تنفيذ الدالة الوهمية إلى سلوكها الأصلي. لا يزال بالإمكان استخدام الوهمي بعد استدعاء هذه الدالة.
صنف: MockModuleContext
أُضيف في: v22.3.0، v20.18.0
[مستقر: 1 - تجريبي]
مستقر: 1 الاستقرار: 1.0 - تطوير مبكر
يُستخدم الصنف MockModuleContext
للتلاعب بسلوك وحدات النماذج الوهمية التي تم إنشاؤها عبر واجهات برمجة التطبيقات MockTracker
.
ctx.restore()
أُضيف في: v22.3.0، v20.18.0
يعيد ضبط تنفيذ الوحدة الوهمية.
صنف: MockTracker
أُضيف في: v19.1.0، v18.13.0
يُستخدم الصنف MockTracker
لإدارة وظائف المحاكاة الوهمية. توفر وحدة تشغيل الاختبار تصديرًا عالي المستوى mock
وهو مثيل MockTracker
. يوفر كل اختبار أيضًا مثيل MockTracker
الخاص به عبر خاصية mock
الخاصة بسياق الاختبار.
mock.fn([original[, implementation]][, options])
أُضيف في: v19.1.0، v18.13.0
original
<Function> | <AsyncFunction> دالة اختيارية لإنشاء وهمي عليها. افتراضي: دالة لا تفعل شيئًا.implementation
<Function> | <AsyncFunction> دالة اختيارية تُستخدم كتنفيذ وهمي لـoriginal
. هذا مفيد لإنشاء نماذج وهمية تعرض سلوكًا واحدًا لعدد محدد من الاستدعاءات ثم استعادة سلوكoriginal
. افتراضي: الدالة المحددة بواسطةoriginal
.options
<Object> خيارات التكوين الاختيارية للدالة الوهمية. الخصائص التالية مدعومة:times
<integer> عدد المرات التي سيستخدم فيها الوهمي سلوكimplementation
. بمجرد استدعاء الدالة الوهميةtimes
مرات، ستستعيد تلقائيًا سلوكoriginal
. يجب أن تكون هذه القيمة عددًا صحيحًا أكبر من الصفر. افتراضي:Infinity
.
إرجاع: <Proxy> الدالة الوهمية. تحتوي الدالة الوهمية على خاصية
mock
خاصة، وهي مثيل لـMockFunctionContext
، ويمكن استخدامها لفحص وتغيير سلوك الدالة الوهمية.
تُستخدم هذه الدالة لإنشاء دالة وهمية.
يقوم المثال التالي بإنشاء دالة وهمية تزيد العداد بمقدار واحد في كل استدعاء. يُستخدم الخيار times
لتعديل السلوك الوهمي بحيث يضيف أول استدعيين اثنين إلى العداد بدلاً من واحد.
test('mocks a counting function', (t) => {
let cnt = 0;
function addOne() {
cnt++;
return cnt;
}
function addTwo() {
cnt += 2;
return cnt;
}
const fn = t.mock.fn(addOne, addTwo, { times: 2 });
assert.strictEqual(fn(), 2);
assert.strictEqual(fn(), 4);
assert.strictEqual(fn(), 5);
assert.strictEqual(fn(), 6);
});
mock.getter(object, methodName[, implementation][, options])
تمت الإضافة في: الإصدار v19.3.0, v18.13.0
هذه الوظيفة هي عبارة عن تسهيل نحوي لـ MockTracker.method
مع تعيين options.getter
على true
.
mock.method(object, methodName[, implementation][, options])
تمت الإضافة في: الإصدار v19.1.0, v18.13.0
object
<Object> الكائن الذي يتم محاكاة طريقته.methodName
<string> | <symbol> مُعرّف الطريقة الموجودة علىobject
المراد محاكاتها. إذا لم يكنobject[methodName]
دالة، فسيتم طرح خطأ.implementation
<Function> | <AsyncFunction> دالة اختيارية تُستخدم كتطبيق وهمي لـobject[methodName]
. الافتراضي: الطريقة الأصلية المحددة بواسطةobject[methodName]
.options
<Object> خيارات تكوين اختيارية للطريقة الوهمية. الخصائص التالية مدعومة:getter
<boolean> إذا كانتtrue
، فسيتم التعامل معobject[methodName]
على أنها مُجلب. لا يمكن استخدام هذا الخيار مع خيارsetter
. الافتراضي: false.setter
<boolean> إذا كانتtrue
، فسيتم التعامل معobject[methodName]
على أنها مُعدِّل. لا يمكن استخدام هذا الخيار مع خيارgetter
. الافتراضي: false.times
<integer> عدد المرات التي سيستخدم فيها النموذج الوهمي سلوكimplementation
. بمجرد استدعاء الطريقة الوهميةtimes
مرة، سيتم استعادة السلوك الأصلي تلقائيًا. يجب أن تكون هذه القيمة عددًا صحيحًا أكبر من صفر. الافتراضي:Infinity
.
Returns: <Proxy> الطريقة الوهمية. تحتوي الطريقة الوهمية على خاصية
mock
خاصة، وهي عبارة عن نسخة منMockFunctionContext
، ويمكن استخدامها لفحص وتغيير سلوك الطريقة الوهمية.
تُستخدم هذه الوظيفة لإنشاء نموذج وهمي لطريقة كائن موجودة. يوضح المثال التالي كيفية إنشاء نموذج وهمي لطريقة كائن موجودة.
test('تجسس على طريقة كائن', (t) => {
const number = {
value: 5,
subtract(a) {
return this.value - a;
},
};
t.mock.method(number, 'subtract');
assert.strictEqual(number.subtract.mock.callCount(), 0);
assert.strictEqual(number.subtract(3), 2);
assert.strictEqual(number.subtract.mock.callCount(), 1);
const call = number.subtract.mock.calls[0];
assert.deepStrictEqual(call.arguments, [3]);
assert.strictEqual(call.result, 2);
assert.strictEqual(call.error, undefined);
assert.strictEqual(call.target, undefined);
assert.strictEqual(call.this, number);
});
mock.module(specifier[, options])
تمت الإضافة في: v22.3.0, v20.18.0
[مستقر: 1 - تجريبي]
مستقر: 1 الاستقرار: 1.0 - تطوير مبكر
specifier
<string> | <URL> سلسلة تعريف الوحدة النمطية المراد محاكاتها.options
<Object> خيارات تكوين اختيارية لوحدة المحاكاة. الخصائص التالية مدعومة:cache
<boolean> إذا كانتfalse
، فإن كل استدعاء لـrequire()
أوimport()
سيولد وحدة محاكاة جديدة. إذا كانتtrue
، فإن الاستدعاءات اللاحقة ستعيد نفس وحدة المحاكاة، وسيتم إدراج وحدة المحاكاة في ذاكرة التخزين المؤقت لـ CommonJS. الافتراضي: false.defaultExport
<any> قيمة اختيارية تستخدم كتصدير افتراضي لوحدة المحاكاة. إذا لم يتم توفير هذه القيمة، فلن تتضمن محاكاة ESM تصديرًا افتراضيًا. إذا كانت المحاكاة عبارة عن وحدة CommonJS أو وحدة مدمجة، فسيتم استخدام هذا الإعداد كقيمة لـmodule.exports
. إذا لم يتم توفير هذه القيمة، فستستخدم محاكاة CJS والوحدات المدمجة كائنًا فارغًا كقيمة لـmodule.exports
.namedExports
<Object> كائن اختياري تُستخدم مفاتيحه وقيمه لإنشاء الصادرات المسماة لوحدة المحاكاة. إذا كانت المحاكاة عبارة عن وحدة CommonJS أو وحدة مدمجة، فسيتم نسخ هذه القيم علىmodule.exports
. لذلك، إذا تم إنشاء محاكاة مع كل من الصادرات المسماة والتصدير الافتراضي غير الكائني، فستقوم المحاكاة بإلقاء استثناء عند استخدامها كوحدة CJS أو وحدة مدمجة.
الإرجاع: <MockModuleContext> كائن يمكن استخدامه لمعالجة المحاكاة.
تُستخدم هذه الدالة لمحاكاة صادرات وحدات ECMAScript ووحدات CommonJS ووحدات Node.js المدمجة. لا تتأثر أي مراجع إلى الوحدة الأصلية قبل المحاكاة. لتمكين محاكاة الوحدة، يجب بدء Node.js بعلامة سطر الأوامر --experimental-test-module-mocks
.
يوضح المثال التالي كيف يتم إنشاء محاكاة لوحدة نمطية.
test('mocks a builtin module in both module systems', async (t) => {
// Create a mock of 'node:readline' with a named export named 'fn', which
// does not exist in the original 'node:readline' module.
const mock = t.mock.module('node:readline', {
namedExports: { fn() { return 42; } },
});
let esmImpl = await import('node:readline');
let cjsImpl = require('node:readline');
// cursorTo() is an export of the original 'node:readline' module.
assert.strictEqual(esmImpl.cursorTo, undefined);
assert.strictEqual(cjsImpl.cursorTo, undefined);
assert.strictEqual(esmImpl.fn(), 42);
assert.strictEqual(cjsImpl.fn(), 42);
mock.restore();
// The mock is restored, so the original builtin module is returned.
esmImpl = await import('node:readline');
cjsImpl = require('node:readline');
assert.strictEqual(typeof esmImpl.cursorTo, 'function');
assert.strictEqual(typeof cjsImpl.cursorTo, 'function');
assert.strictEqual(esmImpl.fn, undefined);
assert.strictEqual(cjsImpl.fn, undefined);
});
mock.reset()
تمت إضافته في: الإصدار v19.1.0، v18.13.0
تقوم هذه الدالة باستعادة السلوك الافتراضي لجميع النماذج الوهمية التي تم إنشاؤها مسبقًا بواسطة MockTracker
هذه وفصل النماذج الوهمية عن نسخة MockTracker
. بمجرد الفصل، لا يزال من الممكن استخدام النماذج الوهمية، ولكن لا يمكن استخدام نسخة MockTracker
بعد الآن لإعادة تعيين سلوكها أو التفاعل معها بأي طريقة أخرى.
بعد اكتمال كل اختبار، يتم استدعاء هذه الدالة على MockTracker
الخاص بسياق الاختبار. إذا تم استخدام MockTracker
العام على نطاق واسع، فمن المستحسن استدعاء هذه الدالة يدويًا.
mock.restoreAll()
تمت إضافته في: الإصدار v19.1.0، v18.13.0
تقوم هذه الدالة باستعادة السلوك الافتراضي لجميع النماذج الوهمية التي تم إنشاؤها مسبقًا بواسطة MockTracker
هذه. على عكس mock.reset()
، لا تفصل mock.restoreAll()
النماذج الوهمية عن نسخة MockTracker
.
mock.setter(object, methodName[, implementation][, options])
تمت إضافته في: الإصدار v19.3.0، v18.13.0
هذه الدالة عبارة عن تسهيل في الكتابة لـ MockTracker.method
مع تعيين options.setter
إلى true
.
فئة: MockTimers
[سجل التغييرات]
الإصدار | التغييرات |
---|---|
v23.1.0 | أصبح Mock Timers الآن مستقرًا. |
v20.4.0, v18.19.0 | تمت إضافته في: الإصدار v20.4.0، v18.19.0 |
[مستقر: 2 - مستقر]
مستقر: 2 الاستقرار: 2 - مستقر
إنشاء نماذج وهمية للمؤقتات هو أسلوب شائع الاستخدام في اختبار البرامج لمحاكاة والتحكم في سلوك المؤقتات، مثل setInterval
و setTimeout
، دون الانتظار فعليًا للفترات الزمنية المحددة.
MockTimers قادر أيضًا على إنشاء نموذج وهمي لكائن Date
.
يوفر MockTracker
تصدير timers
عالي المستوى وهو عبارة عن نسخة MockTimers
.
timers.enable([enableOptions])
[سجل التغييرات]
الإصدار | التغييرات |
---|---|
v21.2.0, v20.11.0 | تم تحديث المعلمات لتكون كائن خيارات مع واجهات برمجة تطبيقات متاحة والعصر الأولي الافتراضي. |
v20.4.0, v18.19.0 | تمت إضافته في: الإصدار v20.4.0، v18.19.0 |
يقوم بتمكين إنشاء نموذج وهمي للمؤقتات للمؤقتات المحددة.
-
enableOptions
<Object> خيارات تكوين اختيارية لتمكين إنشاء نموذج وهمي للمؤقت. يتم دعم الخصائص التالية:-
apis
<Array> مصفوفة اختيارية تحتوي على المؤقتات المراد إنشاء نموذج وهمي لها. قيم المؤقت المدعومة حاليًا هيsetInterval
وsetTimeout
وsetImmediate
وDate
. افتراضي:['setInterval', 'setTimeout', 'setImmediate', 'Date']
. إذا لم يتم توفير مصفوفة، فسيتم إنشاء نموذج وهمي لجميع واجهات برمجة التطبيقات المتعلقة بالوقت ('setInterval'
و'clearInterval'
و'setTimeout'
و'clearTimeout'
و'setImmediate'
و'clearImmediate'
و'Date'
) بشكل افتراضي. -
now
<number> | <Date> رقم اختياري أو كائن Date يمثل الوقت الأولي (بالمللي ثانية) لاستخدامه كقيمة لـDate.now()
. افتراضي: 0
.
-
ملاحظة: عند تمكين إنشاء نموذج وهمي لمؤقت معين، سيتم أيضًا إنشاء نموذج وهمي ضمني لوظيفة المسح المرتبطة به.
ملاحظة: سيؤثر إنشاء نموذج وهمي لـ Date
على سلوك المؤقتات الوهمية لأنها تستخدم نفس الساعة الداخلية.
مثال على الاستخدام بدون تعيين الوقت الأولي:
import { mock } from 'node:test';
mock.timers.enable({ apis: ['setInterval'] });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['setInterval'] });
يمكّن المثال أعلاه إنشاء نموذج وهمي للمؤقت setInterval
وينشئ نموذجًا وهميًا ضمنيًا للدالة clearInterval
. سيتم إنشاء نموذج وهمي فقط للدوال setInterval
و clearInterval
من node:timers و node:timers/promises و globalThis
.
مثال على الاستخدام مع تعيين الوقت الأولي
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: 1000 });
const { mock } = require('node:test');
mock.timers.enable({ apis: ['Date'], now: 1000 });
مثال على الاستخدام مع كائن Date أولي كوقت تم تعيينه
import { mock } from 'node:test';
mock.timers.enable({ apis: ['Date'], now: new Date() });
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
لسياق الاختبار.
import { mock } from 'node:test';
mock.timers.reset();
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
يتقدم في الوقت مما يؤدي إلى تشغيل جميع المؤقتات المعلقة.
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);
});
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
عدة مرات
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);
});
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
أيضًا على أن يكون وهميًا).
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);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
const fn = context.mock.fn();
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
setTimeout(fn, 9999);
assert.strictEqual(fn.mock.callCount(), 0);
assert.strictEqual(Date.now(), 0);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(fn.mock.callCount(), 1);
assert.strictEqual(Date.now(), 9999);
});
استخدام دوال clear
كما ذكرنا، يتم عمل محاكاة ضمنية لجميع دوال clear
من المؤقتات (clearTimeout
و clearInterval
و clearImmediate
). ألق نظرة على هذا المثال باستخدام setTimeout
:
import assert from 'node:assert';
import { test } from 'node:test';
test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
const fn = context.mock.fn();
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout'] });
const id = setTimeout(fn, 9999);
// Implicitly mocked as well
clearTimeout(id);
context.mock.timers.tick(9999);
// As that setTimeout was cleared the mock function will never be called
assert.strictEqual(fn.mock.callCount(), 0);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('mocks setTimeout to be executed synchronously without having to actually wait for it', (context) => {
const fn = context.mock.fn();
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout'] });
const id = setTimeout(fn, 9999);
// Implicitly mocked as well
clearTimeout(id);
context.mock.timers.tick(9999);
// As that setTimeout was cleared the mock function will never be called
assert.strictEqual(fn.mock.callCount(), 0);
});
العمل مع وحدات مؤقتات Node.js
بمجرد تمكين محاكاة المؤقتات، يتم تمكين وحدات node:timers و node:timers/promises، والمؤقتات من سياق Node.js العالمي:
ملاحظة: تجريد الدوال مثل import { setTimeout } from 'node:timers'
غير مدعوم حاليًا بواسطة واجهة برمجة التطبيقات هذه.
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimers from 'node:timers';
import nodeTimersPromises from 'node:timers/promises';
test('mocks setTimeout to be executed synchronously without having to actually wait for it', async (context) => {
const globalTimeoutObjectSpy = context.mock.fn();
const nodeTimerSpy = context.mock.fn();
const nodeTimerPromiseSpy = context.mock.fn();
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(globalTimeoutObjectSpy, 9999);
nodeTimers.setTimeout(nodeTimerSpy, 9999);
const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1);
assert.strictEqual(nodeTimerSpy.mock.callCount(), 1);
await promise;
assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1);
});
const assert = require('node:assert');
const { test } = require('node:test');
const nodeTimers = require('node:timers');
const nodeTimersPromises = require('node:timers/promises');
test('mocks setTimeout to be executed synchronously without having to actually wait for it', async (context) => {
const globalTimeoutObjectSpy = context.mock.fn();
const nodeTimerSpy = context.mock.fn();
const nodeTimerPromiseSpy = context.mock.fn();
// Optionally choose what to mock
context.mock.timers.enable({ apis: ['setTimeout'] });
setTimeout(globalTimeoutObjectSpy, 9999);
nodeTimers.setTimeout(nodeTimerSpy, 9999);
const promise = nodeTimersPromises.setTimeout(9999).then(nodeTimerPromiseSpy);
// Advance in time
context.mock.timers.tick(9999);
assert.strictEqual(globalTimeoutObjectSpy.mock.callCount(), 1);
assert.strictEqual(nodeTimerSpy.mock.callCount(), 1);
await promise;
assert.strictEqual(nodeTimerPromiseSpy.mock.callCount(), 1);
});
في Node.js، setInterval
من node:timers/promises هو AsyncGenerator
وهو مدعوم أيضًا بواسطة واجهة برمجة التطبيقات هذه:
import assert from 'node:assert';
import { test } from 'node:test';
import nodeTimersPromises from 'node:timers/promises';
test('should tick five times testing a real use case', async (context) => {
context.mock.timers.enable({ apis: ['setInterval'] });
const expectedIterations = 3;
const interval = 1000;
const startedAt = Date.now();
async function run() {
const times = [];
for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
times.push(time);
if (times.length === expectedIterations) break;
}
return times;
}
const r = run();
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
const timeResults = await r;
assert.strictEqual(timeResults.length, expectedIterations);
for (let it = 1; it < expectedIterations; it++) {
assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
}
});
const assert = require('node:assert');
const { test } = require('node:test');
const nodeTimersPromises = require('node:timers/promises');
test('should tick five times testing a real use case', async (context) => {
context.mock.timers.enable({ apis: ['setInterval'] });
const expectedIterations = 3;
const interval = 1000;
const startedAt = Date.now();
async function run() {
const times = [];
for await (const time of nodeTimersPromises.setInterval(interval, startedAt)) {
times.push(time);
if (times.length === expectedIterations) break;
}
return times;
}
const r = run();
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
context.mock.timers.tick(interval);
const timeResults = await r;
assert.strictEqual(timeResults.length, expectedIterations);
for (let it = 1; it < expectedIterations; it++) {
assert.strictEqual(timeResults[it - 1], startedAt + (interval * it));
}
});
timers.runAll()
تمت إضافتها في: v20.4.0, v18.19.0
يقوم بتشغيل جميع المؤقتات المحاكاة المعلقة على الفور. إذا تم أيضًا محاكاة كائن Date
، فسيتم أيضًا تقديم كائن Date
إلى أبعد وقت للمؤقت.
يوضح المثال أدناه تشغيل جميع المؤقتات المعلقة على الفور، مما يؤدي إلى تنفيذها دون أي تأخير.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
// Notice that if both timers have the same timeout,
// the order of execution is guaranteed
setTimeout(() => results.push(3), 8888);
setTimeout(() => results.push(2), 8888);
assert.deepStrictEqual(results, []);
context.mock.timers.runAll();
assert.deepStrictEqual(results, [3, 2, 1]);
// The Date object is also advanced to the furthest timer's time
assert.strictEqual(Date.now(), 9999);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('runAll functions following the given order', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
// Notice that if both timers have the same timeout,
// the order of execution is guaranteed
setTimeout(() => results.push(3), 8888);
setTimeout(() => results.push(2), 8888);
assert.deepStrictEqual(results, []);
context.mock.timers.runAll();
assert.deepStrictEqual(results, [3, 2, 1]);
// The Date object is also advanced to the furthest timer's time
assert.strictEqual(Date.now(), 9999);
});
ملاحظة: تم تصميم وظيفة runAll()
خصيصًا لتشغيل المؤقتات في سياق محاكاة المؤقت. ليس لها أي تأثير على ساعات النظام في الوقت الفعلي أو المؤقتات الفعلية خارج بيئة المحاكاة.
timers.setTime(milliseconds)
تمت إضافتها في: v21.2.0, v20.11.0
يضبط الطابع الزمني الحالي لنظام Unix الذي سيتم استخدامه كمرجع لأي كائنات Date
محاكاة.
import assert from 'node:assert';
import { test } from 'node:test';
test('runAll functions following the given order', (context) => {
const now = Date.now();
const setTime = 1000;
// Date.now is not mocked
assert.deepStrictEqual(Date.now(), now);
context.mock.timers.enable({ apis: ['Date'] });
context.mock.timers.setTime(setTime);
// Date.now is now 1000
assert.strictEqual(Date.now(), setTime);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('setTime replaces current time', (context) => {
const now = Date.now();
const setTime = 1000;
// Date.now is not mocked
assert.deepStrictEqual(Date.now(), now);
context.mock.timers.enable({ apis: ['Date'] });
context.mock.timers.setTime(setTime);
// Date.now is now 1000
assert.strictEqual(Date.now(), setTime);
});
التواريخ والمؤقتات تعمل معًا
تعتمد كائنات التاريخ والمؤقت على بعضها البعض. إذا كنت تستخدم setTime()
لتمرير الوقت الحالي إلى كائن Date
الوهمي، فلن تتأثر المؤقتات المعينة باستخدام setTimeout
و setInterval
.
ومع ذلك، فإن طريقة tick
ستقوم بتقديم كائن Date
الوهمي.
import assert from 'node:assert';
import { test } from 'node:test';
test('تشغيل جميع الوظائف بالترتيب المحدد', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
assert.deepStrictEqual(results, []);
context.mock.timers.setTime(12000);
assert.deepStrictEqual(results, []);
// يتم تقديم التاريخ ولكن المؤقتات لا تعمل
assert.strictEqual(Date.now(), 12000);
});
const assert = require('node:assert');
const { test } = require('node:test');
test('تشغيل جميع الوظائف بالترتيب المحدد', (context) => {
context.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
const results = [];
setTimeout(() => results.push(1), 9999);
assert.deepStrictEqual(results, []);
context.mock.timers.setTime(12000);
assert.deepStrictEqual(results, []);
// يتم تقديم التاريخ ولكن المؤقتات لا تعمل
assert.strictEqual(Date.now(), 12000);
});
صنف: TestsStream
[تاريخ]
الإصدار | التغييرات |
---|---|
v20.0.0, v19.9.0, v18.17.0 | تمت إضافة النوع إلى أحداث test:pass و test:fail عندما يكون الاختبار مجموعة. |
v18.9.0, v16.19.0 | تمت الإضافة في: v18.9.0, v16.19.0 |
- يمتد <Readable>
ستؤدي المكالمة الناجحة لطريقة 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'
يتم إصداره عندما يكتب اختبار قيد التشغيل إلى stderr
. يتم إصدار هذا الحدث فقط إذا تم تمرير العلامة --test
. لا يتم ضمان إصدار هذا الحدث بنفس الترتيب الذي يتم به تعريف الاختبارات.
الحدث: 'test: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
.
تُستخدم هذه الدالة لإنشاء أداة ربط تعمل قبل كل اختبار فرعي للاختبار الحالي.
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
.
تُستخدم هذه الدالة لإنشاء خطاف يعمل بعد انتهاء الاختبار الحالي.
test('اختبار المستوى الأعلى', async (t) => {
t.after((t) => t.diagnostic(`تم الانتهاء من تشغيل ${t.name}`));
assert.ok('بعض التأكيدات ذات الصلة هنا');
});
context.afterEach([fn][, options])
أُضيف في: v18.8.0, v16.18.0
fn
<Function> | <AsyncFunction> دالة الخطاف. الوسيط الأول لهذه الدالة هو كائنTestContext
. إذا كان الخطاف يستخدم ردود النداء، فسيتم تمرير دالة رد النداء كوسيط ثانٍ. افتراضي: دالة لا تفعل شيئًا.options
<Object> خيارات تكوين الخطاف. الخصائص التالية مدعومة:signal
<AbortSignal> يسمح بإلغاء خطاف قيد التقدم.timeout
<number> عدد المللي ثانية التي سيفشل بعدها الخطاف. إذا لم يتم تحديده، فسوف ترث الاختبارات الفرعية هذه القيمة من الأصل الخاص بها. افتراضي:Infinity
.
تُستخدم هذه الدالة لإنشاء خطاف يعمل بعد كل اختبار فرعي للاختبار الحالي.
test('اختبار المستوى الأعلى', async (t) => {
t.afterEach((t) => t.diagnostic(`تم الانتهاء من تشغيل ${t.name}`));
await t.test(
'هذا اختبار فرعي',
(t) => {
assert.ok('بعض التأكيدات ذات الصلة هنا');
},
);
});
context.assert
تمت الإضافة في: v22.2.0, v20.15.0
كائن يحتوي على أساليب التأكيد المرتبطة بـ context
. يتم عرض الدوال ذات المستوى الأعلى من وحدة node:assert
هنا لغرض إنشاء خطط الاختبار.
test('test', (t) => {
t.plan(1);
t.assert.strictEqual(true, true);
});
context.assert.snapshot(value[, options])
تمت الإضافة في: v22.3.0
[مستقر: 1 - تجريبي]
مستقر: 1 الاستقرار: 1.0 - تطوير مبكر
value
<any> قيمة يتم تسلسلها إلى سلسلة. إذا تم بدء Node.js باستخدام العلامة--test-update-snapshots
، فستتم كتابة القيمة المسلسلة في ملف اللقطة. وإلا، تتم مقارنة القيمة المسلسلة بالقيمة المقابلة في ملف اللقطة الموجود.options
<Object> خيارات التكوين الاختيارية. الخصائص التالية مدعومة:serializers
<Array> مصفوفة من الدوال المتزامنة المستخدمة لتسلسلvalue
إلى سلسلة. يتم تمريرvalue
كوسيطة وحيدة إلى دالة التسلسل الأولى. يتم تمرير القيمة المرجعة لكل مسلسِل كمدخل للمسلسِل التالي. بمجرد تشغيل جميع المسلسلات، يتم إجبار القيمة الناتجة على سلسلة. الافتراضي: إذا لم يتم توفير أي مسلسلات، فسيتم استخدام المسلسلات الافتراضية لتشغيل الاختبار.
تنفذ هذه الدالة تأكيدات لاختبار اللقطات.
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> الرسالة التي سيتم الإبلاغ عنها.
تُستخدم هذه الدالة لكتابة التشخيصات في الإخراج. يتم تضمين أي معلومات تشخيصية في نهاية نتائج الاختبار. لا تُرجع هذه الدالة قيمة.
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> عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها.
تُستخدم هذه الدالة لتعيين عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها داخل الاختبار. إذا كان عدد التأكيدات والاختبارات الفرعية التي يتم تشغيلها لا يتطابق مع العدد المتوقع، فسيفشل الاختبار.
test('top level test', (t) => {
t.plan(2);
t.assert.ok('some relevant assertion here');
t.test('subtest', () => {});
});
عند العمل مع التعليمات البرمجية غير المتزامنة، يمكن استخدام دالة plan
للتأكد من تشغيل العدد الصحيح من التأكيدات:
test('planning with streams', (t, done) => {
function* generate() {
yield 'a';
yield 'b';
yield 'c';
}
const expected = ['a', 'b', 'c'];
t.plan(expected.length);
const stream = Readable.from(generate());
stream.on('data', (chunk) => {
t.assert.strictEqual(chunk, expected.shift());
});
stream.on('end', () => {
done();
});
});
context.runOnly(shouldRunOnlyTests)
تمت الإضافة في: الإصدار 18.0.0، الإصدار 16.17.0
-
shouldRunOnlyTests
<boolean> سواء كان سيتم تشغيل اختباراتonly
أم لا.
إذا كانت قيمة shouldRunOnlyTests
صالحة، فسياق الاختبار سيشغل فقط الاختبارات التي تم تعيين خيار only
لها. بخلاف ذلك، يتم تشغيل جميع الاختبارات. إذا لم يتم بدء Node.js باستخدام خيار سطر الأوامر --test-only
، فإن هذه الوظيفة لا تفعل شيئًا.
test('اختبار المستوى الأعلى', (t) => {
// يمكن ضبط سياق الاختبار لتشغيل الاختبارات الفرعية بخيار 'only'.
t.runOnly(true);
return Promise.all([
t.test('هذا الاختبار الفرعي يتم تخطيه الآن'),
t.test('يتم تشغيل هذا الاختبار الفرعي', { only: true }),
]);
});
context.signal
تمت الإضافة في: الإصدار 18.7.0، الإصدار 16.17.0
- النوع: <AbortSignal>
يمكن استخدامه لإلغاء مهام الاختبار الفرعية عندما يتم إلغاء الاختبار.
test('اختبار المستوى الأعلى', async (t) => {
await fetch('some/uri', { signal: t.signal });
});
context.skip([message])
تمت الإضافة في: الإصدار 18.0.0، الإصدار 16.17.0
-
message
<string> رسالة تخطي اختيارية.
تتسبب هذه الوظيفة في إشارة مخرجات الاختبار إلى الاختبار على أنه تم تخطيه. إذا تم توفير message
، فسيتم تضمينها في المخرجات. استدعاء skip()
لا ينهي تنفيذ وظيفة الاختبار. لا تُرجع هذه الوظيفة قيمة.
test('اختبار المستوى الأعلى', (t) => {
// تأكد من الإرجاع هنا أيضًا إذا كان الاختبار يحتوي على منطق إضافي.
t.skip('تم تخطي هذا');
});
context.todo([message])
تمت الإضافة في: الإصدار 18.0.0، الإصدار 16.17.0
-
message
<string> رسالةTODO
اختيارية.
تضيف هذه الوظيفة توجيه TODO
إلى مخرجات الاختبار. إذا تم توفير message
، فسيتم تضمينها في المخرجات. استدعاء todo()
لا ينهي تنفيذ وظيفة الاختبار. لا تُرجع هذه الوظيفة قيمة.
test('اختبار المستوى الأعلى', (t) => {
// تم وضع علامة `TODO` على هذا الاختبار
t.todo('هذا عنصر يجب تنفيذه لاحقًا');
});
context.test([name][, options][, fn])
[السجل]
الإصدار | التغييرات |
---|---|
v18.8.0, v16.18.0 | إضافة خيار signal . |
v18.7.0, v16.17.0 | إضافة خيار timeout . |
v18.0.0, v16.17.0 | أُضيف في: v18.0.0, v16.17.0 |
name
<string> اسم الاختبار الفرعي، والذي يتم عرضه عند الإبلاغ عن نتائج الاختبار. الافتراضي: الخاصيةname
لـfn
، أو'\<anonymous\>'
إذا لم يكن لـfn
اسم.options
<Object> خيارات التهيئة للاختبار الفرعي. الخصائص التالية مدعومة:concurrency
<number> | <boolean> | <null> إذا تم توفير رقم، فسيتم تشغيل هذا العدد من الاختبارات بالتوازي داخل مؤشر ترابط التطبيق. إذا كانتtrue
، فسيتم تشغيل جميع الاختبارات الفرعية بالتوازي. إذا كانتfalse
، فسيتم تشغيل اختبار واحد فقط في كل مرة. إذا لم يتم تحديدها، فسوف ترث الاختبارات الفرعية هذه القيمة من أصلها. الافتراضي:null
.only
<boolean> إذا كانت صحيحة، وتم تكوين سياق الاختبار لتشغيل اختباراتonly
، فسيتم تشغيل هذا الاختبار. بخلاف ذلك، يتم تخطي الاختبار. الافتراضي:false
.signal
<AbortSignal> يسمح بإلغاء اختبار قيد التقدم.skip
<boolean> | <string> إذا كانت صحيحة، يتم تخطي الاختبار. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لتخطي الاختبار. الافتراضي:false
.todo
<boolean> | <string> إذا كانت صحيحة، يتم وضع علامة على الاختبار كـTODO
. إذا تم توفير سلسلة، فسيتم عرض هذه السلسلة في نتائج الاختبار كسبب لكون الاختبارTODO
. الافتراضي:false
.timeout
<number> عدد بالميلي ثانية سيفشل الاختبار بعده. إذا لم يتم تحديدها، فسوف ترث الاختبارات الفرعية هذه القيمة من أصلها. الافتراضي:Infinity
.plan
<number> عدد التأكيدات والاختبارات الفرعية المتوقع تشغيلها في الاختبار. إذا كان عدد التأكيدات التي تم تشغيلها في الاختبار لا يتطابق مع الرقم المحدد في الخطة، فسيفشل الاختبار. الافتراضي:undefined
.
fn
<Function> | <AsyncFunction> الدالة قيد الاختبار. الوسيطة الأولى لهذه الدالة هي كائنTestContext
. إذا كان الاختبار يستخدم ردود الاتصال، فسيتم تمرير دالة رد الاتصال كوسيطة ثانية. الافتراضي: دالة لا تفعل شيئًا.Returns: <Promise> مُحقق بـ
undefined
بمجرد اكتمال الاختبار.
تُستخدم هذه الدالة لإنشاء اختبارات فرعية ضمن الاختبار الحالي. تتصرف هذه الدالة بنفس طريقة دالة test()
ذات المستوى الأعلى.
test('اختبار المستوى الأعلى', async (t) => {
await t.test(
'هذا اختبار فرعي',
{ only: false, skip: false, concurrency: 1, todo: false, plan: 1 },
(t) => {
t.assert.ok('بعض التأكيدات ذات الصلة هنا');
},
);
});
الفئة: SuiteContext
تمت الإضافة في: v18.7.0, v16.17.0
يتم تمرير نسخة من SuiteContext
إلى كل دالة مجموعة اختبار للتفاعل مع مُشغِّل الاختبارات. ومع ذلك، فإن مُنشئ SuiteContext
غير معروض كجزء من واجهة برمجة التطبيقات (API).
context.filePath
تمت الإضافة في: v22.6.0
المسار المطلق لملف الاختبار الذي أنشأ المجموعة الحالية. إذا استورد ملف اختبار وحدات نمطية إضافية تُنشئ مجموعات اختبار، فستُعيد المجموعات المستوردة مسار ملف الاختبار الجذر.
context.name
تمت الإضافة في: v18.8.0, v16.18.0
اسم المجموعة.
context.signal
تمت الإضافة في: v18.7.0, v16.17.0
- النوع: <AbortSignal>
يمكن استخدامه لإلغاء مهام الاختبار الفرعية عند إلغاء الاختبار.