Анализ первопричин
Метод doSth
пытается изменить атрибут src
элемента img
, который приходит из параметра. После изменения элемент img
больше не будет выполнять XPath. Вопрос о том, соответствует ли элемент img
XPath после модификации, имеет значение из-за того, как Selenide извлекает элементы.
Поскольку коллекция элементов, выбранная XPath от Selenide, лениво оценивается так же, как и отдельные объекты-элементы, каждый из элементов в коллекции хранит только индекс элемента и коллекцию XPath (это упоминается в JavaDoc Selenide). Когда атрибут src
одного из элементов коллекции обновляется, он влияет на последующую итерацию цикла, вызывая уменьшение динамического размера коллекции.
После прочтения исходного кода класса ElementsCollection
мы узнаем, что ElementsCollection
- это AbstractList
с переопределенными методами. Поскольку условие завершения в цикле Java for вычисляется на каждой итерации, переопределенный метод size()
фактически возвращает меньшее число с уменьшением 1
после каждой итерации цикла.
Решение
Поскольку первый (индекс 0
) элемент списка имеет измененный src
, список будет уменьшаться до 1
после каждой итерации, элемент n+1
будет занимать позицию n
й элемент. Я всегда могу получить первый (индекс 0
) элемент, который фактически дает мне следующий элемент, так как предыдущий элемент больше не будет оставаться в динамическом списке.
- 1-я итерация:
[0] = element A
[1] = element B
[2] = element C
[3] = element D
- 2-я итерация:
[0] = element B
[1] = element C
[2] = element D
Изменить цикл следующим образом:
final ElementsCollection list = $$(byXpath("//img[@src='original src']"));
final int count = list.size(); // extract to evaluate once only
for (int i=0; i<count; i++) {
doSth(list.get(0)); // change i to 0
}