تا قبل از ES2015، جاوااسکریپت هیچ راهکار مستقیمی برای کار کردن با ماژولها نداشت. که این حفره رو node.js اومد با CommonJS پر کرد. به این صورت که ماژول دلخواهت رو با module.exports میفرستی بیرون و هرجایی که با ()require تحویلش بگیری، درواقع اون ماژول رو آوردیش توی فایلت که ازش استفاده کنی.
بریم با یه مثال ساده، هم این موارد رو ببینم هم یه تست ساده با Jest انجام بدیم.
قبل از هر چیز -با فرض اینکه node روی سیستمتون نصبه- محیط عملیاتیمون رو راهاندازی میکنیم:
npm init -y
و بعد Jest رو نصب میکنیم:
npm install --save-dev jest
حالا باید دستوری که تست رو برامون اجرا میکنه رو به npm معرفی کنیم. داخل فایل package.json دستور مورد نظرمون رو داخل scripts قرار میدیم:
تنظیمات اولیه دیگه تموم شد.
توی همون پوشه یه فایل به اسم sum.js ایجاد کنید و این فانکشن رو داخلش بنویسید:
این فانکشن قراره دوتا عدد رو بگیره و حاصل جمعشون رو تحویل بده.
حالا برای اینکه بتونیم این فانکشن رو با Jest تستش کنیم، نیاز داریم دوتا کار انجام بدیم:
⚠ چرا؟!!
این درسته که ما میتونیم توی یک فایل تستامون رو انجام بدیم. منتها موضوع بحثمون درمورد تست کردن ماژولهای جاوااسکریپته؛ و من قصد دارم بهتون نشون بدم که از ES2015 به بعد که import/export به جاوااسکریپت اضافه شد، چطوری میشه بدون CommonJS و با همین import/export بتونیم تستمون رو انجام بدیم.
پس، همینطوری ماژولار پیش میریم
برای اینکه فانکشنمون رو مثل یه ماژول بفرستیم بیرون، باید این خط رو به انتهای فایل sum.jsمون اضافه کنیم:
module.exports = sum;
حالا، یک فایل جدید با نام sum.test.js میسازیم. این فایل قراره کدهای تستمون رو داشتهباشه. به ساختار اسمش دقت کنید که باید همنام با فایلی باشه که ماژولِ مورد نظرمون داخلشه، و اسم فایل هم باید با test.js تموم بشه.
حالا نیاز داریم که ماژولمون رو توی این فایل دریافت کنیم:
اینجا ()require داره اینکار رو برامون انجام میده. حالا نیاز داریم چیزی که اصطلاحاً load کردیم رو نگهش داریم تا بتونیم باهاش کار کنیم:
الان دیگه فانکشن ()sum داخل func قرار داره. حالا دیگه میتونیم فانکشنمون رو با ()func تست کنیم:
تستمون با صدا زدن فانکشن ()test شروع میشه که دوتا پارامتر میگیره:
حالا کافیه دستور زیر رو اجرا کنید تا تست انجام بشه:
npm run test
در انتها، ()expect میاد خروجی فانکشنی که بهش دادیم رو نگه میداره و میده بغلی؛ که اینجا بغلیش ()toBe. هستش. ینی الان ()expect اومد حاصل (2 ,1)func رو که برابر با "3" شده، داده به ()toBe. و حالا ()toBe میاد این "3"یی که گرفته رو با چیزی که ما بهش گفتیم مقایسه میکنه. اگه یکی باشن، میگه "آفرین درسته" و تستمون pass میشه؛ اگه یکی نباشه میگه "زرشک" و تستمون failed میشه!
خب، بیاید اول تغییرات لازم رو به کدمون بدیم تا همه چی شبیه ماژولای 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 تغییر بدین