آموزش تست نویسی جاوا اسکریپت به زبان ساده
همه میدانیم که باید «تست نویسی واحد» (Unit testing) را انجام دهیم. در این میان، یکی از چالشهای اصلی ما این است که نقطه شروع این فرآیند را به درستی شناسایی کنیم و نسبت زمان لازم برای تست را به پیادهسازی واقعی به درستی تعیین نماییم.
پرسشهای اصلی در این زمینه عبارتند از:
- از کجا باید شروع کنیم؟
- آیا تست نویسی به جز تست کد، مزایای دیگری هم برای تیمهای توسعه دارد؟
در این مقاله از مکتب خونه، به آموزش تست نویسی Javascript و توضیح انواع تستها و مزایای تست نویسی برای تیمهای توسعه نرمافزار و برنامه نویسی میپردازیم. همچنین، برای شما مخاطبان مکتب خونه، یک فریمورک تست Jest – جاوا اسکریپت را معرفی خواهیم کرد.
انواع مدلهای تست نویسی در جاوا اسکریپت
در برخی موارد، تفاوت میان انواع روشهای تست تنها در جزئیات کوچکی نهفته است که به همین دلیل، تمایز قائل شدن میان آنها برای افراد دشوار میشود و این موضوع میتواند منجر به سردرگمی گردد. به همین خاطر، پیش از آنکه به جزئیات تست نویسی بپردازیم، باید مرور کوتاهی بر انواع مختلف تست داشته باشیم تا ابهامات کلی را برطرف کنیم.
تستهای واحد
«تستهای واحد» (Unit test) در فرآیند توسعه و برنامهنویسی، برای آزمایش و ارزیابی بخشهای مجزا از کدهای پیادهسازی شده، میتوان از تستهای واحد استفاده کرد. این تستها به صورت مستقل و بدون نیاز به یکپارچهسازی با بخشهای دیگر برنامه و یا چارچوب کلی آن انجام میشوند.
میتوان عملکرد تستهای واحد را به فرآیند تبدیل یک لینک به زبان خاص تشبیه کرد:
export function getAboutUsLink(language){
switch (language.toLowerCase()){
case englishCode.toLowerCase():
return '/about-us';
case spanishCode.toLowerCase():
return '/acerca-de';
}
return '';
}
تستهای یکپارچهسازی
هنگام انجام پروژه، ممکن است کد شما با دیتابیس، فایل سیستم یا یک سرویس جانبی دیگر ارتباط برقرار کند. همچنین ممکن است در برخی شرایط، یک ماژول دیگر در برنامه شما وجود داشته باشد. این بخش از پروژه، باید توسط تستهای یکپارچهسازی آزمایش شوند.
معمولا تستهای یکپارچهسازی شامل مراحل مختلف و پیچیدهای هستند که شامل آمادهسازی محیطهای تست، راهاندازی وابستگیها و غیره میشوند.
تستهای عملکردی
در بین انواع شیوه تست که معرفی کردیم، تستهای واحد و یکپارچهسازی، شما را از اجرای صحیح برنامهتان مطلع میکنند. یک نوع دیگر از تست که تستهای عملکردی نام دارند، به برنامهتان از دیدگاه کاربر نگاه میکند و نحوه کارکرد آن را طبق مولفههای از پیش تعیین شده بررسی میکند.
در نمودار بالا، مشاهده میکنید که تستهای واحد پایه بزرگی از مجموعه تست برنامه شما را شامل میشوند. تستهای واحد، کوچک هستند اما تعداد زیادی از آنها وجود دارد و همواره فعالیت و شیوه اجرا آنها به صورت خودکار است. حال زمانش رسیده که بیشتر درباره تستهای واحد صحبت کنیم!
پیشنهاد مطالعه: آموزش جاوا اسکریپت در وردپرس؛ صفر تا صد
اهمیت تست نویسی برای برنامهنویسان
به طور معمول، زمانی که از توسعهدهندگان میپرسید: آیا برای برنامهتان تست نوشتهاید؟ میگویند: وقت نداشتم یا به آنها نیازی ندارم. میدانم که قرار است به خوبی کار کند!
پس از شنیدن این پاسخها، به آنها یادآوری میکنم که تستهای واحد صرفا برای تست کردن کد مورد استفاده قرار نمیگیرند. تستهای واحد میتوانند به روشهای گوناگونی به شما کمک کنند:
مطمئن شدن از کارکرد صحیح کد
آخرین باری که کدتان را تغییر دادید اما ساخت شما شکست خورد و نیمی از برنامهتان از کار افتاد، چه زمانی بود؟ به شخصه، مشابه این اتفاق هفته گذشته رخ داد.
با این وجود، ایرادی بر کار شما وارد نیست. مشکل واقعی زمانی است که ساخت موفق میشود، تغییر اعمال میشود اما فعالیت برنامه شما به شکل ناپایداری ادامه پیدا میکند. زمانی که این اتفاق میافتد، اعتمادتان را نسبت به کدهای پروژه از دست میدهید و در نهایت، تنها آرزوی شما این است که کدهایتان به شکلی درست کار کنند.
برای اینکه بتوانید این مشکل را خودتان حل کنید، باید از تست نویسی استفاده کنید. تستهای واحد به شما کمک میکنند تا مشکلات را زودتر پیدا کرده و مشکلات مرتبط با آنها را برطرف کنید. بدین ترتیب، میتوانید با اعتماد به نفس بالاتری به ادامه کار خود برسید.
تصمیمات ساختاری بهتری بگیرید
در طول پروژه، کدها تغییر میکنند، اما برخی تصمیمات در مورد پلتفرم، ماژولها، ساختار و سایر موارد باید در نقطه صفر پروژه گرفته شوند. استفاده از تست نویسی واحد از همان مراحل ابتدایی پروژه به شما کمک میکند تا کدهای خود را به شکل بهینهتری ساختاربندی کنید و به جداسازی مناسب نگرانیها (Separation Of Concerns) بپردازید.
از طریق تستهای واحد، دیگر وسوسهای برای اختصاص دادن مسئولیتهای متعدد به بلوکهای کد واحد نخواهید داشت زیرا تست واحد آنها، اتفاق سخت و ترسناکی خواهد بود.
پیشنهاد مطالعه: آموزش حلقه While در جاوا اسکریپت به زبان ساده
مشخص کردن عملکرد پیش از کدنویسی
در اغلب اوقات، شما مسیر کلی پروژه را در ذهن خود ترسیم کرده و بلافاصله شروع به پیادهسازی آن میکنید. اما به این فکر کردهاید که اگر پارامتری خالی باشد، چه اتفاقی رخ میدهد؟ اگر مقدار آن خارج از محدوده مورد انتظار باشد یا حاوی کاراکترهای زیادی باشد، چه رخدادی در انتظارتان است؟ آیا آن را به عنوان یک شرایط استثنایی تلقی میکنید یا آن را به شکل کاملی باطل میکنید؟
تستهای واحد، مسیر شما را در کشف کردن تمامی موارد ذکر شده تسهیل کرده و کمک میکنند تا به پاسخ مناسبی در مدت زمان کوتاهتری برسید. مجددا به سوالات نوشته شده نگاه کنید؛ متوجه میشوید که دقیقا این پرسشها همان چیزی هستند که موارد تست نویسی شما را تعریف میکنند.
علاوه بر موارد گفته شده، مطمئنم که مزایای بیشتری در انتظار استفادهکنندگان از تستهای واحد است. کارکردهای بالا، تنها جزو محدود مواردی هستند که در طول زمان طولانی و صرف تجربه، آنها را به دست آوردهام!
آموزش تست نویسی جاوا اسکریپت
پس از مرور بر انواع شیوههای تستنویسی و کارکرد آنها، وقت آن رسیده تا به آموزش تست نویسی جاوا اسکریپت بپردازیم. در طول این آموزش، ما با فریمورک Jest جاوا اسکریپت شروع میکنیم. ابزار Jest، تست خودکار کد را فعال میکند، پوشش کد را فراهم کرده و به ما اجازه میدهد تا به راحتی هر چه بیشتر به ماکت کردن اشیا (Mocking Objects) بپردازیم. علاوه بر کارکردهای بالا، ابزار Jest دارای افزونهای برای Visual Studio Code است که در این آموزش، در دسترس ما قرار دارد.
برای آموزش تست نویسی جاوا اسکریپت، علاوه بر Jest، فریمورکهای دیگری نیز وجود دارند که در صورت تمایل میتوانید با آنها آشنا شده و از فریمورکهای دیگر نیز استفاده کنید.
npm i jest --save-dev
برای شروع تست نویسی با جاوا اسکریپت، باید از روش getAboutUsLink که قبلا ذکر شد، به عنوان پیاده سازی کدی که میخواهیم آزمایش کنیم استفاده کرد:
const englishCode = "en-US";
const spanishCode = "es-ES";
function getAboutUsLink(language){
switch (language.toLowerCase()){
case englishCode.toLowerCase():
return '/about-us';
case spanishCode.toLowerCase():
return '/acerca-de';
}
return '';
}
module.exports = getAboutUsLink;
کد داده شده را در فایل index.js قرار دهید .به طور کلی، میتوانید تستنویسی را در فایل یکسانی پیش ببرید، اما روش بهتر این است که تستهای واحد را در یک فایل جداگانه قرار دهید.
برای نامگذاری فایلهای تست نیز میتوانید از فرمتهای زیر استفاده کنید:
- {filename}.test.js
- {filename}.spec.js
در اینجا، من از روش اول، یعنی index.test.js استفاده کردم:
const getAboutUsLink = require("./index");
test("Returns about-us for english language", () => {
expect(getAboutUsLink("en-US")).toBe("/about-us");
});
در ادامه فرایند، ابتدا باید تابعی که قصد تست آن را داریم را وارد کنیم. هر تست از طرف ما به عنوان فراخوانی «تابع test» تعریف میشود. پارامتر اول نیز، اسم تست برای مرجع شماست. پارامتر دوم، یک تابع فلش است که در آن تابعی که میخواهیم تست کنیم را صدا زده و خروجی مد نظرمان را مشخص میکنیم.
در مثال زیر، تابع getAboutUsLink را با پارامتر زبان en-US فراخوان میدهیم. انتظار داریم خروجی برابر با /about-us باشد.
اکنون میتوانیم Jest CLI را به منظور آموزش تست نویسی جاوا اسکریپت، به شکل سراسری نصب کرده و تست را اجرا کنیم:
npm i jest-cli -g
jest
اگر در طول آموزش تست نویسی جاوا اسکریپت، با خطای مربوط به پیکربندی مواجه شدید، اطمینان حاصل کنید که فایل package.json شما وجود دارد. در صورت وجود نداشتن این فایل، میتوانید به کمک استفاده از دستور npm init فایل جدیدی بسازید.
پس از اجرای دستور بالا، خروجی مشابهی با مورد زیر خواهید دید:
PASS ./index.test.js
√ Returns about-us for english language (4ms)
console.log index.js:15
/about-us
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.389s
فرایندی که از ابتدا تا به اینجا متن در حال انجامش بودید، تست نویسی ساده جاوا اسکریپت بود. اگر افزونه Visual Studio Code را نصب کرده باشد، با ذخیره کردن یک فایل، تمامی تستها به شکل خودکار اجرا میشوند. بدین منظور، بیایید با اضافه کردن این خط به تست آن را کمی گسترش دهیم:
expect(getAboutUsLink("cs-CZ")).toBe("/o-nas");
پس از اینکه فایل را ذخیره کردید، ابزار Jest به شما اطلاع میدهد که تست با شکست مواجه شده است. این اطلاعیه به شما کمک میکند تا قبل از ثبت نهایی تغییرات (کامیت کردن)، مشکلات احتمالی را بیابید.
پیشنهاد مطالعه: آموزش دستورات جاوا اسکریپت به زبان ساده
تست تابع پیشرفته و ماک کردن سرویسها
در یک پروژه واقعی، ممکن است کدهای زبان برای متد getAboutUsLink ثابت نباشند و در همان فایل مد نظر شما قرار نگیرند. به طور معمول، مقادیر آنها نیز در کل پروژه به کار گرفته میشود. بنابراین، در یک ماژول جداگانه آنها را تعریف کرده و به تمام توابعی که از آنها استفاده میکنند، وارد میکنیم:
import { englishCode, spanishCode } from './LanguageCodes'
توجه داشته باشید که شما میتوانید مقادیر ثابت را به شیوه گفته شده وارد تست کنید. اما اگر به جای ثابتهای ساده با اشیاء کار میکنید، شرایط برای شما پیچیدهتر خواهد شد.
بیایید به متد زیر نگاهی بیندازیم:
import { UserStore } from './UserStore'
function getUserDisplayName(){
const user = UserStore.getUser(userId);
return `${user.LastName}, ${user.FirstName}`;
}
این متد از UserStore که از بیرون وارد شده است استفاده میکند:
class User {
getUser(userId){
// logic to get data from a database
}
setUser(user){
// logic to store data in a database
}
}
let UserStore = new User();
export { UserStore }
در متد قبلی، برای اینکه بتوانید روشی مناسب و بهینه برای تستنویسی دست پیدا کنید، نیاز به ماک کردن UserStore دارید.
یک ماکت، جانشینی برای شیء و اجزای اصلی ما محسوب میشود. ماک کردن به ما این امکان را میدهد تا وابستگیها و دادههای واقعی را از پیادهسازی متد تحت تست جدا سازیم. در واقع کارکرد ماکت، همچون مانکنهایی است که در تست تصادف خودرو به جای افراد واقعی استفاده میشوند.
اگر در طول تستنویسی و توسعه، از ماکت استفاده نکنیم، در حال تست کردن هر دو تابع و خود انبار اطلاعات هستیم. این شیوه از کارکرد تست را یک تست ادغام مینامند. شما برای اینکه بتوانید فرایند پروژه را طبق خواسته خود پیش ببرید، به احتمال زیاد به ماک کردن دیتابیس استفاده شده خواهید داشت.
ماک کردن سرویس
برای ماک کردن اجزا میتوانید از تابع ماکساز یا یک ماک دستی استفاده کنید. در ادامه، تمرکز خود را بر روی ماک دستی میگذاریم و مطالبی مرتبط با ماک دستی ارائه خواهیم داد. شما میتوانید علاوه بر ماک دستی که خود روشی ساده برای ماک کردن است، از سایر امکانات ماکسازی که Jest ارائه میدهد نیز استفاده کنید.
jest.mock('./UserStore', () => ({
UserStore: ({
getUser: jest.fn().mockImplementation(arg => ({
FirstName: 'Ondrej',
LastName: 'Polesny'
})),
setUser: jest.fn()
})
}))
گام اول برای ماک کردن این است که مشخص کنیم چه چیزی را میخواهیم ماک کنیم. در اینجا قصد ما ماک کردن ماژول ./UserStore است. سپس باید ماکتی را برگردانیم که حاوی تمام اجزای خروجی (Exported) از آن ماژول باشد.
در این نمونه، فقط شیء User با نام UserStore است که تابع getUser را دارد اما این فرایند ماک کردن در پیادهسازیهای کد در پروژههای واقعی، بسیار طولانیتر است. همچنین، هر تابعی که در محدوده تست نویسی به آن اهمیت نمیدهید، به راحتی با jest.fn() قابل ماک شدن است.
تست واحدی برای تابع getUserDisplayName، مشابه تستی است که قبلا ایجاد کردیم:
test("Returns display name", () => {
expect(getUserDisplayName(1)).toBe("Polesny, Ondrej");
})
به محض اینکه فایل را ذخیره کردید، Jest پیامی را تحت عنوان «2 تست با موفقیت اجرا شد» را به شما نشان میدهد. اگر تستها را به صورت دستی اجرا میکنید، فایلها را هر چه سریعتر ذخیره کنید و مطمئن شوید که نتیجه مشابهی را میبینید.
گزارش پوشش کد
تا به این جای آموزش تست نویسی جاوا اسکریپت، یاد گرفتهاید که چگونه تستهایی را بنویسید که کدهایتان را تحت پوشش قرار دهند. به طور طبیعی، انجام این کار همیشه آسان نیست و گاهی اوقات چالشهایی را به همراه دارد. در نهایت، ما انسان هستیم و به دنبال راههایی برای سرعت بخشیدن به فرآیند توسعه و انجام کارها بدون دردسر هستیم. در این میان، تستهای واحد میتوانند به وظایف ناخواستهای تبدیل شوند که تمایل به نادیده گرفتن آنها داریم.
برای حل این مشکل، گزارش پوشش کد (Code Coverage Report ) ابزاری است که به کمک ما میآید. گزارش پوشش کد به شما نشان میدهد که چه درصدی از کدهایتان توسط تستهای واحد پوشش داده شده است. به عنوان مثال، اولین تست واحدی که برای بررسی تابع getAboutUsLink نوشتیم را در نظر بگیرید:
test("Returns about-us for english language", () => {
expect(getAboutUsLink("en-US")).toBe("/about-us");
});
این تست، لینک انگلیسی را بررسی میکند اما نسخه اسپانیایی آن بدون اعمال هیچ تستی باقی میماند.در واقع، پوشش کد تنها به صورت 50 درصدی انجام شده است.
تست واحد دیگر به طور کامل تابع getDisplayName را بررسی میکند و پوشش کد آن به طور کامل صورت میگیرد. در مجموع، کل پوشش کد 67 درصد است. در طی این فرآیند، ما 3 سناریو برای تست داشتیم اما تستهای ما فقط 2 مورد از آنها را پوشش میدهند.
برای اینکه بتوانید گزارش پوشش کدتان را مشاهده کنید، دستور زیر را در ترمینال تایپ کنید:
jest --coverage
اما اگر از Visual Studio Code با افزونه Jest استفاده میکنید، میتوانید دستور (CTRL+SHIFT+P) Jest: Toggle Coverage Overlay را اجرا کنید. این دستور به شما نشان میدهد که کدام خطوط کد در پیادهسازی با تست، پوشش داده نشدهاند.
در ادامه، با اجرا بررسی پوشش، Jest یک گزارش با فرمت HTML ایجاد میکند. فایل ایجاد شده را میتوانید در پروژه خود تحت عنوان coverage/lcov-report/index.html پیدا کنید. در این لحظه، شما موفق شدهاید که پوشش کدهایتان را به شکل 100 درصدی انجام دهید!
نکته: خوب است بدانید که ممکن است پوشش کد شما در گزارش 100 درصد باشد اما در واقعیت، دستیابی به این عدد همیشه ممکن نیست. به طور کلی، هدف این است که تستهای واحد به شما در نگهداری کد و اطمینان از عملکرد همیشگی آن کمک کنند.
پیشنهاد مطالعه: آموزش ساخت ماشین حساب با جاوا اسکریپت به صورت گام به گام
کلام پایانی
در این مقاله از مکتبخانه، شما را با انواع شیوههای تست کد جاوا اسکریپت و ویژگیهای هر یک از آنها آشنا کردیم. در ادامه، کاربردهای گوناگون تست کد را به شما نشان دادیم و علل استفاده از تست کد را برای مخاطبان مکتبخانه شرح دادیم. در نهایت کلیات آموزش تست نویسی Javascript را برای شما قرار دادیم و سعی کردیم متدهای ماکت کردن و پوشش کد را به شکل کاملی توضیح دهیم.
آموزش تست نویسی Javascript با دورههای مکتب خونه
تا به اینجا سعی کردیم شما را با کلیات آموزش تست نویسی جاوا اسکریپت آشنا کنیم. اگر به حوزه تستنویسی علاقه دارید و میخواهید در دوره تست نویسی و آموزش پروژه محور جاوا اسکریپت شرکت کنید، میتوانید از دورههای متنوع آموزش برنامه نویسی و آموزش جاوا اسکریپت مکتبخونه استفاده کنید. در مکتب خونه انواع دورهها تحت عنوان آموزش تایپ اسکریپت، آموزش جاوا اسکریپت، آموزش اکما اسکریپت، آموزش جاوا اسکریپت پیشرفته و غیره را میتوانید بیابید.
همچنین لازم است بدانید که مکتب خونه علاوه بر ارائه ویدیوهای آموزشی، مدرک معتبری را به دانشجویان خود ارائه میدهد که با قرار دادن آن در رزومهتان میتوانید مهارتهای خود را به کارفرمایان اثبات کنید. پس تا هر چه سریعتر، از طریق وبسایت مکتب خونه دوره مد نظرتان را خریداری کنید و به آموزش و یادگیری بپردازید!
رفرنس مورد استفاده برای این مطلب: freecodecamp