Java Selenide-对于循环的ElementsCollection,在循环期间进行了修改

时间:2019-04-02 10:01:13

标签: java list for-loop selenide

背景

我从事Java编程已有3年了,但这是我第一次我仍然不了解for循环的基本原理,哦,天哪!

所以我有一个Selenide项目。 Selenide是一个基于SeleniumHQ的网络自动化测试库。

我有一个简单的for循环,循环遍历图像元素列表。


项目设置

依赖性:

compile group: 'com.codeborne', name: 'selenide', version: '5.2.2'

进口:

import static com.codeborne.selenide.Selenide.$$;
import static com.codeborne.selenide.Selectors.byXpath;

邪恶代码:

final ElementsCollection list = $$(byXpath("//img[@src='original src']"));
for (int i=0; i<list.size(); i++) {
    doSth(list.get(i));
}

doSth方法:

void doSth(SelenideElement element) {
    Selenide.executeJavaScript("arguments[0].src = 'new src';", element);
}

当然,以上代码是我正在处理的代码的简单版本,但核心结构仍然存在。


问题

我发现循环计数/迭代次数少于预期,对我而言,它是预期4 实际2

1 个答案:

答案 0 :(得分:0)

根本原因分析

doSth方法尝试更改来自参数的src元素的img属性。更改之后,img元素将不再满足XPath。 img元素在修改后是否满足XPath至关重要,因为Selenide如何检索这些元素。

由于Selenide的XPath选择的元素集合像单个元素对象一样被懒惰地求值,因此集合中的每个元素仅存储元素索引和集合XPath(在Selenide的JavaDoc中提到)。更新集合元素之一的src属性时,它会导致动态集合大小缩小,从而影响后续的循环迭代。

在阅读ElementsCollection类的源代码之后,我们将知道ElementsCollection是具有重写方法的AbstractList。随着Java for循环的终止条件在每次迭代中得到评估,被覆盖的size()方法实际上在每次循环迭代后返回一个较小的数字,且递减1


解决方案

由于列表的第一项(0的索引)已修改其src,因此每次迭代后,列表1的大小将缩小n+1。第n个元素的位置。我总是可以得到第一项(0的索引),它实际上给了我下一个项,因为上一个项将不再保留在动态列表中。

  • 第一次迭代:
    • [0] = element A
    • [1] = element B
    • [2] = element C
    • [3] = element D
  • 第二次迭代:
    • [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
}