اشکان حیدری‌فاضل
اشکان حیدری‌فاضل
خواندن ۵ دقیقه·۳ سال پیش

تست ماژول‌های ES6 با Jest

داستان چیه؟

تا قبل از ES2015، جاوااسکریپت هیچ راهکار مستقیمی برای کار کردن با ماژول‌ها نداشت. که این حفره رو node.js اومد با CommonJS پر کرد. به این صورت که ماژول دلخواهت رو با module.exports می‌فرستی بیرون و هرجایی که با ()require تحویلش بگیری، درواقع اون ماژول رو آوردیش توی فایلت که ازش استفاده کنی.

بریم با یه مثال ساده، هم این موارد رو ببینم هم یه تست ساده با Jest انجام بدیم.


اولین تست با Jest

قبل از هر چیز -با فرض اینکه node روی سیستمتون نصبه- محیط عملیاتیمون رو راه‌اندازی می‌کنیم:

npm init -y

و بعد Jest رو نصب می‌‌کنیم:

npm install --save-dev jest

حالا باید دستوری که تست رو برامون اجرا می‌کنه رو به npm معرفی کنیم. داخل فایل package.json دستور مورد نظرمون رو داخل scripts قرار می‌دیم:

افزودن دستور دلخواه برای تست کردن با jest
افزودن دستور دلخواه برای تست کردن با jest

تنظیمات اولیه دیگه تموم شد.

توی همون پوشه یه فایل به اسم sum.js ایجاد کنید و این فانکشن رو داخلش بنویسید:

فانکشن sum که دو عدد a و b را با هم جمع می‌کند در فایل sum.js قرار گرفته‌است
فانکشن sum که دو عدد a و b را با هم جمع می‌کند در فایل sum.js قرار گرفته‌است

این فانکشن قراره دوتا عدد رو بگیره و حاصل جمع‌شون رو تحویل بده.
حالا برای اینکه بتونیم این فانکشن رو با Jest تستش کنیم، نیاز داریم دوتا کار انجام بدیم:

  • لازمه که این فانکشن رو به شکل یه ماژول بفرستیمش بیرون؛ که...
  • ... یه جای دیگه بتونیم بگیریمش و تستمون رو روش انجام بدیم
⚠ چرا؟!!
این درسته که ما می‌تونیم توی یک فایل تستامون رو انجام بدیم. منتها موضوع بحثمون درمورد تست کردن ماژول‌های جاوااسکریپته؛ و من قصد دارم بهتون نشون بدم که از ES2015 به بعد که import/export به جاوااسکریپت اضافه شد، چطوری میشه بدون CommonJS و با همین import/export بتونیم تستمون رو انجام بدیم.
پس، همینطوری ماژولار پیش می‌ریم

برای اینکه فانکشنمون رو مثل یه ماژول بفرستیم بیرون، باید این خط رو به انتهای فایل sum.jsمون اضافه کنیم:

module.exports = sum;
با تغییر اخیر، فایل sum.js آماده تست کردن شد
با تغییر اخیر، فایل sum.js آماده تست کردن شد

حالا، یک فایل جدید با نام sum.test.js می‌سازیم. این فایل قراره کدهای تست‌مون رو داشته‌باشه. به ساختار اسمش دقت کنید که باید هم‌نام با فایلی باشه که ماژولِ مورد نظرمون داخلشه، و اسم فایل هم باید با test.js تموم بشه.

فایل دوم با نام sum.test.js ایجاد شد
فایل دوم با نام sum.test.js ایجاد شد

حالا نیاز داریم که ماژولمون رو توی این فایل دریافت کنیم:

ماژول توسط فانکشن require دریافت شد
ماژول توسط فانکشن require دریافت شد

اینجا ()require داره اینکار رو برامون انجام میده. حالا نیاز داریم چیزی که اصطلاحاً load کردیم رو نگهش داریم تا بتونیم باهاش کار کنیم:

ماژول در متغیر func ذخیره شد
ماژول در متغیر func ذخیره شد

الان دیگه فانکشن ()sum داخل func قرار داره. حالا دیگه می‌تونیم فانکشنمون رو با ()func تست کنیم:

کد تست نوشته شد
کد تست نوشته شد

تستمون با صدا زدن فانکشن ()test شروع میشه که دوتا پارامتر می‌گیره:

  • اسم تست: کوتاه‌ترین جمله‌ای که نشون بده دارید چه چیزی رو تست می‌کنید. مثلا اسمش رو به انگلیسی بنویسیم "انتظار میره حاصل جمع 1 و 2 برابر با 3 شود". اینطوری وقتی بعد از اجرای تست، کنارش تیک بخوره یا ضربدر بخوره، مثل یک check list، ترتمیز و مرتب می‌بینیم که کدوم تست‌ها قبول شدن (pass) و کدوم تست‌ها رد شدن (failed).
  • فانکشن: فانکشنی رو قرار میدیم که میخواد فرایند تست رو انجام بده، که اینجا مستقیماً یک فانکشن بی‌نام به صورت arrow function قرار دادیم و فرایند تستمون رو داخلش نوشتیم.

حالا کافیه دستور زیر رو اجرا کنید تا تست انجام بشه:

npm run test

در انتها، ()expect میاد خروجی فانکشنی که بهش دادیم رو نگه میداره و میده بغلی؛ که اینجا بغلیش ()toBe. هستش. ینی الان ()expect اومد حاصل (2 ,1)func رو که برابر با "3" شده، داده به ()toBe. و حالا ()toBe میاد این "3"یی که گرفته رو با چیزی که ما بهش گفتیم مقایسه می‌کنه. اگه یکی باشن، میگه "آفرین درسته" و تستمون pass میشه؛ اگه یکی نباشه می‌گه "زرشک" و تستمون failed میشه!

نمایش یک تست موفق در ترمینال
نمایش یک تست موفق در ترمینال

تست با import/export

خب، بیاید اول تغییرات لازم رو به کدمون بدیم تا همه چی شبیه ماژولای ES6 بشه. اول بریم exportمون رو تغییر بدیم:

و بعد میریم سراغ import کردن ماژولمون توی فایل sum.test.js :

الان همه چی به ES6 تغییر کرده. اما اگه دستور تست رو دوباره اجرا کنید، می‌بینید که jest بهتون می‌گه:
"بخدای مجید اگه بدونم import چیه؟! یکی بیاد بگه این import چیه @_@"

پس، الان نیاز داریم واقعاً بریم "یکی" رو بیاریم که به jest کمک کنه. یه کم به خودتون وقت بدین و یه حدس بزنید، بعد ادامه بدین...





راهنما: دنبال اونی می‌گردیم که هیچکدوم از engineهای جاوااسکریپت دستشو رد نمی‎‌‌کنن. اصن شما بیا کد ES12 بنویس، کافیه بدیش به "اون" تا واسط بشه برات، تا همه engineهای جاوااسکریپت اجراش کنن...




چیزی که می‌تونه کمکمون کنه Babel هستش. Babel یه پلاگین داره که ماژول‌های ES6 به بعد رو میاد به همون ماژول‌های مدل CommonJS تبدیل می‌کنه. اسمش دقیقاً همین جمله‌ایه که گفتم. پس بریم یه راست نصبش کنیم:

npm install --save-dev @babel/plugin-transform-modules-commonjs

تنها کار دیگه‌ای که نیاز داریم انجام بدیم اینه که این پلاگین رو به محیط تست‌مون معرفیش کنیم. اینجا منظورم از محیط environment هستش. انگلیسش رو گفتم که راحت‌تر یادتون بمونه:

معرفی پلاگین به پروژه - بطور دقیق
معرفی پلاگین به پروژه - بطور دقیق

کلمات انگلیسی رو ببینید که مثل داستان کرده این چند خط کد رو.

داریم به package.json می‌گیم که اجازه بده یکی از pluginهای babel وارد محیطِ(env) تستِ(test) من بشه و به jest کمک کنه. مرسی، اه! ?

این خیلی دقیق بود، ولی خب شاید بنظر خیلی ترسناک بیاد! می‌تونید ساده‌تر هم بنویسیدش:

معرفی پلاگین به پروژه - بطور کلی
معرفی پلاگین به پروژه - بطور کلی

حالا اگه بریم دوباره تست بگیریم، می‌بینیم که تستمون داره کار می‌کنه ????


جمع بندی

وقتی Jest کارشو شروع کرد، خیلی مقتدرانه اومد با کمک CommonJS بهمون این امکان رو داد که بتونیم تیکه‌های دلخواه کدمون رو ببریم تست کنیم. بخاطر همین Jest، حداقل در حوزه‌ی Unit Testing حسابی شناخته‌شده هستش.

زمان گذشت و JavaScript پیشرفت کرد و خودش قابلیت ماژولار نوشتن رو فراهم کرد. با اینکه همین الان هم Jest داره روی این مسئله کار می‌کنه که بیاد این قابلیت جدید JavaScript رو پوشش بده (تا یه جاهایی هم پیش رفته که امروز که اواخر سال 1400 هستش هنوز در وضعیت آزمایشی قرار داره)، اما هنوز با همون CommonJS داره عملکرد خودش رو معرفی می‌کنه.

این مقاله اصلاً به این منظور نوشته نشده که بهتون بگه "از این به بعد باید ماژولای ES6 رو با این روش تست کنید" بلکه این مقاله اونجایی به دردتون می‌خوره که یه کد ES6 (یا جدیدتر) دارید که می‌خواید الان تستش کنید، بدون اینکه بخواید برید سراغ bundlerهایی مثل webpack، parcel، gulp، vite،و یا مجبور باشید همه import/exportهاتون به ساختار CommonJs تغییر بدین

تستes6javascriptbabel
Front-end Developer | Graphic Designer
شاید از این پست‌ها خوشتان بیاید