راهنمای جامع Test Runner در Node.js (ماژول node:test)

ماژول node:test یک فریم‌ورک تست داخلی و مدرن در Node.js است که بدون نیاز به هیچ وابستگی خارجی، امکاناتی مانند تست‌های همگام و ناهمگام، تست‌های Promise و Callback، زیرتست‌ها، هوک‌ها، Mocking، Snapshot، پوشش کد، حالت Watch و گزارشگرهای سفارشی را ارائه می‌دهد. این ماژول پایدار، قدرتمند و مناسب پروژه‌های مدرن Node.js است.

node:testTestContext (t)SubtestsHooksMockingSnapshot testingCoverageWatch modeCustom reporters

~3 دقیقه مطالعه • بروزرسانی ۹ دی ۱۴۰۴

1. نحوهٔ وارد کردن ماژول


const test = require('node:test');
// یا ESM
import test from 'node:test';

2. انواع تست‌های پایه


ماژول node:test از تمام سبک‌های رایج تست پشتیبانی می‌کند:


2.1 تست‌های همگام


test('تست همگام موفق', (t) => {
  assert.strictEqual(1, 1);
});

test('تست همگام ناموفق', (t) => {
  assert.strictEqual(1, 2);
});

2.2 تست‌های Async و Promise


test('تست async موفق', async (t) => {
  assert.strictEqual(1, 1);
});

test('تست async ناموفق', async (t) => {
  throw new Error('failed');
});

test('تست Promise ناموفق', (t) => {
  return Promise.reject(new Error('failed'));
});

2.3 تست‌های Callback


test('تست callback موفق', (t, done) => {
  setImmediate(done);
});

test('تست callback ناموفق', (t, done) => {
  setImmediate(() => done(new Error('failed')));
});

اگر هر تستی شکست بخورد، Node.js با کد خروج 1 خارج می‌شود.


3. زیرتست‌ها (Subtests)


test('تست سطح بالا', async (t) => {
  await t.test('زیرتست ۱', (t) => {
    assert.strictEqual(1, 1);
  });

  await t.test('زیرتست ۲', (t) => {
    assert.strictEqual(2, 2);
  });
});

4. تست‌های Skip و TODO


test('تست Skip شده', { skip: true }, (t) => {});

test('Skip با دلیل', { skip: 'reason' }, (t) => {});

test('تست TODO', { todo: true }, (t) => {
  throw new Error('ignored failure');
});

// داخل تست:
t.skip('skip inside');
t.todo('todo inside');

5. تست‌های Only


test('فقط این تست اجرا می‌شود', { only: true }, (t) => {});

اجرای فقط تست‌های only:


node --test-only

6. هوک‌ها (Hooks)


test('با هوک‌ها', async (t) => {
  t.before(() => console.log('قبل از همه'));
  t.beforeEach(() => console.log('قبل از هر تست'));
  t.afterEach(() => console.log('بعد از هر تست'));
  t.after(() => console.log('بعد از همه'));

  await t.test('زیرتست ۱', () => {});
  await t.test('زیرتست ۲', () => {});
});

7. Mocking


7.1 Mock کردن تابع


test('Mock تابع', (t) => {
  const fn = t.mock.fn((a, b) => a + b);
  assert.strictEqual(fn(2, 3), 5);
  assert.strictEqual(fn.mock.callCount(), 1);
});

7.2 Mock کردن متد


test('Mock متد', (t) => {
  const obj = { add: (a, b) => a + b };
  t.mock.method(obj, 'add');
  obj.add(1, 2);
  assert.strictEqual(obj.add.mock.callCount(), 1);
});

7.3 Mock کردن تایمرها و Date


test('Mock تایمرها', (t) => {
  t.mock.timers.enable({ apis: ['setTimeout', 'Date'] });
  setTimeout(() => console.log('done'), 1000);
  t.mock.timers.tick(1000);
});

8. Snapshot Testing


test('Snapshot', (t) => {
  t.assert.snapshot({ a: 1, b: [2, 3] });
});

به‌روزرسانی Snapshotها:


node --test-update-snapshots

9. پوشش کد (Coverage)


node --experimental-test-coverage --test-reporter=lcov

10. حالت Watch


node --test --watch

11. گزارشگرهای سفارشی


node --test --test-reporter=./my-reporter.js

12. اجرای تست‌ها


node --test                        # اجرای همهٔ تست‌ها
node --test test/**/*.test.js      # الگو
node --test-only                   # فقط تست‌های only
node --test-name-pattern="my test" # فیلتر بر اساس نام

نتیجه‌گیری


ماژول node:test یک Test Runner کامل و مدرن است که امکانات زیر را ارائه می‌دهد:

  • API ساده و قدرتمند
  • زیرتست‌ها و هوک‌ها
  • Mocking برای توابع، متدها، تایمرها و ماژول‌ها
  • Snapshot Testing
  • پوشش کد و حالت Watch
  • گزارشگرهای سفارشی
  • Strict mode و Test Plans

این ماژول یک راه‌حل کامل و بدون وابستگی برای تست در پروژه‌های Node.js است.


نوشته و پژوهش شده توسط دکتر شاهین صیامی