🐛 Типичные ошибки с локаторами
⚡ Топ-5 ошибок с локаторами
- NoSuchElementException — элемент не найден: неверный локатор или элемент ещё не загрузился
- CLASS_NAME с пробелом —
By.CLASS_NAME, "btn btn-primary"падает; используйте CSS:.btn.btn-primary - Хрупкий XPath из DevTools — абсолютный путь сломается при любом изменении HTML
- find_element vs find_elements — путаница типов; у find_elements нет .text напрямую
- is_displayed() не означает "элемент существует" — сначала найдите, потом проверяйте видимость
Ошибка 1: NoSuchElementException
Симптом: тест падает с selenium.common.exceptions.NoSuchElementException: Message: no such element.
Причины:
- Опечатка в локаторе (неверный ID, класс, XPath)
- Элемент ещё не загрузился (нужны ожидания)
- Элемент находится внутри iframe (нужен switch_to.frame)
- Страница не та (неверный URL или редирект)
# ПРОБЛЕМА
element = driver.find_element(By.ID, "loginn") # опечатка
# NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"[id='loginn']"}
# РЕШЕНИЕ: проверить ID через DevTools
element = driver.find_element(By.ID, "login") # правильно
# ПРОБЛЕМА: элемент ещё не загрузился
driver.get("https://example.com")
element = driver.find_element(By.ID, "dynamic-content") # ошибка!
# РЕШЕНИЕ (предварительное): добавить явное ожидание (тема урока 07)
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "dynamic-content"))
)
Ошибка 2: By.CLASS_NAME с составным классом
Симптом: InvalidSelectorException: Compound class names not permitted.
Причина: By.CLASS_NAME принимает только одно имя класса без пробелов. Если у элемента несколько классов, разделённых пробелом — это разные классы.
# HTML
<button class="btn btn-primary">Войти</button>
# НЕВЕРНО — InvalidSelectorException
element = driver.find_element(By.CLASS_NAME, "btn btn-primary")
# ВЕРНО — CSS_SELECTOR с точками
element = driver.find_element(By.CSS_SELECTOR, ".btn.btn-primary")
# Также верно — по одному классу
element = driver.find_element(By.CLASS_NAME, "btn-primary")
Ошибка 3: Хрупкий XPath из DevTools «Copy XPath»
Симптом: локатор работает сегодня, но ломается после любого изменения разметки или стиля страницы.
Причина: DevTools генерирует абсолютный XPath по позиции в DOM.
# Автоматически скопированный XPath из DevTools — хрупкий
/html/body/div[2]/main/div/form/div[1]/input # сломается при любом изменении DOM
# ЛУЧШЕ: XPath на основе стабильного атрибута
//*[@id="username"] # по ID
//input[@name="username"] # по name
//button[text()="Войти"] # по тексту
/html/body/div[N]/.... Такой локатор сломается при любом добавлении/удалении элемента на странице.
Ошибка 4: Путаница find_element и find_elements
Симптом 1: AttributeError: 'list' object has no attribute 'text' — попытка вызвать .text у списка.
Симптом 2: тест не падает, хотя элемент отсутствует — find_elements вернул [].
# ПРОБЛЕМА: find_elements возвращает список, не WebElement
cards = driver.find_elements(By.CSS_SELECTOR, ".col-sm-4")
print(cards.text) # AttributeError! У списка нет .text
# РЕШЕНИЕ: обращаться к элементу по индексу
print(cards[0].text) # текст первой карточки
# ПРОБЛЕМА: пропущенная проверка на пустой список
cards = driver.find_elements(By.CSS_SELECTOR, ".non-existent")
print(cards[0].text) # IndexError: list index out of range
# РЕШЕНИЕ: проверить длину
if cards:
print(cards[0].text)
else:
print("Элементов не найдено")
Ошибка 5: is_displayed() на несуществующем элементе
Симптом: думаете проверить "есть ли элемент", но используете is_displayed() после find_element() — который уже выбросил исключение.
# НЕВЕРНО: если элемент не найден, find_element выбросит
# NoSuchElementException ещё до вызова is_displayed()
element = driver.find_element(By.ID, "maybe-exists")
element.is_displayed() # до этой строки не дойдёт!
# ВЕРНО: используйте find_elements для безопасной проверки
elements = driver.find_elements(By.ID, "maybe-exists")
if elements and elements[0].is_displayed():
print("Элемент найден и виден")
elif elements:
print("Элемент есть в DOM, но скрыт")
else:
print("Элемента нет в DOM")
Ошибка 6: XPath с @class — неполное совпадение
Симптом: //*[@class="btn"] не находит <button class="btn btn-primary">.
Причина: @class="btn" ищет точное совпадение всего значения атрибута class.
# HTML
<button class="btn btn-primary">Click</button>
# НЕ НАЙДЁТ — ищет точное "btn"
//*[@class="btn"]
# НАЙДЁТ — contains проверяет подстроку
//*[contains(@class, "btn")]
# Или CSS (рекомендуется):
.btn.btn-primary
Ошибка 7: Использование старого API (Selenium 3)
Подробнее — в разделе ⚖️ Старый vs Новый.
# ПАДАЕТ в Selenium 4
driver.find_element_by_id("x") # AttributeError
# ВЕРНО
driver.find_element(By.ID, "x")