Ofer Shapira

איך בודקים race conditions בתוסף דפדפן שסוכן AI משנה?

בפוסט שלי על התרומה ל-real-browser-mcp סיפרתי על תורם שחזר אחרי review עם שני PRs נפרדים ותיקונים למקרים שעלו בבדיקה. המדריך הזה מציע דרך עבודה שאפשר להחיל על תרומה נוספת, בלי להניח שכל שינוי כבר נבדק.

בקצרה

מגדירים מה חייב להישאר נכון כשפעולות חופפות, שולטים בסדר ההשלמה שלהן בבדיקה ומוסיפים תרחיש דפדפן אמיתי. בדיקה שבה שתי קריאות רצות זו אחרי זו אינה מוכיחה שהקוד מתמודד עם חפיפה.

מגדירים את ההבטחה לפני כתיבת הבדיקה

תוסף דפדפן מחבר קוד מקומי למצב שמשתנה מחוץ לו. טאב יכול להיסגר, קבוצה יכולה להשתנות וחיבור debugging יכול להסתיים. לכן צריך לשאול מה חייב להישמר בין תחילת פעולה לסיומה.

בתרומה הציבורית ל-real-browser-mcp הופיע מקרה שבו שתי בקשות לשם קבוצה על אותו טאב יכלו ליצור שתי קבוצות. ב-PR מספר 71 מתואר תיקון שמסדר פעולות לפי טאב וקורא את מצב הטאב מחדש בתוך הנעילה. זו דוגמה קונקרטית לאותו פער: המצב שנקרא לפני ההמתנה עשוי להיות ישן כשהפעולה מתחילה.

יוצרים חפיפה שאפשר לחזור עליה

המחשה סינתטית: שתי בקשות רואות טאב ללא קבוצה. כל אחת מתכוננת ליצור קבוצה. בבדיקה אפשר להחזיק את ההבטחה של הקריאה הראשונה פתוחה, להתחיל את השנייה ורק אז לאפשר לראשונה להסתיים.

בדקו בסוף כמה פעמים הופעלה יצירת קבוצה ומהו המצב הסופי של הטאב. אם הדרישה היא קבוצה אחת, שתי תוצאות "success" אינן מספיקות. בקשו מהסוכן להראות שבאותו סדר פעולות הגרסה הישנה נכשלת והחדשה עומדת בדרישה.

הדוגמה היא דרך בדיקה מוצעת. סדר ההשלמה צריך לייצג את הממשק האמיתי, ולא תחליף שמאפשר רק את סדר הפעולות הנוח לקוד.

נועלים לפי המשאב הנכון

נעילה לפי טאב יכולה להתאים לפעולות על קבוצת הטאב. משאב משותף לכל התוסף דורש חשיבה אחרת. ב-PR מספר 72 מתואר תור אחד לרכישת חיבור debugger ולשימוש בו, כדי למנוע שתי רכישות חופפות עם מעקב חלקי.

הבחירה אינה "להוסיף mutex" באופן גורף. הגדירו אילו פעולות חולקות מצב, מה אפשר להריץ במקביל ומתי משחררים את ההגנה. בדקו גם שגיאה בתוך הפעולה: כישלון צריך להשאיר דרך לפעולה הבאה להתקדם לפי החוזה, ולא לתקוע את התור.

מפרידים בין סימן חיצוני לבעלות על חיבור

לפי תיעוד Chrome, חיבור debugger שנכשל דוחה את ההבטחה. אירוע onDetach מגיע כשהדפדפן מסיים את הסשן, למשל כשהטאב נסגר או כשפותחים DevTools על הטאב המחובר.

הודעה על debugger אחר אינה הוכחה שהתוסף שלכם מחזיק בחיבור. ב-PR מספר 72 מתואר probe שמנסה להבחין בין חיבור שהתוסף עדיין מחזיק אחרי אתחול worker לבין כשל חיבור. יש לבדוק את שני המסלולים מול ההתנהגות שהקוד באמת מממש.

מוסיפים בדיקה בגבול של Chrome

בדיקת יחידה עם mock יכולה לשלוט בחפיפה ולבדוק ספירת קריאות. היא אינה מוכיחה שההרשאות, הודעות הדפדפן ואירועי הסגירה מתנהגים כפי שציפיתם.

כתרחישים מוצעים, בדקו שתי בקשות חופפות, סגירת טאב באמצע פעולה ופתיחת DevTools בזמן סשן. לתוסף שמשתמש ב-debugger נדרשת הרשאת debugger במניפסט. שימוש ב-tabGroups API דורש הרשאת tabGroups. התאימו את ההרשאות למימוש בפועל ואל תוסיפו הרשאה רק כדי לגרום לבדיקה לעבור.

מבקשים דוח שמפריד בין שכבות

בסיום, הסוכן צריך לציין מה נבדק עם mock, מה נבדק בדפדפן, מה היה סדר האירועים ועל איזו גרסה הורצה הבדיקה. אין צורך להבטיח כיסוי לכל מרוץ אפשרי. יש צורך בראיה לתרחיש שהתגלה ובגבולות ברורים למה שעוד דורש בדיקה.

מקורות ופרטים נוספים

ההמלצות ודוגמאות הבדיקה הן דרך עבודה מוצעת. הדיון הציבורי ותיעוד GitHub ו-Chrome נבדקו ב-14.10.2026.

תיקון באג עם בדיקת רגרסיה

שאלות נפוצות

האם Promise.all מספיק כדי לבדוק מרוץ?

הוא יכול להתחיל קריאות חופפות, אך אינו מבטיח שהסדר הבעייתי אכן התרחש. כדאי לשלוט בנקודות ההמתנה ולבדוק את המצב הסופי.

האם צריך לנעול את כל הפעולות בתוסף?

בוחרים הגנה לפי המצב המשותף והדרישה. נעילה רחבה מדי יכולה למנוע מקביליות מותרת, צרה מדי יכולה להשאיר התנגשות.

האם בדיקת mock מחליפה בדיקה בדפדפן?

היא עוזרת לשלוט בסדר האירועים. הרשאות, ניתוקים והתנהגות Chrome דורשים גם בדיקה בגבול האמיתי.