تست و بررسی
چرا تست و بررسی؟
تستهای خودکار به شما و تیمتان کمک میکنند تا به سرعت و با اطمینان بیشتری برنامههای پیچیدهی 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)
})
})
همانطور که قبلاً ذکر شد، یونیت تست معمولاً برای منطق بیزینس بدون وابستگی، کامپوننتها، کلاسها، ماژولها، یا توابعی که شامل رندر کردن رابط کاربری، درخواستهای شبکه یا سایر ملاحظات محیطی نمیشوند، اعمال میشود.
این یونیتها معمولاً ماژولهای جاوااسکریپت/تایپاسکریپت سادهای هستند که به ویو مربوط نمیشوند. به طور کلی، نحوه نوشتن یونیت تست برای منطق بیزینس در برنامههای ویو تفاوتی با سایر فریمورکها ندارد.
تنها دو مورد وجود دارد که در آنها شما فیچرهای خاص ویو را یونیت تست میکنید:
- Composables
- کامپوننتها
Composables
یک دسته از توابع خاص در برنامههای ویو، Composible ها هستند که برای تست نیاز به مدیریت مجزا دارند. برای اطلاعات بیشتر به تست Composible ها مراجعه کنید.
یونیت تست کردن کامپوننتها
یک کامپوننت میتواند به دو روش تست شود:
- جعبه سفید: یونیت تست
تستهای "جعبه سفید"، از جزئیات پیادهسازی و وابستگیهای یک کامپوننت آگاه هستند. آنها بر "ایزولهسازی" کامپوننت مورد تست تمرکز دارند. این تستها معمولاً ماک کردن برخی یا همه فرزندان کامپوننت، تنظیمات پلاگینها برای مدیریت استیت و وابستگیها را شامل میشوند.
جعبه سیاه: کامپوننت تست
تستهای "جعبه سیاه" از جزئیات پیادهسازی یک کامپوننت بیاطلاع هستند. این نوع تستها از حداقل میزان ممکن ماکها استفاده میکنند. تستهای جعبه سیاه معمولاً تمام فرزندان را رندر میکنند و بیشتر به عنوان یک "Integration test" در نظر گرفته میشوند. برای اطلاعات بیشتر به قسمت توصیههای تست کردن کامپوننتها رجوع کنید.
توصیهها
از آنجایی که پیکربندی رسمی پروژه که توسط
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) و/یا ویدیوهایی از برنامهی کاربردی در طول تست است که بینشی در مورد چرایی رخ دادن خطاها به توسعهدهندگان میدهد. به طور سنتی، حفظ این یکپارچهسازیها (ادغامها) کاری خستهکننده بود.
پیشنهاد
Playwright یک راهکار عالی برای تست E2E است که از Chromium، WebKit و Firefox پشتیبانی میکند. امکان تست بر روی ویندوز، لینوکس و macOS را فراهم میکند، چه به صورت محلی یا روی CI، به صورت headless یا headed با شبیهسازی بومی موبایل برای گوگل کروم اندروید و موبایل سافاری. دارای رابط کاربری آموزنده، قابلیت اشکالزدایی عالی، assertion های داخلی، اجرای موازی، ردیابی و برای حذف تستهای ناپایدار طراحی شده است. پشتیبانی از تست کامپوننت در دسترس است، اما به عنوان آزمایشی علامتگذاری شده است. Playwright متنباز است و توسط مایکروسافت نگهداری میشود.
Cypress دارای رابط گرافیکی، قابلیت اشکالزدایی عالی، assertion های داخلی، stub ها، مقاومت در برابر ناپایداری و قابلیت snapshot است. همانطور که در بالا ذکر شد، پشتیبانی پایداری را برای تست کامپوننت فراهم میکند. Cypress از مرورگرهای مبتنی بر Chromium، Firefox و Electron پشتیبانی میکند. پشتیبانی از WebKit در دسترس است، اما به عنوان آزمایشی علامتگذاری شده است. Cypress تحت لایسنس MIT است، اما برخی از ویژگیها مانند اجرای موازی نیاز به اشتراک در Cypress Cloud دارند.
انتخاب های دیگر
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، کار را آسانتر کرد.