همانطور که در تست چیست ، تستهای جاوا اسکریپت اساساً فقط کدهایی هستند که اجرای موفقیتآمیز آنها را تأیید میکنیم، یعنی بدون ایجاد Error
. با این حال، یکی از راههایی که این تعریف سادهسازی میشود این است که در آن کد را در کجا اجرا میکنیم، محیط آزمایش آن را در نظر نمیگیرد.
محیط تست را می توان به طور کلی به عنوان دو جزء در نظر گرفت: محیط زمان اجرا که برای اجرای آزمایش خود استفاده می کنید (مانند Node یا مرورگر) و همچنین API های در دسترس شما.
محیط زمان اجرا
زمانهای اجرا مانند Node یا ابزارهای مشابه مانند Deno یا Bun با هدف پشتیبانی از کد JS سمت سرور یا همه منظوره هستند. محیطهای آنها شامل APIهایی نمیشود که ممکن است در مرورگر انتظار داشته باشید، مانند ایجاد و کار با عناصر DOM و HTML، یا هیچ مفهومی از یک مؤلفه بصری یا هدف رندر (یعنی نه فقط عناصر، بلکه ارائه آن عناصر به صورت بصری با CSS به یک viewport).
به این ترتیب، اگر بخواهید مثلاً عناصر React را رندر کنید تا بتوان آنها را آزمایش کرد، این زمانهای اجرا همه منظوره شکست خواهند خورد، زیرا هیچ document
یا شی window
در دسترس نیست.
از سوی دیگر، اگر آزمایشهای خود را در یک مرورگر اجرا کنید، APIهای داخلی که میتوانید از این زمانهای اجرا انتظار داشته باشید ممکن است بدون پلیپر کردن یا کارهای اضافی در دسترس نباشند. یک گوچا معمولی چیزی شبیه خواندن و نوشتن فایلها است: فقط امکان import { fs } from 'node:'fs';
داخل یک مرورگر و به عنوان بخشی از آزمایش، فایلی را به این روش بخوانید.
این مشکل API "web" در مقابل "backend" کمی خارج از محدوده آزمایش است، زیرا داشتن یک پایگاه کد با هر دو بخش سرور و سرویس گیرنده ممکن است ناخوشایند باشد، اما با ایده نوشتن کد قابل آزمایش مرتبط است، که ما آن را انجام می دهیم. در طول این دوره مجدداً بازدید خواهم کرد.
الگوریتمی یا منطق تجاری را تست کنید
برخی از کدهای شما برای کار کردن نیازی به وارد کردن Node یا مرورگر ندارند و بنابراین، آزمایش می شوند. این چیزی است که بعداً در این دوره به آن خواهیم پرداخت، اما ساختار پایگاه کد خود به گونهای که « منطق تجاری » خالص آن جدا از رندر یا کد خاص Node باشد، میتواند آزمایش آن را آسانتر کند.
برای مثال سریع، ممکن است یک تابع Node داشته باشید که فایلی را از دیسک می خواند و می نویسد و در این فرآیند آن را تغییر می دهد. با تنظیم مجدد تابع خود برای پذیرش توابعی که خواندن و نوشتن را از دیسک انجام می دهند، آن را در هر جایی قابل آزمایش کرده اید.
در این حالت، می توانید از هر محیطی برای آزمایش این کد استفاده کنید، چه در زمان اجرا سمت سرور و چه در مرورگر. در آزمایش خود، میتوانید کمکهایی ارائه کنید که یک فایل مجازی را در حافظه ذخیره میکنند یا دادههای نگهدارنده مکان را برمیگردانند. این نوع کمک کننده برای معرفی در یک تست خوب است، زیرا برای مثال بررسی اینکه fs.writeFileSync
کار می کند مهم نیست . روی کد خود و آنچه که آن را منحصر به فرد یا مخاطره آمیز می کند تمرکز کنید.
API های مرورگر را شبیه سازی کنید
بسیاری از چارچوبهای آزمایشی، مانند Vitest، گزینهای را برای شبیهسازی محیط API مرورگر بدون اجرای مرورگر به شما ارائه میدهند. Vitest به صورت داخلی از کتابخانه ای به نام JSDOM استفاده می کند. این می تواند انتخاب خوبی برای تست های کامپوننت ساده باشد که در آن هزینه های سربار استفاده از مرورگر زیاد است.
یکی از ویژگیهای مشترک هر کتابخانه شبیهسازی این است که، اگرچه میتوانند یک مرورگر را شبیهسازی کنند - به عنوان مثال، DOM، عناصر و کوکیها، اما جزء بصری ندارند. این بدان معنی است که آنها یک روش ضروری برای کار با عناصر HTML و دیگر موارد اولیه ارائه می دهند، اما شما نمی توانید خروجی را به یک تصویر یا صفحه نمایش دهید، یا موقعیت یک عنصر را بر حسب پیکسل در صفحه بررسی کنید.
مجدداً، این انتخاب میتواند برای آزمایش مؤلفه مناسب باشد، جایی که یک مؤلفه یک عنصر React یا یک مؤلفه وب یا موارد دیگر را نشان میدهد. این نوع مؤلفهها معمولاً DOM را به روشی نسبتاً کوچک ایجاد میکنند و با آن تعامل دارند، و یک مرورگر شبیهسازیشده میتواند عملکرد کافی برای تأیید عملکرد مؤلفه به روشی که شما قصد دارید ارائه دهد. بخش آینده شامل نمونهای از تست مؤلفه React با Vitest و JSDOM است.
شبیه سازی یک مرورگر یک روش کاملاً جا افتاده است - JSDOM در سال 2014 منتشر شد - اما همیشه با استفاده از یک مرورگر واقعی متفاوت است. این تفاوتها میتوانند آشکار باشند: برای مثال، JSDOM موتور طرحبندی را شامل نمیشود، بنابراین راهی برای بررسی اندازه یک عنصر یا آزمایش یک حرکت پیچیده مانند کشیدن انگشت وجود ندارد. تفاوتها همچنین میتوانند ظریف و ناشناخته باشند، به همین دلیل است که بهتر است آزمایشهای مبتنی بر JSDOM را مختصر نگه دارید، بنابراین میتوانید خطر انحراف هر رفتاری از واقعیت را «جعبه زمانی» کنید.
یک مرورگر واقعی را کنترل کنید
برای آزمایش کد خود همانطور که کاربران شما آن را تجربه خواهند کرد، استفاده از یک مرورگر واقعی بهترین انتخاب است. در عمل، آزمایش زمانهای اجرا که از مرورگر پشتیبانی میکنند، نمونههایی از یک مرورگر واقعی را شروع و کنترل میکنند، حتی اگر «شروع» را در Node.js اجرا کنند.
کنترل مرورگر به عنوان بخشی از آزمایش به این معنی است که درست مانند یک کاربر باز میشود و به تست شما اجازه میدهد آن را با بارگیری URLها، HTML سفارشی و JS یا هر آنچه برای انجام آزمایش شما لازم است کنترل کند. سپس می توانید کدی بنویسید تا به عنوان یک کاربر عمل کنید، مثلاً با کنترل ماوس یا تایپ ورودی در کادرهای ورودی.
ابزارهای مدرن مانند WebdriverIO یا Web Test Runner می توانند تمام مرورگرهای اصلی را کنترل کنند و حتی چندین نمونه را به طور همزمان اجرا کنند. این مرورگرها میتوانند در مجاورت برنامه آزمایشی اجرا شوند (مثلاً در رایانه شخصی شما یا به عنوان بخشی از یک اقدام CI)، یا به سرویسهای تجاری خارجی برون سپاری شوند که آنها را برای شما اجرا میکنند.
کتابخانههای آزمایشی معتبرتر (از جمله Vitest و Jest) اغلب حالت مرورگر دارند، اما از آنجایی که منشأ آنها از Node.js است، حالتهای مرورگر آنها اغلب "روشن" هستند و ویژگیهای مفید را ندارند. به عنوان مثال، Vitest نمی تواند واردات ماژول را در مرورگر مسخره کند، که یک بدوی قدرتمند است که در مثال صفحه بعد استفاده می کنیم.
در عمل
با افزایش پیچیدگی تست های شما، استفاده از یک مرورگر واقعی اهمیت بیشتری پیدا می کند.
- برای آزمایشهایی که از ویژگیهای DOM استفاده نمیکنند یا از حداقل ویژگیها استفاده نمیکنند، حتی ویژگیهایی که در Node.js و زمانهای اجرا مشابه در دسترس هستند، مانند
fetch
یاEventTarget
، محیط اهمیتی ندارد. - برای تست اجزای کوچک، JSDOM می تواند مناسب باشد.
- آزمایشهای بزرگتر - برای مثال، آزمایشهای سرتاسر ، که میتوانند ورود کاربر و انجام یک عمل اصلی را شبیهسازی کنند - اجرای کامل در یک مرورگر واقعی منطقی است.
این بخش از نظر تئوری سنگین است و دیدگاه های متفاوتی را در مورد محل اجرای آزمون ها ارائه می دهد. در عمل، پایگاه کد شما بر اساس نیازهای شما و ابزارهای تست، اغلب از روشهای مختلفی برای انواع مختلف تستها استفاده میکند.
درک خود را بررسی کنید
لایه شبیه سازی jsdom *not* از چه ویژگی های مرورگر پشتیبانی می کند؟
requestAnimationFrame