בדיקות E2E עם Selenium WebDriver לאתרי אינטרנט
השחרור מתעכב בשלושה ימים עקב בדיקות רגרסיה ידניות. כל שינוי בממשק המשתמש שובר תרחישים ישנים, והצוות מבזבז שעות על בדיקות חוזרות. בדיקות לא יציבות מערערות את האמון באוטומציה: בדיקות שעברו אתמול נכשלות היום ללא סיבה נראית לעין, ומפתחים מבזבזים זמן על ניפוי שגיאות. אנו מציעים ליישם בדיקות E2E עם Selenium WebDriver — זה מקצר את הרגרסיה משלושה ימים לשעה אחת ומספק יציבות של 99%.
Selenium הוא התקן הוותיק ביותר לאוטומציה של דפדפנים. תומך בכל הדפדפנים המרכזיים, בכל שפות התכנות, ומשתלב עם TestNG, JUnit ו-pytest. הוא נבחר כאשר נדרשת תאימות בין דפדפנים דרך Selenium Grid או שקיימת תשתית legacy. אנו משתמשים ב-Selenium 4 עם מצב headless, המאפשר להריץ בדיקות על שרת ללא סביבה גרפית.
בעיות שנפתרות על ידי בדיקות E2E של Selenium
שבריריות של בדיקות עקב תוכן דינמי. Selenium משתמש בהמתנות (WebDriverWait) לייצוב. אנו מגדירים המתנות מפורשות עם בדיקות מצב — זה מפחית בדיקות לא יציבות. בפועל, מספר ההרצות החוזרות יורד ב-80%, ויציבות הרצת הבדיקות מגיעה ל-99%. — תיעוד Selenium
חוסר בביצוע מקבילי. Selenium Grid מאפשר להריץ בדיקות על מספר צמתים בו-זמנית. עם Docker Compose, התשתית נפרסת תוך 10 דקות. באמצעות 4 צמתים, רגרסיה של 100 בדיקות מסתיימת תוך 25 דקות במקום 100.
עלות תחזוקה גבוהה של בדיקות. אנו מיישמים את תבנית Page Object — כל מסך מתואר על ידי מחלקה נפרדת. שינוי בסלקטור מתוקן במקום אחד. זמן עדכון הבדיקות לאחר שינויי UI מופחת ב-60%. זה מהיר פי 2.5 בהשוואה לסלקטורים ישירים.
איך אנחנו עושים את זה: טכנולוגיות וגישה
אנו משתמשים ב-Selenium 4 עם Chrome/Firefox במצב headless. עבור Python — pytest עם fixtures, עבור Java — TestNG. אנו מתכנתים לפי Page Object Model, המספק שימוש חוזר וקריאות. עם ניסיון של למעלה מ-8 שנים ב-Selenium, אנו מבטיחים יציבות בדיקות ומציעים אחריות ל-3 חודשים. חיסכון בתקציב הבדיקות יכול להגיע ל-$4.5k–6.5k בשנה, ופרויקטים מתחילים מ-$1.8k–2.6k.
דוגמה להגדרת Chrome headless:
# conftest.py
import pytest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
@pytest.fixture(scope='session')
def driver():
options = Options()
options.add_argument('--headless=new')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome(options=options)
driver.implicitly_wait(10)
driver.set_window_size(1280, 900)
yield driver
driver.quit()
בדיקה להתחברות עם המתנה להפניה:
# tests/test_login.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class TestLogin:
def test_valid_login(self, driver):
driver.get('https://example.com/login')
driver.find_element(By.CSS_SELECTOR, '[data-cy="email"]').send_keys('[email protected]')
driver.find_element(By.CSS_SELECTOR, '[data-cy="password"]').send_keys('password123')
driver.find_element(By.CSS_SELECTOR, '[data-cy="submit"]').click()
wait = WebDriverWait(driver, 10)
wait.until(EC.url_contains('/dashboard'))
assert '/dashboard' in driver.current_url
def test_invalid_login(self, driver):
driver.get('https://example.com/login')
driver.find_element(By.ID, 'email').send_keys('[email protected]')
driver.find_element(By.ID, 'password').send_keys('wrongpass')
driver.find_element(By.XPATH, '//button[@type="submit"]').click()
error = WebDriverWait(driver, 5).until(
EC.visibility_of_element_located((By.CSS_SELECTOR, '.error-message'))
)
assert 'Неверный' in error.text
איך תבנית Page Object מפשטת תחזוקת בדיקות?
Page Object מבודד סלקטורים ולוגיקת עמוד. אם מפתח frontend משנה את # conftest.py import pytest from selenium import webdriver from selenium.webdriver.chrome.options import Options @pytest.fixture(scope='session') def driver(): options = Options() options.add_argument('--headless=new') options.add_argument('--no-sandbox') options.add_argument('--disable-dev-shm-usage') driver = webdriver.Chrome(options=options) driver.implicitly_wait(10) driver.set_window_size(1280, 900) yield driver driver.quit() ל-# tests/test_login.py from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class TestLogin: def test_valid_login(self, driver): driver.get('https://example.com/login') driver.find_element(By.CSS_SELECTOR, '[data-cy="email"]').send_keys('[email protected]') driver.find_element(By.CSS_SELECTOR, '[data-cy="password"]').send_keys('password123') driver.find_element(By.CSS_SELECTOR, '[data-cy="submit"]').click() wait = WebDriverWait(driver, 10) wait.until(EC.url_contains('/dashboard')) assert '/dashboard' in driver.current_url def test_invalid_login(self, driver): driver.get('https://example.com/login') driver.find_element(By.ID, 'email').send_keys('[email protected]') driver.find_element(By.ID, 'password').send_keys('wrongpass') driver.find_element(By.XPATH, '//button[@type="submit"]').click() error = WebDriverWait(driver, 5).until( EC.visibility_of_element_located((By.CSS_SELECTOR, '.error-message')) ) assert 'Неверный' in error.text , התיקון נעשה רק במחלקת העמוד, לא בכל הבדיקות. זה מפחית את זמן התחזוקה ב-60% בהשוואה לסלקטורים ישירים. יתר על כן, Page Object Model יוצר API אחיד לאינטראקציה עם אלמנטים.
# pages/login_page.py
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class LoginPage:
URL = '/login'
def __init__(self, driver):
self.driver = driver
self.wait = WebDriverWait(driver, 10)
def open(self):
self.driver.get(f'https://example.com{self.URL}')
return self
def enter_email(self, email: str):
self.driver.find_element(By.ID, 'email').send_keys(email)
return self
def enter_password(self, password: str):
self.driver.find_element(By.ID, 'password').send_keys(password)
return self
def submit(self):
self.driver.find_element(By.CSS_SELECTOR, 'button[type=submit]').click()
return self
def get_error_message(self) -> str:
element = self.wait.until(EC.visibility_of_element_located((By.CLASS_NAME, 'error')))
return element.text
איך להגדיר ביצוע מקבילי עם Selenium Grid?
כדי להאיץ רגרסיה, אנו פורסים Selenium Grid ב-Docker. הקובץ id מפעיל hub ו-3 צמתי Chrome + צומת Firefox.
דוגמה docker-compose-grid.yml
# docker-compose-grid.yml
services:
selenium-hub:
image: selenium/hub:4.18
ports:
- "4442:4442"
- "4443:4443"
- "4444:4444"
chrome-node:
image: selenium/node-chrome:4.18
environment:
SE_EVENT_BUS_HOST: selenium-hub
depends_on: [selenium-hub]
deploy:
replicas: 3
firefox-node:
image: selenium/node-firefox:4.18
environment:
SE_EVENT_BUS_HOST: selenium-hub
חיבור ל-Grid: data-cy עם כתובת ה-hub.
from selenium.webdriver.remote.webdriver import RemoteWebDriver
driver = RemoteWebDriver(
command_executor='http://selenium-hub:4444/wd/hub',
options=ChromeOptions()
)השוואה בין סוגי המתנות ב-Selenium:
| סוג המתנה | תיאור | מתי להשתמש |
|---|---|---|
| מרומזת (implicitly_wait) | ממתין להופעת אלמנט ב-DOM (גלובלי) | לעמודים פשוטים עם טעינה צפויה |
| מפורשת (WebDriverWait + EC) | ממתין לתנאי ספציפי (נראות, לחיצות) | לתוכן דינמי, בקשות AJAX |
| FluentWait | המתנה מפורשת עם polling והתעלמות מחריגות | לתרחישים מורכבים עם תנאים משתנים |
למה Selenium עדיף על כלים אחרים?
| כלי | תאימות דפדפנים | ביצוע מקבילי | שפות | מהירות ביצוע |
|---|---|---|---|---|
| Selenium | כל הדפדפנים | Selenium Grid | Java, Python, C#, JS | בינוני |
| Cypress | רק Chrome | לא | JS | גבוה |
| Playwright | Chrome, Firefox, Safari | מובנה | JS, Python, C# | גבוה |
Selenium הוא הכרחי כאשר נדרשת תמיכה ב-Internet Explorer, Edge Legacy, או ביצוע מבוזר על חוות של 10+ מכונות. לדוגמה, בפרויקט אחד ביצענו במקביל 200 בדיקות על 8 צמתים — הרגרסיה הסתיימה תוך 18 דקות במקום 4 שעות. זה חסך ללקוח למעלה מ-$3.6k–5.2k בשנה. הפחתת עלויות QA עד 80%.
כדי להילחם בבדיקות לא יציבות, אנו משתמשים ב-# pages/login_page.py from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC class LoginPage: URL = '/login' def __init__(self, driver): self.driver = driver self.wait = WebDriverWait(driver, 10) def open(self): self.driver.get(f'https://example.com{self.URL}') return self def enter_email(self, email: str): self.driver.find_element(By.ID, 'email').send_keys(email) return self def enter_password(self, password: str): self.driver.find_element(By.ID, 'password').send_keys(password) return self def submit(self): self.driver.find_element(By.CSS_SELECTOR, 'button[type=submit]').click() return self def get_error_message(self) -> str: element = self.wait.until(EC.visibility_of_element_located((By.CLASS_NAME, 'error'))) return element.text עם polling כל 500 אלפיות השנייה והתעלמות מ-docker-compose-grid.yml. זה מספק יציבות של 99% בעמודים דינמיים.
מה כלול בעבודה: תוצרים
- הקמת תשתית בדיקות (Selenium Grid, Docker, סוכני CI).
- פיתוח מחלקות Page Object לעמודים מרכזיים (עד 20 מחלקות).
- כתיבת 20–50 מקרי בדיקה (חיוביים/שליליים, מקרי קצה).
- אינטגרציה עם CI/CD (Jenkins, GitLab CI, GitHub Actions).
- הפקת דוחות (Allure, pytest-html עם מדדי כיסוי).
- תיעוד להרצה ותחזוקה.
- הדרכת צוות למשך 1–2 ימים.
- גישה לכל ארטיפקטי הבדיקה ותמיכה שוטפת.
תהליך העבודה
- ניתוח — חקר האפליקציה, זיהוי תרחישים קריטיים, הערכת מאמץ.
- עיצוב — הגדרת מבנה Page Object, נתוני בדיקה, תצורת Grid.
- יישום — כתיבת מחלקות Page Object ובדיקות, הגדרת המתנות.
- בדיקה — הרצה על staging, תיקון בדיקות לא יציבות, מדידת יציבות.
- פריסה — אינטגרציה ל-CI, הגדרת דוחות, הדגמה לצוות.
לוחות זמנים (משוערים)
- מ-5 ימי עסקים (30 בדיקות, סט בסיסי, ללא Grid).
- עד 15 ימי עסקים (50+ בדיקות, Grid, תיעוד מלא, הדרכה).
אנו מספקים הערכה מדויקת לאחר ביקורת פרויקט. הניסיון שלנו באוטומציה: למעלה מ-50 פרויקטים, 8 שנות עבודה עם Selenium. צרו קשר — ונראה לכם איך בדיקות E2E יכולות לקצר רגרסיה משלושה ימים לשעה אחת. הזמינו פיתוח בדיקות E2E עכשיו, והצוות שלכם יפסיק לבזבז זמן על בדיקות ידניות חוזרות. חיסכון בתקציב הבדיקות יכול להגיע ל-$4.5k–6.5k בשנה. קבלו ייעוץ — נענה על כל שאלותיכם.







