המחבר בחר את Vets Who Code לקבל תרומה כחלק מתוכנית כתיבה למענה עמותות.
הקדמה
השגת כיסוי בדיקות יציב הוא חיוני לבניית ביטחון באפליקציה האינטרנטית שלך. Jest הוא רץ בדיקות JavaScript שמספק משאבים לכתיבה והרצת בדיקות. ספריית בדיקות React מציעה סט של עזרים לבדיקות שמבוססות על אינטראקציות משתמש ולא על פרטי יישום הרכיבים. גם Jest וספריית בדיקות React מגיעים מוכנים מראש עם Create React App ונמצאים תחת המנחה שבדיקת האפליקציות צריכה לדמות את אופן השימוש בתוכנה.
במדריך זה, תבדוק קוד אסינכרוני ואינטראקציות בפרוייקט דוגמא הכולל מגוון אלמנטים של ממשק משתמש. תשתמש ב-Jest כדי לכתוב ולהריץ בדיקות יחידה, ותממש ספריית בדיקות React כספריית DOM (Document Object Model) עוזרת לטיפול באינטראקציה עם רכיבים.
דרישות מוקדמות
כדי להשלים את המדריך הזה, תצטרך:
-
Node.js גרסה 14 או יותר גדולה מותקנת על המחשב המקומי שלך. כדי להתקין את Node.js על macOS או Ubuntu 18.04, עקוב אחר השלבים ב- איך להתקין את Node.js וליצור סביבת פיתוח מקומית ב-macOS או בקטע ה- התקנה באמצעות PPA של איך להתקין את Node.js על Ubuntu 18.04.
-
גרסת
npm
5.2 או גבוהה יותר על המחשב המקומי שלך, אשר תזדקק להשתמש ב-Create React App וב-npx
בפרוייקט הדוגמה. אם לא התקנת אתnpm
לצדNode.js
, עשה זאת כעת. עבור Linux, השתמש בפקודהsudo apt install npm
.- כדי שחבילות
npm
יעבדו במדריך זה, התקן את החבילהbuild-essential
. עבור Linux, השתמש בפקודהsudo apt install build-essential
.
- כדי שחבילות
-
Git מותקן על המחשב המקומי שלך. ניתן לבדוק האם Git מותקן על המחשב שלך או לעבור דרך תהליך ההתקנה עבור מערכת ההפעלה שלך באמצעות איך להתקין Git על Ubuntu 20.04.
-
יכולת בקוד React, אותה תוכל לפתח עם סדרת המדריכים איך לכתוב קוד ב־React.js. מאחר והפרויקט הדגמה מופעל עם Create React App, אין צורך להתקין אותו בנפרד.
-
יכולת קלה עם Jest כמרוץ או סביבה לבדיקות יכולה להיות מועילה אך אינה דרושה. מאחר ו־Jest מותקן מראש עם Create React App, אין צורך להתקין אותו בנפרד.
שלב 1 — הגדרת הפרויקט
בשלב זה, תבצעו העתקת פרויקט דוגמה ותפעילו את אוסף הבדיקות. הפרויקט הדוגמתי משתמש בשלושה כלים עיקריים: Create React App, Jest, ו־React Testing Library. Create React App משמש להקמת אפליקציית React דו־צדדית. Jest משמש כמנהל הבדיקות, ו־React Testing Library מספק עזרים לבניית בדיקות סביב התנהגות משתמש.
כדי להתחיל, תעתיקו את פרויקט ה־React App המוכן מ־GitHub. תעבדו עם האפליקציה Doggy Directory, שהיא פרויקט דוגמה המשתמש ב־Dog API לבניית מערכת חיפוש והצגה של אוסף תמונות של כלבים בהתבסס על גזע מסוים.
כדי להעתיק את הפרויקט מ־GitHub, תפתחו את הטרמינל ותריצו את הפקודה הבאה:
תראו פלט דומה לזה:
OutputCloning into 'doggy-directory'...
remote: Enumerating objects: 64, done.
remote: Counting objects: 100% (64/64), done.
remote: Compressing objects: 100% (48/48), done.
remote: Total 64 (delta 21), reused 55 (delta 15), pack-reused 0
Unpacking objects: 100% (64/64), 228.16 KiB | 3.51 MiB/s, done.
שנו אל תיקיית doggy-directory
:
התקינו את תלות הפרויקט:
הפקודה npm install
תתקין את כל תלות הפרויקט המוגדרות בקובץ package.json
.
לאחר התקנת התלות, תוכלו להציג את הגרסה המופעלת של האפליקציה או שתריצו את האפליקציה מקומית באמצעות הפקודה הבאה:
אם בחרתם להפעיל את האפליקציה מקומית, היא תיפתח ב־http://localhost:3000/
. תראו את הפלט הבא בטרמינל:
OutputCompiled successfully!
You can now view doggy-directory in the browser.
Local: http://localhost:3000
On Your Network: http://network_address:3000
לאחר הפעלתה, עמוד הנחיתה של האפליקציה ייראה כמו כך:
התלויות של הפרויקט הותקנו, והאפליקציה כעת רצה. הבא, פתח טרמינל חדש והפעל את הבדיקות עם הפקודה הבאה:
הפקודה npm test
מתחילה את הבדיקות במצב צפיה אינטרקטיבית עם Jest כמנוהל הבדיקות שלו. כאשר במצב צפיה, הבדיקות מריצות מחדש באופן אוטומטי לאחר שינוי בקובץ. הבדיקות ירוצו בכל פעם שתשנה קובץ וידעו אותך אם השינוי עבר את הבדיקות.
לאחר הרצת npm test
לפעם הראשונה, תראה את הפלט הבא בטרמינל:
OutputNo tests found related to files changed since last commit.
Press `a` to run all tests, or run Jest with `--watchAll`.
Watch Usage
› Press a to run all tests.
› Press f to run only failed tests.
› Press q to quit watch mode.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press Enter to trigger a test run.
עכשיו שיש לך את היישום דוגמה ואת סט הבדיקות רצים, תוכל להתחיל בבדיקות בעמוד הנחיתה.
שלב 2 — בדיקת עמוד הנחיתה
בדרך כלל, Jest יחפש קבצים עם הסיומת .test.js
וקבצים עם הסיומת .js
בתיקיות __tests__
. כאשר אתה מבצע שינויים בקבצי הבדיקה הרלוונטיים, הם יזוהו באופן אוטומטי. כאשר מקרי הבדיקה משתנים, הפלט יעדכן באופן אוטומטי. קובץ הבדיקה המוכן עבור פרויקט הדוגמה doggy-directory
מוגדר עם קוד מינימלי לפני שתוסיף פרדיגמות בדיקה. בשלב זה, תכתוב בדיקות כדי לוודא שעמוד הנחיתה של האפליקציה תעלה לפני ביצוע חיפוש.
פתח src/App.test.js
בעורך שלך כדי לראות את הקוד הבא:
A minimum of one test block is required in each test file. Each test block accepts two required parameters: the first argument is a string representing the name of the test case; the second argument is a function that holds the expectations of the test.
בתוך הפונקציה, קיימת שיטת render
שמספקת React Testing Library לעיבוד הרכיב שלך לתוך ה- DOM. עם הרכיב שברצונך לבדוק מוצג ב- DOM של סביבת הבדיקה, כעת ניתן להתחיל לכתוב קוד לאמת את הפונקציונליות הצפויה.
תוסיפו בלוק בדיקה לשיטת ה- render
שיבדוק האם הדף הראשי מוצג בדיוק לפני שהופעלו קריאות ל- API או נעשו בחירות. הוסיפו את הקוד המודגש מתחת לשיטת ה- render
:
הפונקציה expect
משמשת כל פעם שברצונך לאמת תוצאה מסוימת, והיא מקבלת ארגומנט יחיד המייצג את הערך שהקוד שלך מייצר. רוב הפונקציות expect
משווקות עם פונקציות matcher כדי לאמת משהו על ערך מסוים. לרוב מהאמינציות הללו, תשתמשו במאמץ נוסף מסופק על ידי jest-dom כדי לבדוק בקלות רבה את האספקטים הנפוצים שנמצאים ב- DOM. לדוגמה, .toHaveTextContent
הוא המאמץ לפונקציית expect
בשורה הראשונה, בזמן ש- getByRole("heading")
הוא הבורר ללכידת האלמנט ב- DOM.
React Testing Library מספקת את האובייקט screen
כדי לגשת בצורה נוחה לשאילתות הרלוונטיות הנדרשות לאמות בסביבת הבדיקה של DOM. כברירת מחדל, מספקת React Testing Library שאילתות שמאפשרות לך לאתר אלמנטים בתוך ה- DOM. קיימות שלושה קטגוריות עיקריות של שאילתות:
getBy*
(השימוש הנפוץ ביותר)queryBy*
(שימוש כאשר נבדקת החסרות של אלמנט מבלי לזרוק שגיאה)findBy*
(שימוש כאשר נבדקת קוד אסינכרוני)
כל סוג שאילתה משרת למטרה מסוימת שתוגדר במהלך המדריך. בשלב זה, תתמקד בשאילתת ה-getBy*
, שהיא סוג השאילתה הנפוץ ביותר. כדי לראות רשימה מפורטת של השונות של שאילתות, תוכל לבדוק את גליון העבודה של ריאקטגליון המשאבים של שאילתות.
למטה נמצא תמונה עם הערות של דף הנחיתה של ספריית הכלבים המציינות את כל אזור המכיל נתונים שבהם הבדיקה הראשונה (על הצגת דף הנחיתה) מתמקדת בהם:
כל פונקציית expect
מערכת נגד הבא (מוצג בתמונה העם ההערות למעלה):
- אתה מצפה שהאלמנט עם תפקיד הכותרת יהיה לו התאמה חלקית של ספריית הכלבים.
- אתה מצפה שהקלט של הבחירה יהיה עם ערך התצוגה מדויק של בחר גזע.
- אתה מצפה שלכפתור ה-חיפוש יהיה לא מאופשר מאחר ובחירה לא נעשתה.
- אתה מצפה שהתמונה המציינת תהיה נוכחת במסמך מאחר וחיפוש לא בוצע.
כאשר סיימת, שמור את הקובץ src/App.test.js
. מאחר והבדיקות רצות במצב צפיה, השינויים ירשמו אוטומטית. אם השינויים לא נרשמים באופן אוטומטי, עשוי להיות עליך לעצור ולהפעיל מחדש את ערכת הבדיקות.
עכשיו, כאשר אתה מסתכל על הבדיקות שלך בטרמינל, תראה את הפלט הבא:
Output PASS src/App.test.js
✓ renders the landing page (172 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 2.595 s, estimated 5 s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
בשלב זה, כתבת בדיקת תחילתית כדי לאמת את תצוגת הדף הראשית של עמוד הנחיית הכלבים. בשלב הבא, תלמד כיצד לפענח שיחת API מזוייפת לבדיקת קוד אסינכרוני.
שלב 3 — מופעל את שיטת הfetch
בשלב זה, תבקש לבדוק גישה אחת להפעיל את שיטת הfetch
ב-JavaScript. בעוד שישנן דרכים רבות להשיג זאת, המימוש הזה ישתמש בשיטות ה-spyOn
ו-mockImplementation
של Jest.
כאשר אתה תלווה על API חיצוניים, יש סיכוי שה-API שלהם ייפול או ייקח זמן עד שהוא יחזיר תגובה. מסתירת שיטת ה-fetch
מספקת סביבה עקבית וניחושית, נותנת לך יותר ביטחון בבדיקות שלך. מנגנון מסתירת API הוא נחוץ כדי להריץ באופן תקין בדיקות שמשתמשות ב-API חיצוני.
הערה: במאמץ לשמור על פשטות הפרויקט הזה, תסימול של שיטת fetch יתבצע. עם זאת, מומלץ להשתמש בפתרון עוצמתי יותר כמו Mock Service Worker (MSW) כאשר מתבצע תסימול של קוד אסינכרוני עבור קודבייסים גדולים ומוכנים להפקה.
פתח src/mocks/mockFetch.js
בעורך שלך כדי לבדוק איך פעולת השיטה mockFetch
עובדת:
השיטה mockFetch
מחזירה אובייקט שדומה בצורה למה ששיחות של fetch
היו מחזירות בתגובה לקריאות ל- API באפליקציה. שימוש בשיטת mockFetch
נחוץ כדי לבדוק את הפונקציונליות האסינכרונית בשני אזורים של אפליקציית ״מדריך הכלבים״: תיבת הבחירה שממלאה את רשימת הגזעים והקריאה ל- API לקבלת תמונות של כלבים כאשר מבוצעת חיפוש.
סגור את src/mocks/mockFetch.js
. עכשיו שהבנת איך שיטת mockFetch
תשמש בבדיקות שלך, תוכל לייבא אותה לקובץ הבדיקות שלך. הפונקציה mockFetch
תיעבר כארגומנט לשיטת mockImplementation
ואז תשמש כיישום זדוני של API של fetch.
בתוך src/App.test.js
, הוסף את השורות המודגשות כדי לייבא את שיטת mockFetch
:
קטע הקוד הזה יקים ויתפרק את המימוש המזוייף כך שכל בדיקה תתחיל משטח משחק שווה.
jest.spyOn(window, "fetch");
יוצר פונקציה מזויפת שתעקוב אחר קריאות לשיטת fetch
המצורפת למשתנה הגלובלי window ב- DOM.
.mockImplementation(mockFetch);
מקבל פונקציה שתשמש ליישום של השקול המזויף. מכיוון שפקודה זו מחליפה את היישום המקורי של fetch
, היא תופעל בכל פעם שייקרא fetch
בתוך קוד האפליקציה.
כאשר סיימת, שמור את קובץ src/App.test.js
.
כעת, כאשר אתה מסתכל על הבדיקות שלך בטרמינל, תקבל את הפלט הבא:
Output console.error
Warning: An update to App inside a test was not wrapped in act(...).
When testing, code that causes React state updates should be wrapped into act(...):
act(() => {
/* fire events that update state */
});
/* assert on the output */
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
at App (/home/sammy/doggy-directory/src/App.js:5:31)
18 | })
19 | .then((json) => {
> 20 | setBreeds(Object.keys(json.message));
| ^
21 | });
22 | }, []);
23 |
...
PASS src/App.test.js
✓ renders the landing page (429 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 1.178 s, estimated 2 s
Ran all test suites related to changed files.
האזהרה מעדכנת אותך שעדכון במצב התרחש כאשר לא ציפית לכך. מבחינת פלט, הבדיקות גם מעידות על הצלחת הדמייה של שיטת fetch
.
בשלב זה, אתה מדמה את שיטת fetch
ומשתלב עם שיטת בדיקה. למרות שהבדיקה עוברת בהצלחה, עליך עדיין לטפל באזהרה.
שלב 4 — תיקון האזהרה act
בשלב זה, תלמד כיצד לתקן את האזהרה act
שעלתה אחרי השינויים בשלב 3.
האזהרה act
מתרחשת מכיוון שאתה מדמה את שיטת fetch
, וכאשר הרכיב מתקין, הוא בוצע בקריאת API כדי לאחזר את רשימת הגזעים. רשימת הגזעים מאוחסנת במשתנה מצב הממלא את אלמנט ה-option
בתוך קלט הבחירה.
התמונה למטה מציגה איך נראה קלט הבחירה לאחר שהופעלה קריאת ה-API בהצלחה לאחזור את רשימת הגזעים:
האזהרה מתווצגת מכיוון שהמצב מוגדר לאחר שבלוק הבדיקה מסיים לעשות render לרכיב.
כדי לתקן את הבעיה הזו, הוסף את השינויים המסומנים למקרה הבדיקה ב־src/App.test.js
:
המילת המפתח async
מספרת ל־Jest שקוד אסינכרוני רץ כתוצאה מקריאת ה־API שמתרחשת כאשר הרכיב מתקין.
A new assertion with the findBy
query verifies that the document contains an option with the value of husky
. findBy
queries are used when you need to test asynchronous code that is dependent on something being in the DOM after a period of time. Because the findBy
query returns a promise that gets resolved when the requested element is found in the DOM, the await
keyword is used within the expect
method.
כשתסיים, שמור את השינויים שבוצעו ב־src/App.test.js
.
עם ההוספות החדשות, תראה כי האזהרה של act
אינה נמצאת יותר בבדיקות שלך:
Output PASS src/App.test.js
✓ renders the landing page (123 ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 0.942 s, estimated 2 s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
בשלב זה, למדת כיצד לתקן את האזהרה של act
שעשויה להתרחש בעת עבודה עם קוד אסינכרוני. בשלב הבא, תוסיף מקרה בדיקה שני כדי לוודא את הפונקציונליויות האינטראקטיביות של אפליקציית דוגי דירקטורי.
שלב 5 — בדיקת תכונת החיפוש
בשלב האחרון, תכתוב מקרה בדיקה חדש כדי לוודא את תכונת החיפוש והתצוגה של התמונות. תשתמש בפניה רחבה של שאילתות ושיטות API כדי להשיג את כיסוי הבדיקה המתאים.
חזור לקובץ src/App.test.js
בעורך שלך. בראש הקובץ, יבא את ספריית הלייבררי user-event
ואת השיטה האסינכרונית waitForElementToBeRemoved
לתוך קובץ הבדיקות עם הפקודות המודגשות הבאות:
תשתמש בייבואים אלו מאוחר יותר בחלק זה.
לאחר השיטה האיתחולית test()
, הוסף בלוק בדיקת אסינכרונית חדש ועצב את הרכיב App
עם הבלוק הבא של קוד:
עם הרכיב מוצג, כעת אתה יכול להוסיף פונקציות שבודקות את התכונות האינטראקטיביות של אפליקציית ספר הכלבים.
עדיין ב־src/App.test.js
, הוסף את הבלוקים המודגשים שבתוך השיטה השנייה של test()
:
הקטע המודגש למעלה ידמה את הבחירה של גזע כלב ויבדוק כי הערך הנכון מוצג.
השאילתה getByRole
תתפס את האלמנט הנבחר ותשייך אותו למשתנה select
.
בדומה לכיצד תיקנת את אזהרת ה־act
בשלב 4, השתמש בשאילתת findByRole
כדי לחכות להופעת האופציה cattledog
במסמך לפני שתמשיך להצהיב אקציה נוספת.
האובייקט userEvent
שיובא לפני כן ידמה אירועי משתמש רגילים. בדוגמה זו, שיטת selectOptions
מבצעת בחירה באפשרות cattledog
שהמתינו לה בשורה הקודמת.
השורה האחרונה מאמתת כי המשתנה select
מכיל את ערך cattledog
שנבחר למעלה.
הקטע הבא שתוסיף לבלוק test()
ב-Javascript יפעיל את בקשת החיפוש למצוא תמונות כלבים על סמך הגזע שנבחר ויאמת את קיומו של מצב טעינה.
הוסף את השורות המודגשות:
השאילתה getByRole
מאתרת את כפתור החיפוש ומשבצת אותו למשתנה searchBtn
.
הבודק toBeDisabled
matcher של jest-dom יאמת כי כפתור החיפוש אינו מנוטרל כאשר נבחרת אפשרות גזע.
השיטה click
על אובייקט ה-userEvent
מדמה לחיצה על כפתור החיפוש.
הפונקציה waitForElementToBeRemoved
הפונקציה העזר המסונכרנת שיובאה לפני תחכה להופעה ולהיעלמות של ההודעה Loading בזמן ביצוע של קריאת API חיפוש. queryByText
בתוך קולבאק של waitForElementToBeRemoved
תבדוק את חוסר ההופעה של אלמנט מבלי לזרוק שגיאה.
התמונה למטה מציגה את מצב הטעינה שיוצג בעת ביצוע חיפוש:
באשף הבא, הוסף את הקוד ה-Javascript הבא כדי לוודא את התצוגה של התמונה וספירת התוצאות:
השאילתה getAllByRole
תבחר את כל התמונות של הכלב ותשייך אותם למשתנה dogImages
. הגרסה *AllBy*
של השאילתה מחזירה מערך המכיל אלמנטים מרובים התואמים לתפקיד המסופק. הגרסה *AllBy*
שונה מהגרסה ByRole
, שיכולה להחזיר רק אלמנט יחיד.
המימוק של fetch
הכיל שני כתובות URL של תמונה בתגובה. בעזרת התאמת האורך toHaveLength
של Jest, תוכל לוודא שישנן שתי תמונות המוצגות.
השאילתה getByText
תבדוק כי ספירת התוצאות המתאימה מופיעה בפינה הימנית.
שתי אסרציות באמצעות המתאימות toHaveAccessibleName
תאמת כי הטקסט המורשה הוא מקושר עם התמונות האישיות.
A completed search displaying images of the dog based on the breed selected along with the number of results found will look like this:
כאשר אתה משלב את כל החלקים של קוד ה-Javascript החדש, קובץ ה־App.test.js
ייראה כמו זה:
שמור את השינויים שנעשו בקובץ src/App.test.js
.
כאשר אתה בודק את הבדיקות שלך, הפלט הסופי בטרמינל יכיל כעת את הפלט הבא:
Output PASS src/App.test.js
✓ renders the landing page (273 ms)
✓ should be able to search and display dog image results (123 ms)
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 4.916 s
Ran all test suites related to changed files.
Watch Usage: Press w to show more.
בשלב הסופי הזה, הוספת בדיקה שמאמת את פונקציות החיפוש, הטעינה והתצוגה של אפליקציית ה-Doggy Directory. עם הטענה הסופית שנכתבה, אתה עכשיו יודע שהאפליקציה שלך עובדת.
מסקנה
במהלך המדריך הזה, כתבת תרחישי מבחן באמצעות Jest, ספריית בדיקות ה-React Testing והתאמתיות jest-dom. בנייה באופן תרשים, כתבת נבחנים על פי איך משתמש פועל עם ה-UI. גם למדת על ההבדלים בין שאילתות ה-getBy*
, findBy*
ו- queryBy*
וכיצד לבדוק קוד אסינכרוני.
כדי ללמוד עוד על הנושאים שנזכרו לעיל, ראה את התיעוד הרשמי של Jest, ספריית בדיקות ה-React Testing, ו-jest-dom. תוכל גם לקרוא את Common Mistakes with React Testing Library של Kent C. Dodd כדי ללמוד על הפרקטיקות הטובות בעת עבודה עם ספריית בדיקות ה-React Testing. למידע נוסף על שימוש בבדיקות snapshot באפליקציית React, ראה איך לכתוב בדיקות Snapshot.