Как класс Selenium ByChained действительно работает?

Я очень смущен тем, что документация для класса ByChained упоминает. Он говорит:

механизм используется для поиска элементов в документе с помощью ряда других поисков. Этот класс найдет все элементы DOM, которые соответствуют каждый из локаторов в последовательности, например, водитель.findElements(новый ByChained(by1, by2)) найдет все элементы, которые соответствуют by2 и отображаются под элементом, который соответствует by1.

есть вопрос для Селена на code.google.com, поднятый для класса ByChained, где кто-то прокомментировал, что он должен использоваться для поиска элемента/элементов с использованием нескольких локаторов.

Я не понимаю. Почему by1 и by2 должны быть локаторами двух разных элементов? Когда я случайно наткнулся на этот класс, я почувствовал, что он поможет в поиске элемента(ов) с помощью разных локаторов. Так что если один локатор не работает, далее будет работать. Но когда я практически использовал этот класс, он вел себя очень странно и все время бросал NoSuchElementException.

например, если мой html:

<html>
  <body>
    <div id="details">
      <input id="firstName" class="personName" type="text"/>
    </div>
  </body>
</html>

Я хочу найти поле ввода с помощью двух локаторов в ByChained:
1. используя By.id("firstName")
2. используя By.className("personName")

таким образом, мой код становится:

By myBy = new ByChained(By.id("firstName"),By.className("personName"));
driver.findElement(myBy);

на исполнение, я получил NoSuchElementException. Я ожидал, что если сначала не получилось, потом он будет найти элемент с next By в серии.

кто-нибудь может объяснить, как этот класс работает с примером и в каких сценариях он может быть использован?

3 ответов


этот класс позволяет вам найти элемент, используя его heirarchy в dom.

допустим, по какой-то причине у вас есть следующий HTML:

<html>
    <body>
        <div id="details">
            <input id="firstName" class="personName" type="text"/>
        </div>
        <input id="firstName" class="personName" type="text"/>
    </body>
</html>

и вы хотите получить элемент, который находится между div, а не один сам по себе. Вы можете использовать ByChained by, чтобы указать, что вы хотите этот элемент, выполнив следующие действия:

new ByChained(By.id("details"),By.id("firstName"));

что происходит, так это то, что он находит первый элемент, а затем ищет под ним в dom иерархии для селектора, который идет следующим в списке. В основном это просто хороший чистый способ больше не делать следующее:

details = driver.findElement(By.id("details"));
input = details.findElement(By.id("firstName"));

ваш запрос будет удовлетворен чем-то, что можно назвать ByAny который вернет элементы, соответствующие любому из переданных By аргументов. Нет такого класса AFAIK.

, ByChained работает по-разному. Он находит элементы, которые соответствуют первому аргументу,затем ищет их потомков, используя второй аргумент и т. д. Итак, если у вас был HTMl, как это:
<html>
    <body>
        <div id="details">
            <input id="firstName" class="personName" type="text"/>
        </div>
        <div id="notDetails">
            <input id="secondName" class="personName" type="text"/>
        </div>
    </body>
</html>

и вы хотели найти class=personName элемент под id=details, вы можете использовать селектор CSS, выражение XPath или

new ByChained(By.id("details"), By.className("personName"))

обратите внимание, что также есть ByAll класс, который ищет элементы, соответствующие всем By аргументы.


вероятно, важно отметить (потому что я никогда не вижу, чтобы кто-то упоминал об этом), что ByChained следует использовать так же, как и любой другой By локатор, вот так:

driver.findElements( new ByChained(By.id("details"), By.className("personName")) )

или

driver.findElements( new ByAll(By.id("err1"), By.className("errBox")) )