تست نویسی در ری اکت و هرچیزی که باید راجبش بدونیم! راهنمای تست نویسی در React !
تست نویسی در ری اکت برعکس اسم وحشتناکی که داره و تصور اشتباهی که درمورد سخت بودنش وجود داره، خیلی خیلی آسونه! هرجا بحث تست نویسی در React میشه، همه فکر میکنن این یه مبحث خیلی سخت و پیچیدس!
دقیقا به همین دلیل تصمیم به انتشار این مقاله گرفتیم تا تست نویسی در ریکت رو به ساده ترین شکل ممکن بررسی کنیم 🙂
اگه React Developer هستی و چیزی درمورد تست نویسی در React نمیدونی و میخوای یه Level-Up خفن داشته باشی، این مقاله رو مطالعه کن چون به ساده ترین شکل ممکن تست نویسی در ری اکت رو آموزش دادیم 🙂
با فِرانت اِندی همراه باشید 🙂
تست نویسی چیست ؟
تست نویسی به فرآیند نوشتن تست و اجرای آزمایش های مختلف برای اطمینان حاصل از اینکه اجزای اپیکیشن ما به درستی کار میکنن میگن.
در حقیقت ما باید برای اجزای مختلف اپیکیشن خودمون تست بنویسیم تا مطمئن بشیم همونطور که ازشون انتظار داریم، کار میکنن.
ما باید به یک روشی مطمئن بشیم که تمامی این بخش ها دارن درست کار میکنن و هیچ مشکلی ندارن. این روش تست نویسی هست 🙂
تست نویسی به ما اجازه میده عملکرد اجزای مختلف اپیکیشن خودمون رو تست کنیم و اطمینان حاصل کنیم که همه چیز داره درست کار میکنه.
تست نویسی یکی از مهمترین بخش های توسعه هر اپیکیشن هست چون به شناسایی ایرادات اپیکیشن و اطمینان از کیفیت کد و جلوگیری از هدر زمان توسعه دهنده کمک میکنه.
چرا تست نویسی ؟
تست نویسی باعث میشه مطمئن بشیم تیکه کد های ما همونطور که ازشون انتظار داریم، کار میکنن.
تست نویسی در ری اکت شامل چه چیزایی میشه ؟
تست نویسی در React معمولا شامل موارد زیر میشه :
تست نویسی کامپوننت هایی که Props دارن
تست نویسی کامپوننت هایی که Props ندارن
تست نحوه re-Render شدن کامپوننت با تغییر State
تست واکنش کامپوننت نسبت به تعاملات کاربر
چه چیزی رو نمیتونیم تست کنیم ؟
تست نویسی در React خیلی خوب و ضروریه اما نباید هرچیزی رو تست کرد!
بریم ببینیم تست نویسی در ری اکت تو چه مواردی کاربرد نداره ..
نیازی به تست عملکرد واقعی نیست:
درواقع نیازی نیست عملکرد واقعی یک تابع رو چک کنیم فقط کافیه اون رو بصورت کلی تست کنیم تا از عملکرد صحیح کلی اون تابع اطمینان حاصل کنیم.
نیازی به تست کتابخانه های خارجی نیست :
اگه از کتابخانه های خارجی و شخص ثالث استفاده میکنید نیازی نیست که شما عملکرد اونارو تست کنید! درحقیقت توسعه دهنده های اون کتابخانه، باید اون کتابخانه رو تست کنن.
مثلا اگه از کتابخانه Axios در ری اکت استفاده میکنید، نیازی نیست برای خود این کتابخانه تست نویسی ری اکت انجام بدید.
اگه درک این موارد براتون سخته، اصلا نگران نباشید چون تو ادامه با ذکر مثال این موارد رو بررسی میکنیم 🙂
تست نویسی در ری اکت
تست نویسی در ری اکت یکی از اون مباحث پیشرفته و خیلی مهم هست که کمتر کسی بهش توجه میکنه!
شاید یکم زمانبر باشه، اما تست نویسی در ریکت باعث میشه از عملکرد صحیح اپیکیشن خودمون اطمینان حاصل کنیم.
تست نویسی در React شامل موارد زیر میشه :
تست رندر کامپوننت
تست تعامل کاربر با یک اِلِمان کامپوننت
تست درست بودن یک ادعا
خب دیگه تئوری صحبت کردن کافیه 🙂 بریم یکم کد ببینیم.
ایجاد یک پروژه ری اکت برای تست نویسی
برای بررسی بهتر تست نویسی در ریکت ، ما میخوایم یک پروژه React ایجاد کنیم.
برای اینکار ، به کمک CRA یا همون create-react-app یک پروژه ری اکتی میسازیم. سپس از کتابخانه Jest در ری اکت کمک میگیریم.
همچنین به کتابخانه react testing library نیاز داریم.
نکته ای که وجود داره این هست که با نصب React ، هر دو این کتابخانه ها برای ما نصب میشن.
اگه به فایل package.json پروژه خودمون مراجعه کنیم، میبینیم که هر 2 پکیج مورد نیاز برای تست نویسی در React بصورت پیشفرض برای ما نصب شده :
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
این مورد تو خط 2 و 3 مشخصه.
مورد بعدی که باید ازش مطمئن بشیم، وجود 2 خط کد زیر در فایل setupTests.js هست :
import '@testing-library/jest-dom';
import '@testing-library/jest-dom/extend-expect';
اگه 2 خط کد بالا، تو فایل setupTests.js وجود داشت عالیه. حالا باید بخش scripts در فایل package.json رو بصورت زیر تغییر بدیم ( اضافه کردن کامند تست در ری اکت ) :
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --watchAll --coverage",
"eject": "react-scripts eject"
},
خط 4 تیکه کد بالا باعث میشه تست ما درحالت اجرا نمایش داده بشه و بصورت کامل پوشش داده بشه.
برای تغییر پوشش دادن تست توی Jest میتونیم کد زیر رو اضافه کنیم : ( برای پوشش 70% )
"jest": {
"coverageThreshold": {
"global": {
"lines": 70
}
}
}
خب دیگه تنظیمات Jest و تست نویسی در ری اکت تموم شد 🙂 بریم که یه تست بنویسیم . . .
تست نویسی در React چطوریه ؟
فرض کنیم کامپوننت زیر رو داریم و میخوایم براش تست نویسی انجام بدیم:
const FirstTest = () => {
return (
First test
)
}
بنظر شما برای کامپوننت بالا چه تستی باید بنویسیم ؟!
تو کامپوننت بالا ما میتونیم این مورد رو تست کنیم که آیا اِلِمان h2 رندر میشه یا خیر! ( تو خط 4 )
حالا این سوال پیش میاد که برای اِلِمان h2 چطور تست نویسی انجام بدیم ؟
ما میتونیم تست نویسی در ریکت رو در پوشه –tests– داخل پوشه src قرار بدیم.
فایل تست ما باید پسورد زیر رو داشته باشه :
.test.js/jsx
درواقع اجرا کننده تست ( test runner ) فقط همین فایل هارو شناسایی و اجرا میکنه.
الان شاید سوال برامون پیش بیاد که یک فایل تست، چه شکلیه ؟
تیکه کد زیر فایل FirstTest.test.jsx هست که بالاتر کامپوننتش رو نوشته بودیم :
import { render, screen } from '@testing-library/react'
import FirstTest from '../components/FirstTest';
test("Example 1 renders successfully", () => {
render( );
const element = screen.getByText(/first test/i);
expect(element).toBeInTheDocument();
})
در مرحله اول از متود ()test استفاده کردیم که یک individual test محسوب میشه. این متود 2 آرگومان ورودی از ما میگیره:
آرگومان اول نام تست هست.
آرگومان دوم یک callBack هست.
تو خط شماره 4 از متود test استفاده کردیم.
حالا باید کامپوننتی که قصد تست کردنش رو داریم، به کمک متود render تست کنیم ( در خط 5 )
حالا به کمک آبجکت screen میتونیم یک اِلِمان رو بگیریم. ( تو این مثال ما اِلِمان h2 رو توی خط 7 گرفتیم )
نکته : ما از regex برای گرفتن اِلِمان خودمون استفاده کردیم ( تو خط 7 )
حالا باید یک ادعا بسازیم. ما میخوایم ادعا کنیم که اِلِمان ما توی صفحه render شده.
این ادعا رو توی خط 9 به کمک expect ایجاد کردیم . این ادعا با موفقیت انجام شده ( pass شده )
تو مثال بالا ما فقط این ادعا رو مطرح کردیم که اِلِمان h2 توی صفحه رندر شده، اما میتونیم ادعا های بیشتری هم بکنیم.
تست نویسی در ریکت برای دیتاهای دریافتی از سرور
بیاید سناریویی رو در نظر بگیریم که داریم از Back-End اطلاعاتی رو دریافت میکنیم و نمایش میدیم :
import React from 'react'
const TestWithMockData = ({data}) => {
return (
{data.map(item => (
-
{item.id}
{item.first_name},
{item.last_name},
{item.email}
))}
)
}
export default TestWithMockData
تو کامپوننت بالا ما داریم یکسری data رو بصورت Props دریافت میکنیم و نمایش میدیم. تست نویسی در چنین شرایطی ( که Props داریم ) مستلزم ساخت مقداری Data تستی ( Mock Data ) هست.
( اگه با Props آشنا نیستید، پیشنهاد میکنم مقاله Props در ریکت رو مطالعه کنید )
این Data ها دقیقا مشابه Data های Back-End هستن :
const mockData = [
{
"id": 1,
"first_name": "Fletcher",
"last_name": "McVanamy",
"email": "mmcvanamy0@e-recht24.de",
"age": 30
},
{
"id": 2,
"first_name": "Clarice",
"last_name": "Harrild",
"email": "charrild1@dion.ne.jp",
}
]
خب بریم که تست نویسی در React برای کامپوننت بالایی رو انجام بدیم ..
این تست رو توی تیکه کد زیر میشه دید :
test("List renders successfully", () => {
render( )
expect(screen.getByText(/fletcher/i)).toBeInTheDocument();
})
تست نویسی برای Data های ساختگی با سناریوی متفاوت ( Mock Data )
بیاید کامپوننت بالا رو با سناریوی متفاوتی در نظر بگیریم. تو کامپوننت زیر یک Props به اسم displayUnorderdList داریم که رندر شرطی رو برامون انجام میده.
همچنین برای سن بیشتر از 50 سال، عبارت senior و سن کمتر از 50 عبارت Not Senior رو نمایش میدیم :
import React from 'react'
const TestWithMockData = ({data, displayUnorderedList, handleClick}) => {
return (
{displayUnorderedList ?
{data.map(item => (
-
{item.id}
{item.first_name},
{item.last_name},
{
console.log("email link clicked")
handleClick()
}}>{item.email}
{item.age > 50 ? 'Senior' : 'Not senior'}
))}
:
{data.map(item => (
-
Last name: {item.last_name}
))}
}
)
}
export default TestWithMockData
ما برای کامپوننت بالا ( TestWithMockData )َ تست نویسی انجام دادیم. پس اگه به کنسول خودمون نگاهی بندازیم با صحنه زیر مواجه میشیم :
اگه به بخش Uncovered نگاهی بندازیم، میبینیم که نوشته خط 9 توسط تست پوشش داده نشده. و تست ما ناموفق بوده چون نتونسته متن fletcher رو پیدا کنه (این متن رو توی تست بهش داده بودیم که پیدا کنه ).
برای اینکه بتونیم تموم بخش کامپوننت رو پوشش بدیم باید بصورت زیر تست بنویسیم :
test("Ordered list renders", () => {
render( )
expect(screen.getByText(/McVanamy/i)).toBeInTheDocument()
})
خب حالا تست ما کل کامپوننت رو پوشش میده 🙂
تو تصویر زیر نتیجه رو میشه دید :
البته باتوجه به عکس بالا میشه فهمید که هنوز خط 15 پوشش داده نشده. پس باید Mock Data خودمون رو بصورت زیر تغییر بدیم تا یک سن بیشتر از 50 داشته باشیم :
{
"id": 3,
"first_name": "Amby",
"last_name": "Emmer",
"email": "aemmer2@buzzfeed.com",
"age": 67
}
حالا دیگه تمومه و کل کامپوننت ما تحت پوشش تست ما هست 🙂
تست نویسی در ری اکت برای تعاملات کاربر ( User Interactions )
یکی از مهمترین بخش های تست نویسی در React یا هر کتابخانه دیگه، تست نویسی برای رفتار های کاربر هست.
ما میتونیم از کتابخانه user-event در ری اکت برای شبیه سازی رفتار کاربر استفاده کنیم.
به کمک این کتابخانه میتونیم رفتار های کاربر مثل کلیک، هاور، تایپ و .. رو شبیه سازی کنیم تا در نهایت تست نویسی در ری اکت رو انجام بدیم.
برای استفاده از کتابخانه user-event باید این کتابخانه رو به کمک دستور زیر نصب کنیم :
npm install --save-dev @testing-library/user-event
ما میتونیم از این کتابخانه برای شبیه سازی رفتار های کاربر کمک بگیریم. ( مثل هر رفتاری که کاربر میتونه با Button و Input ها داشته باشه ) البته که آموزش کامل این کتابخانه رو بزودی تو وبسایت فِرانت اِندی منشر میکنیم 🙂
تست نویسی در ریکت برای تغییرات State !
ما میتونیم برای تغییرات State کامپوننت خودمون تست نویسی انجام بدیم.
با توجه به اینکه تغییر State باعث re-render کامپوننت میشه، تست نویسی برای تغییر State خیلی ضروریه ( این موارد رو در آموزش هوک useEffect در ری اکت مطرح کردیم )
بریم یک سناریو داشته باشیم.
تو کامپوننت زیر، به محض اولین Render کامپوننت، ما State خودمون رو مقداردهی میکنیم ( به کمک useState ) :
const TestingStateChange = () => {
const [loaded, setLoaded] = useState(false)
useEffect(() => {
setLoaded(true)
}, [])
return (
{loaded && Page Loaded
}
)
}
برای کامپوننت بالا میتونیم از تست زیر استفاده کنیم که هم بخش HTML رو پوشش میده و هم useEffect مارو :
test("Testing page load", () => {
render( )
expect(screen.getByText(/page loaded/i)).toBeInTheDocument();
})
از تست بالا، برای تست نویسی در React برای بررسی تغییرات State استفاده میکنیم.
انواع تست در ری اکت کدامند ؟
تو کتابخانه ری اکت ما انواع مختلف تست داریم که میتونیم با توجه به نیازمون یکی از این تست هارو انتخاب و استفاده کنیم.
Unit Tests :
تمرکز Unit Test در ری اکت بر اجزای واحد اپیکیشن ما مثل توابع یا کامپوننت های جزئی هست. درحقیقت unit test ها کوچکترین بخش های اپیکیشن مارو تست میکنن.
ما از Unit Tests برای این استفاده میکنیم تا مطمئن بشیم که هر جز اپیکیشن ما به خوبی و درستی کار میکنه.
Integration Tests :
بطور خلاصه Integration Tests در ری اکت کمک میکنه تا عملکرد چند بخش که باهمدیگه در تعامل هستن رو تست کنیم.
بطور مثال تو یک صفحه چندین کامپوننت مختلف داریم که این کامپوننت ها با همدیگه در ارتباط هستن. با این تست میتونیم مطمئن بشیم که این کامپوننت ها با همدیگه به درستی تعامل و ارتباط دارن.
Functional Tests :
این نوع تست که معمولا زیرمجموعه Integration Tests هم شناخته میشه، روی خروجی یک عمل تمرکز داره و اجازه میده خروجی یک عمل مشخص در اپیکیشن خودمون رو تست کنیم.
End-To-End Tests :
تست های E2E یا همون End To End شرایط واقعی استفاده از اپیکیشن توسط کاربر رو شبیه سازی میکنن و اجازه میدن کل اپیکیشن ما در شرایط واقعی تست بشه. اینجوری میتونیم رفتار کاربر واقعی از لحظه ورود رو شبیه سازی کنیم.
Snapshot Testing :
این نوع تست ( Snapshot Testing ) به ما اجازه میده خروجی رندر شده یک کامپوننت رو با اسکرین شاتی که این تست در اختیار ما میزاره، مقایسه کنیم. اینجوری میتونیم تفاوت و خروجی های ناخواسته و اشتباه رو تشخیص بدیم.
Static Analysis :
البته که از لحاظ فنی Static Analysis تست نویسی به حساب نمیاد ولی ما میتونیم به کمک ابزار هایی مثل Eslint کد ری اکت خودمون رو تست کنیم تا مشکلاتش رو پیدا و رفع کنیم.
ابزار های تست نویسی در React کدامند ؟
ابزار های مختلفی برای تست نویسی در React وجود دارن ولی بهترینشون عبارتند از :
Jest :
Jest یک کتابخانه تست نویسی محبوب در ری اکت هست که جامعه آماری بالا و عملکرد فوق العاده ای داره.
React Testing Library :
یک کتابخانه محبوب برای تست نویسی در React که تمرکز اصلیش روی رفتار اپیکیشن هست.
Enzyme :
یک کتابخانه محبوب برای تست نویسی در ریکت که درحال حاضر 1.5 میلیون دانلود هفتگی داره.
Cypress :
کتابخانه تست نویسی محبوب که برای تست های E2E عملکرد خیلی خوبی داره.
هدف ما از تست نویسی چیست ؟
قبل از شروع تست نویسی، باید هدف ما از نوشتن تست مشخص و واضح باشه.
بطور مثال ما میخوایم عملکرد یک تابع رو تست کنیم یا Flow ( رفتار ) کاربر رو شبیه سازی کنیم ؟
زمانیکه هدف ما از Testing در ریکت مشخص نباشه، طبیعتا نمیتونیم تست های خوبی بنویسیم.
انتخاب ابزار مناسب برای تست نویسی در ری اکت
هرچقدر هم که تست های خوبی بنویسیم اما ابزار تست مناسبی نداشته باشیم، نمیتونیم نتیجه خوبی از تست های خودمون بگیریم.
ما درمورد ابزار های تست نویسی در ریکت صحبت کردیم و باید با توجه به نیاز خودمون یکی از این ابزارهارو با توجه به ویژگی هایی که دارن انتخاب کنیم.
باید از مهمترین بخش های اپیکیشن شروع کنیم !
تو پروسه تست نویسی بهتره که از بخش های حیاتی اپیکیشن شروع کنیم تا مطمئن باشیم که Base و اساس پروژه ما داره درست کار میکنه. بعد از اون میتونیم سراغ بخش های دیگه با حساسیت کمتر بریم.
جمع بندی
تست نویسی در ری اکت یک بحث طولانی و شاید کمی پیچیده باشه. ما امروز سعی کردیم به ساده ترین شکل ممکن توضیح بدیمش.
تو مقاله های بعدی درمورد کتابخانه ها و ابزار های تست نویسی در ری اکت صحبت میکنیم تا به ساده ترین شکل ممکن توانایی تست نویسی در React رو داشته باشیم 🙂
تست نویسی به ما اجازه میده عملکرد اجزای مختلف اپیکیشن خودمون رو تست کنیم و اطمینان حاصل کنیم که همه چیز داره درست کار میکنه.
بله ما میتونیم برای اپیکیشن های خودمون در React تست نویسی انجام بدیم.
درباره احمد احمدنژاد
من یه برنامه نویس و توسعه دهنده وب هستم که عاشق دنیای صفر و یکم❤️
نوشتههای بیشتر از احمد احمدنژاد3 دیدگاه
به گفتگوی ما بپیوندید و دیدگاه خود را با ما در میان بگذارید.
خيلي جامع و مفید بود . ممنون
خوشحالم که برات مفید واقع شده 🙂
موفق باشی
سپاس