Skip to content

تست و بررسی

چرا تست و بررسی؟

تست‌های خودکار به شما و تیمتان کمک می‌کنند تا به سرعت و با اطمینان بیشتری برنامه‌های پیچیده‌ی Vue را بسازید، باعث جلوگیری از رگرسیون‌ها شده و شما را تشویق کنند تا برنامه‌ی خود را به توابع، ماژول‌ها، کلاس‌ها و کامپوننت‌های قابل تست تقسیم کنید. همانند هر برنامه‌ی دیگری، برنامه‌ی Vue جدید شما می‌تواند به چندین روش خراب شود و مهم است که بتوانید این مشکلات را شناسایی کرده و قبل از انتشار آنها را برطرف کنید.

در این راهنما، ما اصطلاحات پایه را پوشش می دهیم و توصیه های خود را در مورد ابزارهایی که برای برنامه Vue 3 خود انتخاب می کنید، ارائه می دهیم.

یک بخش خاص برای Vue در مورد composables وجود دارد. برای اطلاعات بیشتر، به بخش تست Composables در زیر مراجعه کنید.

زمان نوشتن تست

تست نویسی را زودنر شروع کنید! توضیه می‌کنیم هرچه سریعتر نوشتن تست‌ها را شروع کنید . هر چقدر دیرتر تست‌ها را اضافه کنید وابستگی‌های بیشتری وجود خواهند داشت و اضافه کردن تست سخت‌تر می‌شود.

انواع تست

وقتی استراتژی تست اپلیکیشن Vue خود را دیزاین می‌کنید، می‌توانید از این نوع تست‌ها استفاده کنید.

  • یونیت:‌ بررسی می‌کند که ورودی‌های یک تابع، کلاس یا composable، خروجی یا side-effect های مورد انتظار را ایجاد می‌کنند.
  • کامپوننت: این نوع تست mount شدن، رندر شدن، و تعامل با کامپوننت را صحت سنجی می‌کند. این تست‌ها کد بیشتری نسبت به یونیت تست‌ها را یکباره تست می‌کنند و نسبت به یونیت تست‌ها پیچیده‌تر هستند و به زمان بیشتری برای اجرا نیاز دارند.
  • End-to-end: این نوع تست فیچرهایی را بررسی می‌کند که چندین صفحه را در بر می‌گیرند و درخواست‌های شبکه واقعی را در برابر برنامه Vue ساخته‌شده شما ایجاد می‌کند. این تست‌ها اغلب نیازمند به اجرا کردن پایگاه داده یا سایر سرویس‌های بک‌اند هست.

هر نوع تست نقشی در استراتژی تست برنامه شما ایفا می‌کند و هرکدام شما را در برابر انواع مختلف مشکلات محافظت می‌کنند.

بررسی اجمالی

در این قسمت ما به صورت مختصر به روش‌های تست، چگونگی پیاده‌سازی آن‌ها برای پروژه‌های Vue، و چند توصیه‌ عمومی خواهیم پرداخت.

Unit Testing

یونیت تست‌ها برای اطمینان از عملکرد صحیح واحدهای کوچک و مجزای کد نوشته می‌شوند. یک یونیت تست معمولا یک تابع، کلاس، composable، یا ماژول را پوشش می‌دهد. یونیت تست‌ها بر صحت منطق تمرکز دارند و فقط با بخش کوچکی از عملکرد کلی برنامه درگیر می‌شوند. ممکن است در این نوع تست بخش‌های مختلفی از محیط برنامه را ماک کنیم (مثلا حالت اولیه، کلاس‌های پیچیده، ماژول‌های third-party و درخواست‌های شبکه).

به طور کلی، یونیت تست‌ها منطق بیزینس و پیاده‌سازی منطق یک تابع را صحت‌ سنجی می‌کنند.

برای مثال این تابع increment را در نظر بگیرید:

js
// helpers.js
export function increment (current, max = 10) {
  if (current < max) {
    return current + 1
  }
  return current
}

نوشتن یونیت تست برای این تابع به دلیل نداشتن وابستگی به سادگی اجرا کردن آن و بررسی خروجی آن با استفاده از assertion ها هست.

شکست خودن هر کدام از این assertion ها نشان دهنده یک مشکل در تابع increament هست.

js
// helpers.spec.js
import { increment } from './helpers'

describe('increment', () => {
  test('increments the current number by 1', () => {
    expect(increment(0, 10)).toBe(1)
  })

  test('does not increment the current number over the max', () => {
    expect(increment(10, 10)).toBe(10)
  })

  test('has a default max of 10', () => {
    expect(increment(10)).toBe(10)
  })
})

همانطور که قبلاً ذکر شد، یونیت تست معمولاً برای منطق بیزینس بدون وابستگی، کامپوننت‌ها، کلاس‌ها، ماژول‌ها، یا توابعی که شامل رندر کردن رابط کاربری، درخواست‌های شبکه یا سایر ملاحظات محیطی نمی‌شوند، اعمال می‌شود.

این یونیت‌ها معمولاً ماژول‌های جاوااسکریپت/تایپ‌اسکریپت ساده‌ای هستند که به ویو مربوط نمی‌شوند. به طور کلی، نحوه نوشتن یونیت تست برای منطق بیزینس در برنامه‌های ویو تفاوتی با سایر فریمورک‌ها ندارد.

تنها دو مورد وجود دارد که در آن‌ها شما فیچرهای خاص ویو را یونیت تست می‌کنید:

  1. Composables
  2. کامپوننت‌ها

Composables

یک دسته از توابع خاص در برنامه‌های ویو، Composible ها هستند که برای تست نیاز به مدیریت مجزا دارند. برای اطلاعات بیشتر به تست Composible ها مراجعه کنید.

یونیت تست کردن کامپوننت‌ها

یک کامپوننت می‌تواند به دو روش تست شود:

  1. جعبه سفید: یونیت تست

تست‌های "جعبه سفید"، از جزئیات پیاده‌سازی و وابستگی‌های یک کامپوننت آگاه هستند. آن‌ها بر "ایزوله‌سازی" کامپوننت مورد تست تمرکز دارند. این تست‌ها معمولاً ماک کردن برخی یا همه فرزندان کامپوننت، تنظیمات پلاگین‌ها برای مدیریت استیت و وابستگی‌ها را شامل می‌شوند.

  1. جعبه سیاه: کامپوننت تست

    تست‌های "جعبه سیاه" از جزئیات پیاده‌سازی یک کامپوننت بی‌اطلاع هستند. این نوع تست‌ها از حداقل میزان ممکن ماک‌ها استفاده می‌کنند. تست‌های جعبه سیاه معمولاً تمام فرزندان را رندر می‌کنند و بیشتر به عنوان یک "Integration test" در نظر گرفته می‌شوند. برای اطلاعات بیشتر به قسمت توصیه‌های تست کردن کامپوننت‌ها رجوع کنید.

توصیه‌ها

  • Vitest

    از آنجایی که پیکربندی رسمی پروژه که توسط create-vue ایجاد شده، بر پایه Vite پیشنهاد ما استفاده از چارچوب یونیت تستی است که بتواند از همان تنظیمات Vite به طور مستقیم استفاده کند. Vitest, که توسط اعضای تیم Vue / Vite طراحی و نگهداری می‌شود، یک چارچوب تست است که ویژه این هدف ساخته شده است. این چارچوب به راحتی با پروژه‌های مبتنی بر Vite ادغام می‌شود و سرعت بسیار بالایی دارد.

گزینه‌های دیگر

  • Jest: یک چارچوب یونیت تست محبوب است. با این حال، ما در حالتی Jest را توصیه می‌کنیم که شما یک سورس کد مبتنی بر Jest دارید و می‌خواهید به Vite مهاجرت کنید، چرا که Vitest یکپارچگی و عملکرد بهتری ارائه می‌دهد.

کامپوننت تست

در برنامه‌های Vue، کامپوننت‌ها اصلی‌ترین قطعات سازنده رابط کاربری (UI) هستند. بنابراین، کامپوننت‌ها واحد ایده‌آلی برای جداسازی به منظور اعتبارسنجی رفتار برنامه شما هستند. از نظر دقت و جزئیات، تست کردن کامپوننت در چارچوب دقت و جزئیات، در سطحی بالاتر از تست واحدی (unit testing) قرار دارد و می‌توان آن را یک شکل از تست ادغامی (integration testing) در نظر گرفت. بخش زیادی از برنامه Vue شما باید تحت پوشش تست کامپوننت قرار گیرد و توصیه می‌کنیم برای هر کامپوننت یک فایل مشخص (spec file) و مجزا داشته باشید.

تست‌های کامپوننت باید ایرادات مربوط به پراپ‌ها (props)، رویدادها (events)، اسلات‌هایی (slots) که ارائه می‌دهد، استایل‌ها (styles)، کلاس‌ها، هوک‌های چرخه حیات، و سایر موارد را شناسایی کند.

تست‌های کامپوننت نباید کامپوننت‌های فرزند (child components) را ماک (mock) کنند، بلکه باید با برقراری ارتباط با کامپوننت‌ها همانطور که کاربر انجام می‌دهد، تعامل بین کامپوننت شما و فرزندانش را تست کنند. به عنوان مثال، یک تست کامپوننت باید روی یک عنصر کلیک کند، همانطور که کاربر انجام می‌دهد، به جای اینکه به صورت کدنویسی با کامپوننت تعامل کند.

تست‌های کامپوننت باید روی رابط‌های کاربری عمومی (public interfaces) کامپوننت تمرکز کنند، نه جزئیات پیاده‌سازی داخلی آن. برای بیشتر کامپوننت ها، روابط کاربری عمومی تفسیر میشه به: رویدادهای اجرا شده، پراپ‌ها و اسلات ها. هنگام تست، به یاد داشته باشید که عملکرد (چه کاری انجام می‌دهد) کامپوننت را تست کنید، نه چگونگی انجام آن.

بایدها

  • برای منطق ظاهری (Visual): خروجی رندر (render output) صحیح را بر اساس پراپ‌های ورودی و اسلات‌های ارائه شده تأیید کنید.

  • برای منطق رفتاری (Behavioral): بروزرسانی‌های رندر (render updates) یا رویدادهای اجرا شده صحیح را در پاسخ به رویدادهای ورودی کاربر تأیید کنید.

    در این مثال، ما یک کامپوننت شمارنده (Stepper) را نشان می‌دهیم که یک عنصر DOM با برچسب "افزایش" دارد و قابل کلیک است. ما یک پارامیتر (prop) به نام max پاس می‌دهیم که از افزایش شمارنده فراتر از عدد ۲ جلوگیری می‌کند. بنابراین، اگر روی دکمه ۳ بار کلیک کنیم، رابط کاربری همچنان عدد ۲ را نمایش خواهد داد.

    بدون در نظر گرفتن جزئیات داخلی کامپوننت شمارنده (Stepper)، تنها بر ورودی و خروجی آن تمرکز می‌کنیم: ورودی داده‌ی max و خروجی، وضعیت نهایی رابط کاربری است که کاربر می‌بیند.

Vue Test Utils
Cypress
Testing Library
js
const valueSelector = '[data-testid=stepper-value]'
const buttonSelector = '[data-testid=increment]'

const wrapper = mount(Stepper, {
  props: {
    max: 1
  }
})

expect(wrapper.find(valueSelector).text()).toContain('0')

await wrapper.find(buttonSelector).trigger('click')

expect(wrapper.find(valueSelector).text()).toContain('1')

نباید ها

  • از بررسی state داخلی یک نمونه کامپوننت یا تست متدهای داخلی آن خودداری کنید. تست کردن جزئیات نحوه‌ی عملکرد و پیاده‌سازی یک کامپوننت، باعث می‌شود که این تست‌ها شکننده شوند. چرا که با هر تغییر در نحوه‌ی پیاده‌سازی، به احتمال زیاد تست‌ها نیز نیاز به به‌روزرسانی پیدا می‌کنند.

    هدف نهایی یک کامپوننت، رندر خروجی صحیح DOM است. بنابراین، تست‌هایی که بر خروجی DOM تمرکز می‌کنند، همان سطح اطمینان از صحت عملکرد (و حتی ممکن است سطح بالاتری) را به همراه داشته باشند، در عین حال که نسبت به تغییرات مقاوم‌تر و انعطاف‌پذیرتر هستند.

    به طور انحصاری بر تست‌های اسنپ‌شات تکیه نکنید. بررسی و تأیید صرفاً کدهای HTML، بیانگر صحت عملکرد نیست. تست‌ها را با مفهوم و هدف مشخصی بنویسید.

    در صورتی که نیاز به تستی جامع برای یک متد وجود دارد، در نظر بگیرید که آن را به یک تابع مستقل (utility function) تبدیل کنید و سپس یک تست واحد اختصاصی برای آن بنویسید. اگر امکان تبدیل تمیز این متد به تابع مستقل وجود ندارد، می‌توان آن را در قالب تست کامپوننت، تست یکپارچه‌سازی (integration test) یا تست انتها به انتها (end-to-end) که آن را پوشش می‌دهد، تست کرد.

پیشنهاد

  • Vitest : برای کامپوننت ها یا کامپوزیبل هایی که بدون ویژگی بصری (headlessly) رندر میشوند (ماننده تابع useFavicon در VueUse). کامپوننت‌ها و DOM را می‌توان با استفاده از @vue/test-utils تست کرد.

  • Cypress Component Testing برای کامپوننت‌هایی که رفتار مورد انتظار آن‌ها وابسته به رندر صحیح استایل‌ها یا فعال سازی رویدادهای بومی DOM است. می‌توان از کتابخانه @testing-library/cypress استفاده کرد.

تفاوت‌های اصلی بین Vitest و اجراکننده‌های مبتنی بر مرورگر، سرعت و زمینه اجرا هستند. به طور خلاصه، اجراکننده‌های مبتنی بر مرورگر مانند Cypress می‌توانند مشکلاتی را شناسایی کنند که اجراکننده‌های مبتنی بر Node.js مانند Vitest قادر به آن نیستند (مانند مشکلات استایل، رویدادهای بومی واقعی DOM، کوکی‌ها، حافظه محلی و خرابی‌های شبکه). با این حال، اجراکننده‌های مبتنی بر مرورگر به دلیل باز کردن مرورگر، کامپایل کردن استایل‌شیت‌ها و موارد دیگر، به مراتب کندتر از Vitest هستند. Cypress یک اجراکننده مبتنی بر مرورگر است که از تست کامپوننت پشتیبانی می‌کند. برای مقایسه‌ی به‌روز Vitest و Cypress، لطفا به صفحه Vitest's comparison page مراجعه کنید.

بارگذاری کتابخانه‌ها

تست کامپوننت‌ها اغلب شامل این موارد است: بارگذاری جداگانه کامپوننت مورد نظر، شبیه‌سازی رویدادهای ورودی کاربران و بررسی خروجی رندر شده‌ی DOM. کتابخانه‌های کمکی ویژه‌ای وجود دارند که این کارها را ساده‌تر می‌کنند.

  • @vue/test-utils کتابخانه ای رسمی تست کامپوننت سطح پایینی است که با هدف ارائه دسترسی کاربران به APIهای اختصاصی Vue نوشته شده است. این کتابخانه همچنین زیربنای کتابخانه سطح بالاتر @testing-library/vue می‌باشد که برای تست کامپوننت‌های Vue مورد استفاده قرار می‌گیرد.

  • @testing-library/vue یک کتابخانه تست کامپوننت برای Vue.js است که بر تست کامپوننت‌ها بدون وابستگی به جزئیات پیاده‌سازی آن‌ها تمرکز دارد. اصل هدایت‌گر این کتابخانه این است که هرچه تست‌ها به نحوه‌ی واقعی استفاده از نرم‌افزار نزدیک‌تر باشند، اطمینان بیشتری را برای توسعه‌دهندگان به ارمغان می‌آورند.

برای تست کامپوننت‌های برنامه، استفاده از کتابخانه vue/test-utils@ را توصیه می‌کنیم. کتابخانه testing-library/vue@ در تست کامپوننت‌های ناهمزمان (asynchronous) با قابلیت Suspense مشکلاتی دارد، لذا باید با احتیاط از آن استفاده کرد.

انتخاب های دیگر

  • Nightwatch یک اجراکننده تست E2E با پشتیبانی از تست کامپوننت Vue است. (Example Project)

  • WebdriverIO برای تست کامپوننت بین‌مرورگرها است که بر تعامل کاربر بومی بر اساس استاندارد اتوماسیون تکیه می‌کند. همچنین امکان استفاده از آن به همراه Testing Library وجود دارد.

تست انتها به انتها (E2E)

در حالی که تست‌های واحد تا حدی به توسعه‌دهندگان اطمینان می‌دهند، اما تست‌های واحد و کامپوننت در پوشش جامع یک برنامه‌ی کاربردی (اپلیکیشن) پس از استقرار در محیط تولید محدودیت‌هایی دارند. در نتیجه، تست‌های انتها به انتها (E2E) روی مهم‌ترین جنبه‌ی یک اپلیکیشن تمرکز می‌کنند: آنچه زمانی که کاربران به طور واقعی از برنامه استفاده می‌کنند، اتفاق می‌افتد.

تست‌های انتها به انتها (E2E) بر رفتار برنامه‌های چند صفحه‌ای که درخواست‌های شبکه‌ای را به سمت برنامه‌ی Vue شما که در محیط تولید ساخته شده است، ارسال می‌کنند، تمرکز دارند. این تست‌ها اغلب شامل ایجاد یک پایگاه داده یا بک‌اند دیگر و حتی ممکن است در یک محیط استیجینگ زنده اجرا شوند.

تست‌های انتها به انتها (E2E) اغلب مشکلاتی را در روتر، کتابخانه مدیریت وضعیت، کامپوننت‌های سطح بالا (مانند App یا Layout)، دارایی‌های عمومی یا هرگونه مدیریت درخواست شناسایی می‌کنند. همانطور که گفته شد، آن‌ها مسائل بحرانی را که ممکن است با تست‌های واحد یا تست‌های کامپوننت قابل شناسایی نباشند، کشف می‌کنند.

تست‌های انتها به انتها (E2E) هیچ کد برنامه Vue شما را بارگیری نمی‌کنند، بلکه به طور کامل بر تست برنامه شما با پیمایش در صفحات کامل در یک مرورگر واقعی تکیه می‌کنند.

تست‌های انتها به انتها (E2E) بسیاری از لایه‌های موجود در برنامه‌ی کاربردی شما را اعتبارسنجی می‌کنند. این تست‌ها می‌توانند روی برنامه‌ی ساخته‌شده‌ی محلی شما یا حتی یک محیط استیجینگ زنده اجرا شوند. تست در برابر محیط استیجینگ نه تنها کد فرونت‌اند و سرور استاتیک شما را در بر می‌گیرد، بلکه شامل همه‌ی سرویس‌های بک‌اند و زیرساخت مرتبط نیز می‌شود.

هرچقدر تست‌های شما بیشتر شبیه به نحوه‌ی استفاده از نرم‌افزارتان باشند، اطمینان بیشتری به شما می‌دهند. - Kent C. Dodds - نویسنده کتاب خانه تست نویسی (Testing Library)

با تست کردن نحوه‌ی تاثیرگذاری اقدامات کاربر بر برنامه‌ی شما، تست‌های E2E اغلب کلید اطمینان بیشتر به عملکرد صحیح یا نادرست برنامه هستند.

انتخاب یک راه حل تست E2E

در حالی که تست انتها به انتها (E2E) در وب، پیش‌تر به دلیل غیرقابل اعتماد بودن (ناپایداری) تست‌ها و کند کردن فرآیند توسعه، شهرت منفی‌ای به دست آورده بود، ابزارهای مدرن E2E گام‌های بلندی برای ایجاد تست‌های قابل اعتمادتر، تعاملی‌تر و مفیدتر برداشته‌اند. بخش‌های زیر هنگام انتخاب یک چارچوب تست E2E برای اپلیکیشن‌تان، نکاتی را برای در نظر گرفتن ارائه می‌دهند.

تست بین مرورگری

یکی از مهم‌ترین مزایای تست‌های انتها به انتها (E2E) امکان تست کردن برنامه‌ی شما در مرورگرهای مختلف است. در حالی که دستیابی به پوشش کامل تست بین‌مرورگری (۱۰۰٪) ایده‌آل به نظر می‌رسد، لازم است توجه داشته باشید که اجرای مداوم تست‌های بین‌مرورگری به دلیل نیاز به زمان و منابع سخت‌افزاری اضافی، بازدهی کاهشی دارد. بنابراین، هنگام تعیین میزان تست بین‌مرورگری مورد نیاز برای برنامه‌ی خود، باید به این موضوع توجه ویژه‌ای داشته باشید.

حلقه‌های بازخورد سریع‌تر

یکی از چالش‌های اصلی تست و توسعه‌ی E2E، زمان‌بر بودن اجرای کل مجموعه تست است. به طور معمول، این تست‌ها تنها در خطوط انتقال و استقرار مداوم (CI/CD) اجرا می‌شوند. چارچوب‌های مدرن تست E2E با افزودن ویژگی‌هایی مانند موازی‌سازی (parallelization) به حل این مشکل کمک کرده‌اند. موازی‌سازی باعث می‌شود تا خطوط CI/CD اغلب چندین برابر سریع‌تر از قبل اجرا شوند. علاوه بر این، هنگام توسعه‌ی محلی، امکان اجرای انتخابی یک تست برای صفحه‌ای که روی آن کار می‌کنید، به همراه قابلیت بازگذاری داغ تست‌ها (hot reloading) می‌تواند به بهبود روند کاری و بهره‌وری توسعه‌دهنده کمک کند.

تجربه اشکال‌زدایی درجه یک

در حالی که توسعه‌دهندگان به طور سنتی برای یافتن مشکل در تست‌ها به بررسی لاگ‌ها در پنجره ترمینال اتکا می‌کردند، چارچوب‌های مدرن تست E2E به آنها امکان می‌دهند از ابزارهایی که از قبل با آنها آشنا هستند، مانند ابزارهای توسعه‌دهنده مرورگر، استفاده کنند.

دید در حالت بدون رابط کاربری (headless mode)

زمانی که تست‌های انتها به انتها (E2E) در خطوط انتقال و استقرار مداوم (CI/CD) اجرا می‌شوند، اغلب در مرورگرهای بدون رابط کاربری (headless browsers) اجرا می‌شوند، به این معنی که هیچ مرورگر قابل مشاهده‌ای برای کاربر باز نمی‌شود. یکی از ویژگی‌های کلیدی چارچوب‌های مدرن تست E2E، امکان مشاهده‌ی اسنپ‌شات‌ها (snapshots) و/یا ویدیوهایی از برنامه‌ی کاربردی در طول تست است که بینشی در مورد چرایی رخ دادن خطاها به توسعه‌دهندگان می‌دهد. به طور سنتی، حفظ این یکپارچه‌سازی‌ها (ادغام‌ها) کاری خسته‌کننده بود.

پیشنهاد

  • Cypress

    به طور کلی، ما معتقدیم که Cypress با برخورداری از ویژگی‌هایی مانند رابط گرافیکی آموزنده، قابلیت اشکال‌زدایی عالی، تعیینات (assertions) و استاب‌های (stubs) داخلی، مقاومت در برابر ناپایداری (flake-resistance)، موازی‌سازی (parallelization) و اسنپ‌شات‌ها، کامل‌ترین راه‌حل برای تست‌های E2E را ارائه می‌دهد. همانطور که پیش‌تر ذکر شد، همچنین از تست کامپوننت ComponentTesting. پشتیبانی می‌کند. لازم به ذکر است که از مرورگرهای مبتنی بر کرومیوم، فایرفاکس و الکترون پشتیبانی می‌کند. پشتیبانی از WebKit نیز موجود است، اما به عنوان آزمایشی علامت گذاری شده است.

انتخاب های دیگر

  • Playwright یک راه حل آزمایش E2E عالی نیز هست که از تمام موتورهای رندر مدرن از جمله Chromium و WebKit و Firefox پشتیبانی می‌کند. آزمایش در ویندوز، لینوکس و macOS، لوکال یا در CI، بدون رابط کاربری یا همراه با شبیه‌سازی موبایل بومی Google Chrome برای اندروید و Mobile Safari.
  • Nightwatch یک راه حل تست انتها به انتها (E2E) است که بر پایه Selenium WebDriver ساخته شده است. این امر باعث می‌شود Nightwatch از گسترده‌ترین پشتیبانی مرورگر در میان فریمورک‌های تست E2E برخوردار باشد، از جمله آزمایش موبایل بومی. راه حل های مبتنی بر سلنیوم از Playwright یا Cypress کندتر خواهند بود.
  • WebdriverIO یک چارچوب تست خودکار برای وب و موبایل است که بر اساس پروتکل WebDriver بنا شده است.

دستورالعمل‌ها

اضافه کردن Vitest به پروژه

در یک پروژه ویو (Vue) مبتنی بر ویت (Vite)، دستور زیر را اجرا کنید:

sh
> npm install -D vitest happy-dom @testing-library/vue

در مرحله بعد، پیکربندی Vite را برای اضافه کردن بلاک گزینه test به روز رسانی کنید:

js
// vite.config.js
import { defineConfig } from 'vite'

export default defineConfig({
  // ...
  test: {
    // enable jest-like global test APIs
    globals: true,
    // simulate DOM with happy-dom
    // (requires installing happy-dom as a peer dependency)
    environment: 'happy-dom'
  }
})

راهنمایی

اگر از TypeScript استفاده می‌کنید، vitest/globals را به فیلد types در tsconfig.json خود اضافه کنید.

json
// tsconfig.json

{
  "compilerOptions": {
    "types": ["vitest/globals"]
  }
}

سپس، یک فایل با پسوند *.test.js در پروژه خود ایجاد کنید. شما می‌توانید تمامی فایل‌های تستی خود را در یک پوشه تست (test) در ریشه پروژه قرار دهید یا در پوشه‌های تست مجزایی کنار فایل‌های سورس (source) خود جایگذاری کنید. Vitest با استفاده از توافق نام‌گذاری (naming convention) به صورت خودکار به جستجوی آنها می‌پردازد.

js
// MyComponent.test.js
import { render } from '@testing-library/vue'
import MyComponent from './MyComponent.vue'

test('it should work', () => {
  const { getByText } = render(MyComponent, {
    props: {
      /* ... */
    }
  })

  // assert output
  getByText('...')
})

در نهایت، package.json را برای اضافه کردن اسکریپت تست و اجرای آن به روز کنید:

json
{
  // ...
  "scripts": {
    "test": "vitest"
  }
}
sh
> npm test

تست کامپوزِبل‌ها

این بخش فرض می‌کند که شما بخش کامپوزِبل‌ها را مطالعه کرده‌اید Composables.

وقتی صحبت از تست کامپوزِبل‌ها می‌شود، می‌توانیم آن‌ها را به دو دسته تقسیم کنیم: کامپوزِبل‌هایی که به نمونه‌ای از یک کامپوننت میزبان وابسته نیستند، و کامپوزِبل‌هایی که وابسته هستند.

یک کامپوزِبل به نمونه‌ای از یک کامپوننت میزبان وابسته است هنگامی که از API های زیر استفاده می کند:

  • قلاب‌های چرخه عمر (Lifecycle hooks)
  • فراهم کردن / دریافت (Provide / Inject)

اگر یک کامپوزِبل فقط از API های Reactivity استفاده کند، می‌توان آن را با فراخوانی مستقیم و بررسی خروجیِ حالت (state) و متدهای برگشتی، تست کرد:

js
// counter.js
import { ref } from 'vue'

export function useCounter() {
  const count = ref(0)
  const increment = () => count.value++

  return {
    count,
    increment
  }
}
js
// counter.test.js
import { useCounter } from './counter.js'

test('useCounter', () => {
  const { count, increment } = useCounter()
  expect(count.value).toBe(0)

  increment()
  expect(count.value).toBe(1)
})

یک کامپوزِبلی که به قلاب‌های چرخه عمر (lifecycle hooks) یا الگوی Provide/Inject وابسته باشد، برای تست شدن نیاز به پوشاندن (wrap) شدن در یک کامپوننت میزبان دارد. ما می‌توانیم یک تابع کمکی (helper) به شکل زیر ایجاد کنیم:

js
// test-utils.js
import { createApp } from 'vue'

export function withSetup(composable) {
  let result
  const app = createApp({
    setup() {
      result = composable()
      // suppress missing template warning
      return () => {}
    }
  })
  app.mount(document.createElement('div'))
  // return the result and the app instance
  // for testing provide/unmount
  return [result, app]
}
js
import { withSetup } from './test-utils'
import { useFoo } from './foo'

test('useFoo', () => {
  const [result, app] = withSetup(() => useFoo(123))
  // mock provide for testing injections
  app.provide(...)
  // run assertions
  expect(result.foo.value).toBe(1)
  // trigger onUnmounted hook if needed
  app.unmount()
})

برای کامپوزِبل‌های پیچیده‌تر بیشتر، همچنین می‌توان با نوشتن تست برای کامپوننت Wrapper با استفاده از تکنیک‌های Component Testing، کار را آسان‌تر کرد.

تست و بررسی has loaded