Учитывая ссылку на элемент пользовательского интерфейса, как мне «добавить» к нему строку, чтобы я мог найти ее следующий родственный элемент типа XCUIElementTypeStaticText?
Фреймворк, который я использую, содержит файл driver_helper.py.
В этом файле находятся методы find_element и find_elements, определенные как:
def find_element(self, locator: tuple) -> WebElement:
return self.driver.find_element(*locator)
def find_elements(self, locator: tuple) -> list[WebElement]:
return self.driver.find_elements(*locator)
Существует также файл selector_const.py, содержащий объявления для различных типов селекторов. Тот, который я использую специально для этого вопроса:
BY_XPATH = MobileBy.XPATH
В объектном файле экрана/страницы, над которым я работаю, я определяю кортеж
self.CHECKBOXES = (sc.BY_XPATH, '//XCUIElementTypeButton[@name = "Square"]')
который я затем использую для создания этой переменной:
checkboxes = self.driver_helper.find_elements(self.CHECKBOXES)
Я хочу найти родственный элемент для одного из флажков, но этот фрагмент кода:
checkboxes = self.driver_helper.find_elements(self.CHECKBOXES)
sibling = (
sc.BY_XPATH,
f'{checkboxes[0]}/following-sibling::XCUIElementTypeStaticText',
)
test = self.driver_helper.find_element(sibling)
print("checkbox 0 sibling element text: " + str(test))
терпит неудачу с NoSuchElementError: An element could not be located on the page using the given search parameters.
Я включил скриншот домена экрана, чтобы показать, что флажки действительно существуют и что рядом с ними есть XCUIElementTypeStaticText.
Домен экрана приложения iOS:
<XCUIElementTypeButton type = "XCUIElementTypeButton" name = "Square" label = "Square" enabled = "true" visible = "true" accessible = "true" x = "15" y = "428" width = "20" height = "21" index = "22"/>
<XCUIElementTypeStaticText type = "XCUIElementTypeStaticText" value = "checkbox 1 text" name = "checkbox 1 text" label = "checkbox 1 text" enabled = "true" visible = "true" accessible = "true" x = "43" y = "428" width = "308" height = "18" index = "23"/>
<XCUIElementTypeButton type = "XCUIElementTypeButton" name = "Square" label = "Square" enabled = "true" visible = "true" accessible = "true" x = "15" y = "478" width = "20" height = "21" index = "24"/>
<XCUIElementTypeStaticText type = "XCUIElementTypeStaticText" value = "checkbox 2 text" name = "checkbox 2 text" label = "checkbox 2 text" enabled = "true" visible = "true" accessible = "true" x = "43" y = "478" width = "260" height = "35" index = "25"/>
<XCUIElementTypeButton type = "XCUIElementTypeButton" name = "Square" label = "Square" enabled = "true" visible = "true" accessible = "true" x = "15" y = "542" width = "20" height = "21" index = "26"/>
<XCUIElementTypeStaticText type = "XCUIElementTypeStaticText" value = "checkbox 3 text" name = "checkbox 3 text" label = "checkbox 3 text" enabled = "true" visible = "true" accessible = "true" x = "43" y = "542" width = "333" height = "86" index = "27"/>
<XCUIElementTypeButton type = "XCUIElementTypeButton" name = "Square" label = "Square" enabled = "true" visible = "true" accessible = "true" x = "15" y = "657" width = "20" height = "21" index = "28"/>
<XCUIElementTypeStaticText type = "XCUIElementTypeStaticText" value = "checkbox 4 text" name = "checkbox 4 text" label = "checkbox 4 text" enabled = "true" visible = "true" accessible = "true" x = "43" y = "657" width = "320" height = "52" index = "29"/>






Сохраните весь XPath в переменной:
main_element = "//*[@id = "submenu1"]/a[2]"
element = driver.find_element(By.XPATH, main_element)
siblingElement = main_element + "/following-sibling::td"
element2 = driver.find_element(By.XPATH, siblingElement)
Вы не можете вставить WebElement объект/ссылку в строку XPath, потому что выражение Xpath должно быть строкой, как вы сами упомянули.
Что вы можете сделать, так это найти другой элемент на основе существующего элемента.
Например, если вы хотите найти /following-sibling::td на основе существующего элемента, вы можете сделать это следующим образом:
element = driver.find_element(By.XPATH, '//*[@id = "submenu1"]/a[2]')
siblingElement = element.find_element(By.XPATH, './following-sibling::td')
find_element к объекту element, а не к объекту driver.., чтобы уведомить, что этот относительный XPath связан с текущим узлом.find_element(By.XPATH, используется сейчас, а find_element_by_xpath устарело.base_elements = driver.find_elements(By.XPATH, 'the_xpath_locator')
for element in base_elements:
siblingElement = element.find_element(By.XPATH, './following-sibling::td')
В этом случае вам нужно будет перебрать список объектов, применяя подход, который я упомянул для каждого элемента в списке.
Я попытался передать жестко закодированное значение для целей тестирования, но до сих пор не нашел элемент. Я добавил более конкретную информацию к вопросу для большего контекста.
В вашем обновленном вопросе не то, что я имел в виду. Пожалуйста, смотрите мой обновленный ответ
Спасибо вам за помощь. К сожалению, это тоже не сработало.
Пожалуйста, поделитесь XML/HTML этого экрана (я понимаю, что это мобильное приложение), чтобы мы могли выполнить базовую отладку.
Хорошо, добавил XML/HTML экрана
Если вы можете добавить методы в driver_helper.py, вы можете реализовать там метод, используя решение, представленное в этом ответе
Но если вы не можете этого сделать, вам нужно изменить код вашей переменной sibling. Теперь вы пытаетесь поместить элемент в XPATH, и это не может работать, поскольку вы помещаете объект в строку.
Таким образом, обходной путь состоит в том, чтобы поместить туда строку XPATH, которую вы используете для поиска родительского элемента.
Когда вы соберете все флажки в список, вы можете пройтись по ним и получить братьев и сестер следующим образом:
for i in range(len(checkboxes)):
sibling = (sc.BY_XPATH, f'(//XCUIElementTypeButton[@name = "Square"])[{i+1}]/following-sibling::XCUIElementTypeStaticText')
test = self.driver_helper.find_element(sibling)
print(f"checkbox {i+1} sibling element text: {test.text}")
Те же результаты. Я попытался изменить как [{i+1}], так и [{i}] в качестве переданного в индексе, и оба потерпели неудачу. ============== для i в диапазоне (len (флажки)): sibling = (sc.BY_XPATH, f'(//XCUIElementTypeButton[@name = "Square"])[{i +1}]/XCUIElementTypeStaticText') test = self.driver_helper.find_element(sibling) print(f"checkbox {i+1} sibling element text: {test.text}")
Извините, я забыл о важной части кода: following-sibling::. Сейчас я отредактировал код. Можешь попробовать еще раз?
Это сработало. Тай очень! Я заметил, что вы пропустили этот небольшой фрагмент ранее (часть next-sibling::), но по какой-то причине, когда я попытался добавить его самостоятельно, он все еще терпел неудачу. При этом я скопировал ваш недавно отредактированный ответ, и это было успешно. Я награжу тебя наградой, как только смогу. Еще раз спасибо.
Что, если я использую вызов findelements для хранения массива ссылок в переменной?