Playwright Locators – מדריך מלא לאיתור אלמנטים בבדיקות אוטומטיות
איך לאתר כפתורים, שדות טופס, טקסטים ורכיבים דינמיים באמצעות Playwright Locators, לכתוב בדיקות E2E יציבות ולהימנע מתקלות שנגרמות מסלקטורים לא אמינים.
- מהו Locator ב־Playwright וכיצד הוא פועל.
- מה ההבדל בין getByRole, getByText, getByLabel ו־CSS Selectors.
- כיצד לאתר אלמנטים בתוך אזורים ספציפיים בעמוד.
- איך לעבוד עם רשימות, טבלאות, רכיבים חוזרים ותוכן דינמי.
- כיצד להשתמש ב־filter, ב־hasText וב־has לצמצום תוצאות.
- איך להתמודד עם Strict Mode, המתנה לאלמנטים ובדיקות לא יציבות.
- אילו שיטות מומלצות כדאי ליישם בפרויקטים אמיתיים.
1. מה הם Playwright Locators?
בבדיקות אוטומטיות של ממשקי משתמש, אחד האתגרים המרכזיים הוא לזהות את האלמנט שאיתו הבדיקה צריכה לעבוד. לדוגמה, בדיקת התחברות צריכה למצוא את שדה שם המשתמש, את שדה הסיסמה ואת כפתור ההתחברות. בדיקת רכישה צריכה לזהות מוצר מסוים, את המחיר שלו ואת כפתור ההוספה לעגלה.
Locator ב־Playwright הוא מנגנון לאיתור אלמנטים בעמוד אינטרנט. באמצעותו אפשר למצוא רכיב, לבצע עליו פעולה ולבדוק את מצבו. Locator אינו רק דרך לכתוב CSS Selector, אלא ממשק שמספק יכולות כמו איתור לפי תפקיד נגישות, טקסט, תווית, מאפיינים, סינון והמתנה אוטומטית.
לדוגמה, אם בעמוד קיים כפתור עם הכיתוב "התחברות", אפשר לאתר אותו כך:
const loginButton = page.getByRole('button', {
name: 'התחברות'
});
await loginButton.click();
הקוד מחפש כפתור לפי תפקידו ושמו הנגיש. לאחר מכן Playwright מנסה להמתין עד שהכפתור יהיה זמין לפעולה, בהתאם לתנאים הנדרשים עבור הפעולה.
אם אתם בתחילת הדרך, כדאי לקרוא גם את מדריך Playwright למתחילים, שמסביר את עקרונות העבודה עם הכלי.
2. מדוע בחירת Locator נכונה חשובה כל כך?
בדיקה אוטומטית יכולה להיכשל גם כאשר המערכת תקינה. אחת הסיבות הנפוצות היא שהבדיקה מסתמכת על מזהה, מבנה HTML או מיקום בעמוד שהשתנו בעקבות עדכון ממשק המשתמש.
נניח שהקוד המקורי כולל את הכפתור הבא:
<button class="btn-primary">התחברות</button>
אפשר לאתר אותו באמצעות CSS:
await page.locator('.btn-primary').click();
אבל אם מפתח ישנה את המחלקה ל־btn-main, הבדיקה עלולה להיכשל, אף שהכפתור עדיין מופיע ומתפקד כרגיל.
לעומת זאת, כאשר המטרה היא לאתר כפתור שהמשתמש מזהה כ"התחברות", ניתן להעדיף:
await page.getByRole('button', {
name: 'התחברות'
}).click();
גישה זו מבטאת טוב יותר את ההתנהגות שהמשתמש מצפה לה. עם זאת, גם שם הכפתור יכול להשתנות בעקבות שינוי מוצר או שפה. לכן אין Locator אחד שמתאים לכל מצב; הבחירה תלויה במבנה העמוד, בנגישות שלו ובמטרה העסקית של הבדיקה.
העדיפו Locator שמתאר את האלמנט מנקודת המבט של המשתמש. כאשר אין דרך אמינה לעשות זאת, השתמשו במזהה בדיקה ייעודי כמו data-testid.
3. getByRole – בחירה לפי תפקיד נגישות
getByRole היא אחת הדרכים המומלצות לאיתור אלמנטים ב־Playwright. היא מאפשרת לחפש רכיבים לפי תפקידם, למשל button, link, textbox, checkbox או heading, ובדרך כלל גם לפי השם הנגיש שלהם.
לדוגמה, עבור הממשק הבא:
<button>שמירת שינויים</button>
<a href="/profile">הפרופיל שלי</a>
<h1>פרטי חשבון</h1>
אפשר לכתוב את הבדיקות הבאות:
await page.getByRole('button', {
name: 'שמירת שינויים'
}).click();
await page.getByRole('link', {
name: 'הפרופיל שלי'
}).click();
await expect(
page.getByRole('heading', {
name: 'פרטי חשבון'
})
).toBeVisible();
הדוגמאות משתמשות ב־expect מתוך @playwright/test. יש לוודא שהייבוא המתאים קיים בקובץ הבדיקה.
התאמה מדויקת באמצעות exact
כאשר יש כמה רכיבים ששמותיהם דומים, אפשר להגדיר התאמה מדויקת:
page.getByRole('button', {
name: 'שמירה',
exact: true
});
ללא exact, התאמת שם עשויה להיות חלקית. לדוגמה, חיפוש בשם "שמירה" עלול להתאים גם ל"פעולת שמירה". התאמה מדויקת מצמצמת את הסיכון לבחירת רכיב לא נכון.
מתי להשתמש ב־getByRole?
- כפתורים ופעולות בממשק.
- קישורים לניווט.
- כותרות ותיבות סימון.
- שדות טופס בעלי תפקיד ושם נגישים תקינים.
- בדיקות שמטרתן לוודא שהממשק נגיש ושאפשר לזהות את הפעולות בו.
אם רכיב חסר שם נגיש תקין, ייתכן ש־getByRole לא יאתר אותו בדרך המצופה. זה עשוי להצביע על בעיית נגישות בממשק עצמו ולא רק על בעיה בבדיקה.
4. getByText – איתור אלמנטים לפי טקסט
getByText מאפשר למצוא רכיב לפי הטקסט שמופיע בו. הוא שימושי להודעות הצלחה, הודעות שגיאה, תיאורי מוצר וטקסטים אחרים המוצגים למשתמש.
await expect(
page.getByText('ההזמנה נשמרה בהצלחה')
).toBeVisible();
await expect(
page.getByText('לא נמצאו תוצאות', {
exact: true
})
).toBeVisible();
חשוב להבחין בין איתור טקסט לבין איתור פעולה. אם המטרה היא ללחוץ על כפתור, עדיף בדרך כלל getByRole עם שם הכפתור, ולא חיפוש כללי אחר טקסט שעשוי להופיע גם באזורים אחרים.
לדוגמה, הביטוי "המשך" יכול להופיע בכפתור, בהסבר או בכותרת. Locator שמבוסס על טקסט בלבד עשוי להיות פחות חד־משמעי.
טקסט חלקי לעומת טקסט מדויק
כאשר משתמשים בהתאמה שאינה מדויקת, Playwright עשוי למצוא טקסט המכיל את הביטוי המבוקש. כאשר נדרשת התאמה מלאה, אפשר להגדיר exact: true.
// התאמה שעשויה להיות חלקית
page.getByText('ההזמנה');
// התאמה מדויקת
page.getByText('ההזמנה', {
exact: true
});
בחירת האפשרות הנכונה תלויה בשאלה אם הטקסט המלא צפוי להיות קבוע, ואם ייתכנו כמה מופעים שלו באותו עמוד.
5. getByLabel – איתור שדות טופס לפי התווית
getByLabel מתאים לשדות טופס שמקושרים לתווית ברורה. במקום לאתר שדה באמצעות class או מבנה HTML, ניתן לאתר אותו באמצעות השם שהמשתמש רואה או שהטכנולוגיה המסייעת מזהה.
לדוגמה:
<label for="email">כתובת אימייל</label>
<input id="email" type="email">
<label for="password">סיסמה</label>
<input id="password" type="password">
הבדיקה יכולה למלא את השדות כך:
await page.getByLabel('כתובת אימייל')
.fill('qa@example.com');
await page.getByLabel('סיסמה')
.fill('ExamplePassword123');
getByLabel יכול לעבוד גם עם מנגנוני תווית נתמכים אחרים, לרבות תוויות שמקושרות באמצעות aria-labelledby. כאשר שדה אינו מקושר לתווית כראוי, כדאי לשקול לתקן את הנגישות שלו.
6. getByPlaceholder – איתור לפי טקסט מציין מקום
Placeholder הוא הטקסט שמופיע בתוך שדה ריק, למשל "הקלידו כתובת אימייל". Playwright מאפשר לאתר שדה לפי הטקסט הזה:
await page.getByPlaceholder(
'הקלידו כתובת אימייל'
).fill('qa@example.com');
הגישה פשוטה ונוחה, אך חשוב לזכור ש־placeholder אינו תחליף לתווית נגישה. בנוסף, הטקסט עשוי להשתנות בעקבות עיצוב, תרגום או שינוי חוויית המשתמש.
אם קיימת תווית מתאימה, בדרך כלל עדיף להשתמש ב־getByLabel. השתמשו ב־getByPlaceholder כאשר זהו המאפיין המתאים ביותר לזיהוי השדה בממשק.
7. getByTestId – איתור באמצעות מזהה בדיקה
לפעמים רכיב מורכב אינו כולל שם נגיש ברור, או שקיימים כמה רכיבים דומים שקשה להבחין ביניהם באמצעות טקסט. במקרים כאלה ניתן להוסיף לאלמנט מזהה בדיקה ייעודי, למשל data-testid.
<button data-testid="submit-order">
אישור הזמנה
</button>
לאחר מכן אפשר לאתר את הכפתור כך:
await page.getByTestId('submit-order').click();
ברירת המחדל של Playwright היא להשתמש במאפיין data-testid. ניתן לשנות את המאפיין באמצעות הגדרת testIdAttribute בתצורת ה־Playwright, אם הפרויקט משתמש בשם אחר.
מזהי בדיקה יכולים להיות יציבים מאוד, אבל הם דורשים תיאום בין צוות הפיתוח לצוות הבדיקות. כדאי להשתמש בשמות משמעותיים שמייצגים את תפקיד הרכיב ולא את מיקומו הזמני במסך.
8. CSS Selectors ו־page.locator
Playwright תומך ב־CSS Selectors ובמנגנוני איתור נוספים באמצעות page.locator. זו אפשרות גמישה במיוחד כאשר צריך לאתר אלמנט לפי מאפיין HTML, מחלקה, מזהה או מבנה DOM.
דוגמאות:
// לפי מזהה
page.locator('#email');
// לפי מחלקה
page.locator('.submit-button');
// לפי מאפיין
page.locator('[data-status="active"]');
// לפי סוג שדה
page.locator('input[type="email"]');
CSS מתאים כאשר אין דרך טובה יותר לזהות את הרכיב, או כאשר מאפיין מסוים הוא חלק יציב ומכוון מממשק הבדיקה. עם זאת, סלקטורים ארוכים המבוססים על מבנה DOM פנימי נוטים להיות שבירים.
לדוגמה, סלקטור שמסתמך על מספר שכבות של div ועל מיקום הילד בתוך ההורה עלול להישבר כאשר מתבצע שינוי עיצובי שאינו משפיע על התנהגות המערכת.
| שיטת איתור | מתי מתאימה? | נקודה שחשוב לבדוק |
|---|---|---|
| getByRole | כפתורים, קישורים, כותרות ורכיבים בעלי תפקיד נגיש | שהתפקיד והשם הנגיש נכונים וחד־משמעיים |
| getByText | הודעות, תיאורים וטקסטים המוצגים למשתמש | שהטקסט אינו מופיע בכמה מקומות |
| getByLabel | שדות טופס בעלי תווית | שהשדה מקושר לתווית כראוי |
| getByPlaceholder | שדות עם placeholder ברור | שהטקסט לא משתנה בקלות |
| getByTestId | רכיבים מורכבים או רכיבים ללא זיהוי נוח אחר | שהמזהה קבוע ומתוחזק |
| locator עם CSS | איתור לפי מאפייני HTML או מבנה DOM | שהסלקטור אינו תלוי במבנה שברירי |
9. שילוב כמה Locators באמצעות locator ו־getByRole
בממשקים אמיתיים, לפעמים יש כמה כפתורים בעלי אותו שם. לדוגמה, בכל כרטיס מוצר מופיע כפתור "הוספה לעגלה". כדי להימנע מבחירה בכפתור הלא נכון, מומלץ תחילה לאתר את המוצר הרצוי ולאחר מכן למצוא את הכפתור בתוכו.
נניח שהעמוד כולל שני מוצרים:
<article data-testid="product-card">
<h2>מקלדת אלחוטית</h2>
<button>הוספה לעגלה</button>
</article>
<article data-testid="product-card">
<h2>עכבר אלחוטי</h2>
<button>הוספה לעגלה</button>
</article>
אפשר לאתר את הכרטיס של המקלדת לפי הכותרת ואז לאתר את הכפתור שבתוכו:
const keyboardCard = page
.getByTestId('product-card')
.filter({
has: page.getByRole('heading', {
name: 'מקלדת אלחוטית'
})
});
await keyboardCard.getByRole('button', {
name: 'הוספה לעגלה'
}).click();
כך הבדיקה לא צריכה להניח שכפתור המקלדת הוא הכפתור הראשון בעמוד. היא מזהה קודם את הכרטיס הנכון ופועלת רק בתוכו.
שימו לב: filter עם has מקבל Locator פנימי שהחיפוש שלו מתבצע ביחס לכל רכיב מועמד. לכן ה־Locator הפנימי צריך להיות מוגדר באופן שמתאים להקשר שבו הוא נבדק.
10. filter, hasText ו־hasNotText
המתודה filter מאפשרת לצמצם אוסף של אלמנטים לפי תנאי. היא שימושית במיוחד כאשר קיימים רכיבים חוזרים, כגון שורות טבלה, כרטיסי מוצר, משימות או משתמשים.
סינון לפי טקסט
const completedTask = page
.getByTestId('task-row')
.filter({
hasText: 'הכנת דוח חודשי'
});
await expect(completedTask).toBeVisible();
בדוגמה זו מאתרים שורת משימה המכילה את הטקסט הרצוי. חשוב לוודא שהטקסט ייחודי מספיק, או להוסיף תנאים נוספים במקרה שבו קיימות משימות דומות.
סינון לפי אלמנט פנימי
const activeUsers = page
.getByTestId('user-row')
.filter({
has: page.getByText('פעיל', {
exact: true
})
});
אפשר גם להשתמש ב־hasNotText או ב־hasNot כאשר רוצים להחריג רכיבים שמכילים טקסט או אלמנט מסוים, בתנאי שהלוגיקה מתאימה למבנה העמוד.
שימוש ב־filter בדרך כלל קריא יותר מסלקטור CSS ארוך שמנסה לבטא את כל תנאי האיתור בבת אחת.
11. עבודה עם רשימות וטבלאות
רשימות וטבלאות הן מקור נפוץ לטעויות בבדיקות אוטומטיות, משום שבדרך כלל מופיעים בהן אלמנטים חוזרים. איתור הכפתור הראשון ברשימה אינו בהכרח בחירה נכונה, במיוחד כאשר סדר הרשומות משתנה.
נניח שיש טבלה עם משתמשים ופעולת מחיקה לכל משתמש. במקום ללחוץ על הכפתור הראשון, אפשר לזהות את השורה לפי שם המשתמש:
const userRow = page
.getByRole('row')
.filter({
hasText: 'דנה כהן'
});
await userRow.getByRole('button', {
name: 'מחיקה'
}).click();
אם שם המשתמש עשוי להופיע גם בפרטים אחרים, עדיף לאתר אותו באמצעות תא מוגדר או מזהה יציב של המשתמש. כמו כן, יש לוודא שהשורה שנבחרה היא אכן יחידה.
במקרים שבהם אפשר לזהות את השורה לפי תפקידים נגישים ותוכן הטבלה, getByRole ו־filter עשויים ליצור בדיקה קריאה יותר מאשר שימוש במיקום מספרי.
12. first, last ו־nth – בחירה לפי מיקום
Playwright מאפשר לבחור אלמנט לפי מיקומו בתוצאות של Locator:
const buttons = page.getByRole('button', {
name: 'המשך'
});
await buttons.first().click();
await buttons.last().click();
await buttons.nth(1).click();
האינדקס מתחיל באפס, ולכן nth(1) מתייחס לאלמנט השני.
שיטות אלו מועילות כאשר המיקום הוא חלק מכוון מהתרחיש. עם זאת, אין להשתמש בהן כפתרון אוטומטי ל־Locator עמום. אם הסדר משתנה, הבדיקה עלולה לבצע פעולה על רכיב שגוי.
לפני שימוש ב־first, last או nth, כדאי לשאול אם אפשר לזהות את האלמנט לפי תפקיד, שם, תוכן או הקשר. אם הבחירה לפי מיקום היא אכן הדרישה, מומלץ גם לבדוק את מספר התוצאות ואת המשמעות של הסדר.
13. מהו Strict Mode ולמה הוא גורם לכישלון?
אחת השגיאות הנפוצות בעבודה עם Playwright היא ש־Locator מתאים ליותר מאלמנט אחד כאשר מבצעים עליו פעולה שדורשת יעד יחיד.
לדוגמה, אם קיימים שלושה כפתורים עם השם "עריכה", הקוד הבא עלול להיכשל:
await page.getByRole('button', {
name: 'עריכה'
}).click();
הסיבה היא שפעולת click דורשת לדעת בדיוק על איזה כפתור יש ללחוץ. Playwright לא אמור לבחור שרירותית אחד מכמה רכיבים אפשריים.
הפתרון הוא לצמצם את החיפוש להקשר הנכון:
const profileCard = page
.getByTestId('profile-card')
.filter({
has: page.getByRole('heading', {
name: 'פרטי משתמש'
})
});
await profileCard.getByRole('button', {
name: 'עריכה'
}).click();
אם קיימים כמה כפתורים בעלי שם זהה בתוך אותו אזור, יש להוסיף תנאי מדויק יותר. אין להתעלם משגיאת Strict Mode באמצעות first() בלי להבין איזה רכיב אמור להיבחר.
14. Auto-Waiting – המתנה אוטומטית
Playwright כולל מנגנוני המתנה אוטומטיים. כאשר מבצעים פעולה כמו click או fill, הוא ממתין לתנאים הנדרשים עבור אותה פעולה, למשל שהאלמנט יהיה גלוי, יציב, זמין לאינטראקציה ולא ייחסם על ידי רכיב אחר.
לכן, במקרים רבים אין צורך להוסיף המתנה קבועה לפני כל פעולה.
גישה פחות מומלצת:
await page.waitForTimeout(3000);
await page.getByRole('button', {
name: 'התחברות'
}).click();
גישה טובה יותר היא להמתין למצב שהבדיקה באמת צריכה:
await page.getByRole('button', {
name: 'התחברות'
}).click();
await expect(
page.getByText('התחברת בהצלחה')
).toBeVisible();
הדוגמה השנייה אינה רק ממתינה; היא גם מאמתת תוצאה עסקית. חשוב לזכור ש־Auto-Waiting אינו מבטיח שהשרת סיים כל תהליך או שהמידע העסקי נשמר. יש לבדוק את התנאי שמוכיח שהפעולה הושלמה.
אפשר להעמיק בנושא במאמר איך כותבים בדיקת E2E עם Playwright – מדריך מעשי.
15. Locators מול ElementHandle
בגרסאות מודרניות של Playwright, מומלץ בדרך כלל לעבוד עם Locators במקום להסתמך על ElementHandle בתרחישי בדיקה רגילים.
Locator מתאר כיצד למצוא אלמנט, ו־Playwright יכול לפתור אותו מחדש כאשר נדרשת פעולה. הדבר חשוב בממשקים שבהם רכיבים מתחלפים בעקבות רינדור, עדכון נתונים או שינוי מצב.
לעומת זאת, ElementHandle מתייחס לאלמנט DOM מסוים שכבר אותר. אם האלמנט הוסר מהעמוד או הוחלף, העבודה עם הידית עלולה להיות פחות עמידה לשינויים.
לדוגמה, אפשר לשמור Locator ולבצע איתו פעולות בהמשך:
const saveButton = page.getByRole('button', {
name: 'שמירה'
});
await saveButton.click();
await expect(saveButton).toBeVisible();
שמירת Locator במשתנה אינה מקבעת את האלמנט הפיזי שנמצא ברגע ההגדרה. האיתור מתבצע כאשר משתמשים בו לפעולה או לבדיקה.
16. דוגמה מלאה: בדיקת התחברות באמצעות Locators
נבחן תרחיש התחברות פשוט. הבדיקה תמלא אימייל וסיסמה, תלחץ על כפתור ההתחברות ותבדוק שהמשתמש הגיע לעמוד החשבון.
import { test, expect } from '@playwright/test';
test('התחברות משתמש בהצלחה', async ({ page }) => {
await page.goto('/login');
await page.getByLabel('כתובת אימייל')
.fill('qa@example.com');
await page.getByLabel('סיסמה')
.fill('ExamplePassword123');
await page.getByRole('button', {
name: 'התחברות'
}).click();
await expect(
page.getByRole('heading', {
name: 'החשבון שלי'
})
).toBeVisible();
});
הדוגמה מניחה שהיישום משתמש בנתיב /login, שהשדות מחוברים לתוויות מתאימות ושלאחר התחברות מוצגת כותרת "החשבון שלי". יש להתאים את הנתיבים, פרטי המשתמש ותנאי ההצלחה למערכת הנבדקת. בסביבת בדיקות אמיתית מומלץ להשתמש במשתמש בדיקה ייעודי ולא לשמור סיסמאות אמיתיות בקוד המקור.
מה הופך את הבדיקה הזו לטובה?
- היא משתמשת בתוויות של השדות במקום במיקומים ב־DOM.
- היא מאתרת את כפתור ההתחברות לפי תפקיד ושם.
- היא בודקת תוצאה לאחר הפעולה, ולא מסתפקת בלחיצה.
- היא אינה תלויה בהמתנה קבועה של מספר שניות.
- היא קריאה גם למי שאינו מכיר את מבנה ה־HTML של העמוד.
17. בדיקות Assertions עבור Locators
איתור אלמנט הוא רק חלק מהבדיקה. לאחר שמצאנו את הרכיב, עלינו לוודא שהמערכת נמצאת במצב הצפוי. לשם כך משתמשים ב־Assertions של Playwright Test.
דוגמאות נפוצות:
// בדיקת נראות
await expect(
page.getByText('ההזמנה אושרה')
).toBeVisible();
// בדיקת כותרת
await expect(
page.getByRole('heading', {
name: 'הזמנה חדשה'
})
).toBeVisible();
// בדיקת ערך בשדה
await expect(
page.getByLabel('כתובת אימייל')
).toHaveValue('qa@example.com');
// בדיקת תיבת סימון
await expect(
page.getByRole('checkbox', {
name: 'אני מאשר את התנאים'
})
).toBeChecked();
// בדיקת מספר תוצאות
await expect(
page.getByTestId('product-card')
).toHaveCount(3);
Assertions מסוג expect(locator) מבצעים בדרך כלל המתנה חוזרת עד שהתנאי מתקיים או שפג הזמן שהוגדר. הדבר עוזר להתמודד עם ממשקים דינמיים, שבהם התוכן לא מופיע בהכרח מיד לאחר הפעולה.
18. Locators בתוך iframe
לפעמים רכיב בעמוד מוצג בתוך iframe, למשל טופס חיצוני או רכיב תשלום. במקרה כזה, Locator שמתחיל ב־page אינו בהכרח יכול לאתר ישירות את האלמנטים שבתוך המסגרת.
Playwright מאפשר לעבוד עם FrameLocator:
const paymentFrame = page.frameLocator(
'iframe[title="טופס תשלום"]'
);
await paymentFrame.getByLabel('מספר כרטיס')
.fill('4111111111111111');
זהו מספר כרטיס דוגמה בלבד, ואין להשתמש בו לתשלום אמיתי. במערכת אמיתית יש לפעול לפי הוראות סביבת הבדיקות של ספק התשלום.
חשוב גם להבחין בין iframe רגיל לבין רכיב שמוצג באמצעות Shadow DOM. Playwright תומך ברוב רכיבי Shadow DOM באמצעות מנגנוני האיתור הרגילים, אך קיימים חריגים, למשל סלקטורים מסוימים שאינם חוצים Shadow DOM.
19. טעויות נפוצות בעבודה עם Playwright Locators
טעות 1: שימוש במיקום במקום בזיהוי משמעותי
בחירה באמצעות nth(2) עשויה לעבוד היום, אך להיכשל כאשר מתווסף רכיב חדש לרשימה. עדיף לזהות את האלמנט באמצעות שם, תוכן או הקשר ברור.
טעות 2: הסתמכות על class לצורכי עיצוב
מחלקות CSS רבות מיועדות לעיצוב ולא לזיהוי בבדיקות. שינוי בעיצוב עלול לגרום לכישלון בדיקה שאין לו משמעות עסקית. כאשר אין Locator מתאים המבוסס על תפקיד או תוכן, שקלו data-testid ייעודי.
טעות 3: התעלמות מ־Strict Mode
אם Locator מחזיר כמה אלמנטים במקום אחד, אל תבחרו באופן אוטומטי את הראשון. צמצמו את החיפוש כך שיתאים לרכיב שהבדיקה באמת צריכה.
טעות 4: שימוש בהמתנות קבועות
waitForTimeout אינו תחליף לתנאי הצלחה. העדיפו Assertions או המתנה לאירוע או למצב מוגדר. המתנה קבועה עלולה להאט את הבדיקות ועדיין לא להספיק במערכת איטית.
טעות 5: איתור טקסט שאינו ייחודי
טקסט כמו "עריכה", "המשך" או "אישור" עשוי להופיע כמה פעמים בעמוד. השתמשו בהקשר של הכרטיס, השורה או האזור הרלוונטי.
טעות 6: הנחה ש־Locator מבטיח הצלחה עסקית
Locator יציב יכול לאתר וללחוץ על כפתור בצורה תקינה, אך הפעולה עצמה עדיין עלולה להיכשל בשרת. לאחר פעולות חשובות, בדקו את התוצאה העסקית הצפויה.
20. שיטות מומלצות לבניית Locators יציבים
התחילו מתפקיד נגיש
העדיפו getByRole כאשר תפקיד הרכיב ושמו הנגיש מתארים היטב את הפעולה.
צמצמו את ההקשר
באלמנטים חוזרים, אתרו תחילה כרטיס או שורה ורק אחר כך את הכפתור שבתוכם.
השתמשו ב־Test IDs כשצריך
הגדירו מזהים ייעודיים ויציבים לרכיבים שקשה לאתר בדרך אחרת.
אמתו תוצאות
לאחר כל פעולה חשובה, בדקו את המצב העסקי או את המשוב שהמשתמש אמור לראות.
בנוסף, כדאי להקפיד על שמות ברורים למשתנים, להימנע מסלקטורים ארוכים ומסובכים, ולבנות בדיקות שמתארות התנהגות משתמש ולא פרטים פנימיים של המימוש.
כאשר פרויקט האוטומציה גדל, חשוב גם להגדיר סטנדרטים משותפים לצוות. ניתן להיעזר במדריך איך בונים תהליך אוטומציה לבדיקות תוכנה כדי לחבר בין איכות הבדיקות לבין תהליך העבודה הכולל.
21. איך לבחור Locator בפרויקט אמיתי?
אפשר להשתמש בתהליך החלטה פשוט כאשר כותבים בדיקה חדשה:
- האם מדובר בכפתור, קישור או רכיב עם תפקיד נגיש ברור? התחילו ב־getByRole.
- האם מדובר בשדה טופס עם תווית? נסו getByLabel.
- האם צריך לבדוק הודעה או טקסט שמוצג למשתמש? השתמשו ב־getByText.
- האם יש מזהה בדיקה יציב? השתמשו ב־getByTestId כאשר הוא הפתרון המתאים.
- האם יש כמה רכיבים דומים? צמצמו את החיפוש באמצעות filter והקשר מקומי.
- האם אין אפשרות אחרת? השתמשו ב־CSS Selector ממוקד ויציב.
- האם הפעולה הצליחה מבחינה עסקית? הוסיפו Assertion שבודק את התוצאה הרצויה.
המטרה אינה להימנע לחלוטין מ־CSS או להשתמש תמיד באותה שיטה. המטרה היא לבחור את הדרך הברורה והיציבה ביותר לכל רכיב.
22. Playwright Locators לעומת Selenium ו־Cypress
ל־Playwright, Selenium ו־Cypress יש מנגנוני איתור אלמנטים, אך חוויית העבודה והיכולות סביבם שונות. ב־Playwright, Locator הוא חלק מרכזי בממשק הבדיקה ומשולב עם המתנה אוטומטית, Assertions ושרשור של תנאי איתור.
אם אתם בוחנים איזה כלי מתאים לצוות שלכם, מומלץ לקרוא את המדריכים הבאים:
הבחירה בכלי צריכה להתבסס על דרישות הפרויקט, התשתית הקיימת, שפות התכנות, ניסיון הצוות וצרכי התחזוקה. אין כלי אחד שמבטיח בדיקות יציבות ללא תכנון נכון.
23. תרגול מעשי: כתיבת Locators לממשק משימות
נניח שיש מערכת לניהול משימות ובה שדה להוספת משימה, כפתור יצירה ורשימת משימות קיימות. נסו לכתוב Locators עבור הפעולות הבאות:
אתרו שדה עם התווית "שם המשימה", הזינו "בדיקת מערכת" ולחצו על כפתור "הוספת משימה".
הצגת פתרון לדוגמה
await page.getByLabel('שם המשימה')
.fill('בדיקת מערכת');
await page.getByRole('button', {
name: 'הוספת משימה'
}).click();
בדקו שהמשימה החדשה מופיעה ברשימה לאחר היצירה.
הצגת פתרון לדוגמה
await expect(
page.getByText('בדיקת מערכת', {
exact: true
})
).toBeVisible();
אם יש כמה משימות וכל אחת כוללת כפתור "מחיקה", נסו לאתר את שורת המשימה הנכונה וללחוץ על כפתור המחיקה שבתוכה.
הצגת פתרון לדוגמה
const taskRow = page
.getByTestId('task-row')
.filter({
hasText: 'בדיקת מערכת'
});
await taskRow.getByRole('button', {
name: 'מחיקה'
}).click();
התרגילים מניחים שהממשק כולל את התוויות, השמות ומזהי הבדיקה המתוארים. התאימו את הקוד ל־HTML האמיתי של המערכת וודאו שה־Locator שבחרתם מתאים לאלמנט יחיד כאשר הפעולה דורשת זאת.
24. סיכום: איך כותבים Playwright Locators איכותיים?
Playwright Locators הם אחד המרכיבים החשובים ביותר בכתיבת בדיקות אוטומטיות יציבות. Locator טוב לא רק מוצא אלמנט; הוא מבטא באופן ברור את הכוונה של הבדיקה, מצמצם תלות במבנה פנימי של העמוד ומקל על תחזוקה כאשר הממשק משתנה.
ברוב המקרים כדאי להתחיל ב־getByRole עבור רכיבים אינטראקטיביים, ב־getByLabel עבור שדות טופס וב־getByText עבור תוכן שמוצג למשתמש. כאשר הרכיב אינו מזוהה היטב בדרך זו, אפשר להשתמש ב־getByTestId או ב־CSS Selector מתאים. בממשקים עם רכיבים חוזרים, שילוב של filter והקשר מקומי מאפשר לבחור את האלמנט הנכון בלי להסתמך על סדר מקרי.
חשוב לא פחות לבדוק את התוצאה של הפעולה באמצעות Assertions, להימנע מהמתנות קבועות כשאפשר להמתין למצב מוגדר, ולפתור עמימות ב־Locator במקום לעקוף אותה. שילוב העקרונות האלה יוצר בדיקות קריאות יותר, יציבות יותר וקלות יותר לתחזוקה לאורך זמן.
ממשיכים ללמוד Playwright
כדי להתקדם מאיתור אלמנטים לבניית תהליך בדיקות E2E מלא, המשיכו למדריכים המעשיים באתר TESQA.
איך כותבים בדיקת E2E עם Playwright
לקרוא מאמרים זה נחמד אבל לא יביא אותך לתוצאה שאתה רוצה, בדיוק בשביל זה הכנו עבורך את הקורס הדיגיטלי המהיר, תוך שעתיים וחצי תלמד את תחום הבדיקות ידניות, תוכל להתחיל לעבוד מהבית דרך FIVERR או ולהתכונן נכון לראיונות עבודה שיעזרו לך לצלוח אותם. כנס כאן הקורס ממוקד בבדיקות תוכנה ידניות הנותן בסיס חזק לתחום.
לעבוד מהבית כבודק תוכנה עם FIVERR >> לחץ כאן