آشنایی با Jest

آشنایی با Jest
فهرست مقاله [نمایش]

    اگر تازه می‌خواهی با دنیای «تست» آشنا شوی، این مقاله مخصوص توست. خیلی خودمانی جلو می‌رویم و از صفر توضیح می‌دهیم Jest چی هست، چرا به درد می‌خورد و چطور سریع راهش می‌اندازیم. 

     

    Jest دقیقاً چیه؟

    Jest یک ابزار test برای دنیای JavaScript و TypeScript است. یعنی کمک می‌کند برای کدت سناریوهایی بنویسی که هر بار پروژه را اجرا می‌کنی، خودش خودکار چک کند «همه‌چیز درست کار می‌کند یا نه». Jest open source است، سرعت خوبی دارد و معمولاً با تنظیمات خیلی کم راه می‌افتد. هم برای Front‑end (مثلاً React) خوبه، هم برای Back‑end با Node.js.

    به زبان ساده: با Jest یک «محافظ نامرئی» کنار کدت می‌گذاری تا اگر تغییری دادی و چیزی خراب شد، سریع خبر بده.

    چرا Jest را انتخاب کنم؟

    سریع و ساده: بدون دردسر زیاد، نصب می‌شود و می‌تونی همون اول کار test بنویسی.

    همه‌فن‌حریف: با React و Node.js خیلی خوب connect می‌شود، ولی محدود به آن‌ها نیست.

    بدون تنظیمات عجیب: برای بسیاری از پروژه‌ها با کمترین پیکربندی جواب می‌دهد.

    جامعه‌ی بزرگ: سوال‌های تکراری معمولاً جواب آماده دارند.

     

    نصب و راه‌اندازی خیلی سریع

    ۱) وارد ریشه‌ی پروژه شو و یکی از این‌ها را بزن:

    npm i -D jest
    # یا
    yarn add -D jest
    # یا
    pnpm add -D jest

    ۲) توی package.json یک اسکریپت اضافه کن:

    {
      "scripts": {
        "test": "jest"
      }
    }

    ۳) یک فایل test بساز؛ مثلاً calculator.test.js.

    ۴) حالا بزن:

    npm run test

    تمام! Jest بالا می‌آید و test‌ها را اجرا می‌کند.

    اولین تست: ساده و سرراست

    بیایید یک مثال خیلی دم‌دستی بزنیم؛ جمع دو عدد:

    // calculator.js
    export function sum(a, b) {
      return a + b;
    }

    و حالا test:

    // calculator.test.js
    import { sum } from './calculator';
    
    test('جمع دو عدد 2 و 3 برابر 5 است', () => {
      expect(sum(2, 3)).toBe(5);
    });

    اینجا test(...) یعنی «یک سناریو برای بررسی بنویس».

    expect(...).toBe(...) هم یعنی «انتظار دارم خروجی دقیقاً برابر این مقدار باشد».

    الگوی ساده AAA

    برای این‌که test‌هایت مرتب باشند، از الگوی AAA استفاده کن:

    Arrange (آماده‌سازی): داده‌ها و شرایط را آماده کن.

    Act (اجرا): تابع/کدت را صدا بزن.

    Assert (راستی‌آزمایی): نتیجه را بررسی کن.

    همین! همین سه قدم را اگر رعایت کنی، test تمیز و قابل فهم می‌شود.

    تست‌های ناهمزمان (async/await)

    خیلی وقت‌ها با API کار می‌کنیم و نتیجه دیر می‌رسد. Jest با async/await خیلی راحت کنار می‌آید:

    // user.service.js
    export async function fetchUser(id) {
      const res = await fetch(`https://example.com/users/${id}`);
      return res.json();
    }
    // user.service.test.js
    import { fetchUser } from './user.service';
    
    test('دریافت کاربر با id=1', async () => {
      const user = await fetchUser(1);
      expect(user.id).toBe(1);
    });

    نکته: برای جلوگیری از کند شدن test‌ها، بهتر است درخواست‌های واقعی شبکه را در test‌های واحد انجام ندهیم (در ادامه با mock آشنا می‌شویم).

    Mock و Spy: وقتی نمی‌خواهی واقعاً به بیرون کانکت شوی

    گاهی یک تابع به پایگاه داده، فایل، یا اینترنت connect می‌شود. در test لازم نیست واقعاً این کار انجام شود. با mock رفتار «تقلبی ولی قابل کنترل» می‌سازیم تا تست سریع و پایدار بماند.

    // email.js
    export async function sendEmail(api, to, subject) {
      return api.send({ to, subject });
    }
    // email.test.js
    test('ارسال ایمیل با api ساختگی', async () => {
      const fakeApi = { send: jest.fn().mockResolvedValue({ ok: true }) };
    
      const result = await sendEmail(fakeApi, 'a@b.com', 'hello');
    
      expect(fakeApi.send).toHaveBeenCalledTimes(1);
      expect(fakeApi.send).toHaveBeenCalledWith({ to: 'a@b.com', subject: 'hello' });
      expect(result.ok).toBe(true);
    });

    با jest.fn() یک تابع ساختگی می‌سازیم.

    با mockResolvedValue می‌گوییم «وقتی صدا زده شد، این نتیجه را بده».

    بعد هم با toHaveBeenCalledWith چک می‌کنیم با چه داده‌هایی connect شده.

    Snapshot: عکس یادگاری از خروجی

    snapshot بیشتر زمانی به درد می‌خورد که ظاهر خروجی مهم باشد (مثلاً یک کامپوننت React) یا یک شیء بزرگ برمی‌گردد و نمی‌خواهیم تک‌تک فیلدها را دستی چک کنیم.

    test('خروجی قالب‌بندی شده تغییر نکرده باشد', () => {
      const view = renderUserCard({ id: 1, name: 'Ali' });
      expect(view).toMatchSnapshot();
    });

    بار اول یک فایل snapshot ساخته می‌شود. دفعه‌های بعد اگر خروجی عوض شده باشد، Jest بهت می‌گوید. اگر تغییر عمدی بود، با یک دستور می‌توانی snapshot جدید را ذخیره کنی.

    Coverage: ببینیم چقدر از کد زیر تست است

    با یک پرچم ساده می‌توانی coverage بگیری:

    npm run test -- --coverage

    بعد از اجرا، یک گزارش می‌بینی که می‌گوید چند درصد Lines/Functions/Branches پوشش داده شده. عدد بزرگ الزاماً به معنی کیفیت بالا نیست، ولی کمک می‌کند جاهایی که بدون test مانده را ببینی.

    ساختار پوشه و نام‌گذاری فایل‌های تست

    معمولاً کنار هر فایل کد، یک فایل test با پسوند .test.js یا .spec.ts می‌گذارند.

    یا یک پوشه‌ی جدا درست می‌کنند به اسم __tests__.

    مهم‌تر از همه «ثبات» است: هر چه انتخاب می‌کنی، همه‌ی تیم همان را ادامه دهند.

    چند نکته‌ی طلایی روزمره

    تست‌ها مستقل باشند: نتیجه‌ی هر test نباید به اجرای قبلی وابسته باشد.

    نام‌گذاری شفاف: عنوان test مثل یک جمله‌ی قابل فهم باشد: «وقتی ورودی X می‌دهیم، خروجی Y می‌خواهیم».

    داده‌ی آزمایشی تمیز: برای ساخت داده از توابع کمکی (factory) استفاده کن تا تکرار کد کم شود.

    استفاده‌ی به‌جا از snapshot: برای خروجی‌هایی که «شکل» مهم است، عالی است؛ برای منطق محض، همان expect‌های دقیق بهترند.

     

    یک مسیر کاری ساده با TDD

    روش TDD سه مرحله دارد:

    قرمز: اول test بنویس، طبیعتاً شکست می‌خورد.

    سبز: کمترین کد لازم را بزن تا test پاس شود.

    بازآرایی: حالا کد را تمیز کن، بدون اینکه test‌ها بشکنند.

    این چرخه کمک می‌کند کدت کم‌کم «طراحی بهتر» پیدا کند و با خیال راحت تغییرش بدهی.

     

    اجرای خودکار در CI/CD

    بهتر است روی هر pull request، test‌ها خودکار اجرا شوند. اگر test شکست خورد، ادغام متوقف شود تا کیفیت حفظ شود. یک نمونه خیلی کوچک برای GitHub Actions:

    name: tests
    on: [push, pull_request]
    jobs:
      run-tests:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
          - uses: actions/setup-node@v4
            with:
              node-version: '20'
          - run: npm ci
          - run: npm test -- --coverage

     

    خطاهای رایج و راه‌حل‌های سریع

    تست‌های کند: درخواست شبکه را mock کن، داده‌ها را کوچک نگه دار.

    وابستگی به زمان: از تایمرهای ساختگی (jest.useFakeTimers) استفاده کن.

    snapshotهای حجیم: فقط جاهایی که واقعاً لازم است snapshot بگیر.

    state مشترک: بین test‌ها state مشترک نساز؛ اگر لازم شد قبل/بعد از هر test با beforeEach/afterEach تمیزکاری کن.


    جمع‌بندی

    Jest مثل یک هم‌تیمی منظم و خستگی‌ناپذیر است؛ هر بار پروژه را اجرا می‌کنی، با سرعت همه‌چیز را چک می‌کند و اگر مشکلی باشد، بهت می‌گوید «حواست باشه!». نصبش ساده است، با React و Node.js خوب connect می‌شود، و ابزارهای مفیدی مثل mock، snapshot و coverage دارد. اگر امروز اولین قدمت را برای test نوشتن برداری، فردا تغییر دادن کدت خیلی کم‌استرس‌تر می‌شود.


    پرسش‌های کوتاه (FAQ)

    Jest فقط برای React است؟
    نه؛ با React عالیه ولی برای Node.js و پروژه‌های ساده‌ی JavaScript/TypeScript هم کاملاً جواب می‌دهد.

    برای شروع حتماً باید تنظیمات پیچیده انجام بدهم؟
    نه؛ اغلب با یک نصب ساده و یک اسکریپت "test": "jest" کار راه می‌افتد.

    عدد coverage چند باشد خوب است؟
    عددی جادویی وجود ندارد، ولی معمولاً ۷۰–۸۰٪ برای شروع خوب است. مهم‌تر از عدد، پوشش بخش‌های حساس و پرریسک است.

    mock چیست؟
    یک نسخه‌ی ساختگی از وابستگی‌ها که جای نسخه‌ی واقعی می‌نشیند تا test سریع و قابل کنترل باشد (مثلاً به اینترنت واقعی وصل نشوی).

    snapshot کِی به درد می‌خورد؟
    وقتی «شکل خروجی» مهم است؛ مثلاً یک کامپوننت UI یا یک شیء بزرگ که دستی چک‌کردنش سخت است.

     

    اطلاعات نویسنده
    • نویسنده: تیم تحریریه باگتو

    ارسال دیدگاه

    برای افزودن دیدگاه خود، نیاز است ابتدا وارد حساب کاربری‌تان شوید


    دیدگاه کاربران

    آموزش پیشنهادی باگتو


    course image

    Git در Visual Studio

    2,490,000 تومان


    اطلاعات بیشتر

    course image

    آموزش http و مبانی web

    199,000 تومان

    39,800 تومان


    اطلاعات بیشتر

    }