Как написать запрос для поиска нескольких элементов на странице одним запросом?
Что проверяют
Знаете ли вы разницу между поиском одного элемента и коллекции в своём инструменте автоматизации и умеете ли писать селектор, который покрывает несколько элементов сразу. Следом спрашивают, что вернётся, если ничего не найдено, и как проверить количество.
Как отвечать
Суть в одном селекторе, который описывает все нужные элементы, и в методе, который возвращает коллекцию:
- Selenium:
driver.findElements(By.cssSelector(".item"))возвращаетList<WebElement>. Если совпадений нет, приходит пустой список, аfindElementв той же ситуации бросаетNoSuchElementException; - Playwright:
page.locator('.item')описывает сразу все совпадения. Дальшеcount(),nth(i),all(),allTextContents(), а проверка идёт черезawait expect(locator).toHaveCount(5)с автоожиданием; - консоль браузера:
document.querySelectorAll()возвращает статическийNodeList, в DevTools есть короткая форма$$().
Если элементы разные, их объединяют в одном запросе. В CSS это группа через запятую: button.save, a.cancel. В XPath объединение через |: //button[@type='submit'] | //a[@role='button']. Результат приходит в порядке следования в документе, а не в порядке частей селектора, на это легко нарваться.
Для устойчивости опирайтесь на атрибуты, которые команда добавляет для тестов, вроде data-testid, а не на nth-child и абсолютные XPath от /html/body. В Playwright удобнее getByRole() с фильтрами: page.getByRole('listitem').filter({ hasText: 'Оплачен' }).
Где спотыкаются
Проверяют отсутствие элемента через findElements(...).isEmpty() при включённом неявном ожидании. Selenium ждёт весь таймаут и только потом возвращает пустой список, тест замедляется на секунды.
Сохраняют найденный список и работают с ним после перерисовки страницы. Ссылки устаревают, и прилетает StaleElementReferenceException, поэтому элементы ищут заново или используют локаторы Playwright, которые разрешаются при каждом действии.
Вызывают click() на локаторе Playwright, который находит несколько элементов. В строгом режиме это ошибка, нужно сузить селектор или явно указать first() или nth().