在粉丝群,总是见到有新人问selenium定位失败的问题,几年前呢还都是些简单的普通的原生页面元素,问题也都很简单,比如被遮挡啊,xpath写错啊,有前置事件啊等等。
而最近一两年,大多数都是一些专门的前端框架导致的定位失败,尤其是ELementUI的(包括elementPlus的),而且大多并非特殊情况,都是普通标准的元素。考虑到elementUI的各种元素支持selenium操作并没有搜到完整教程,那这里就先写一个关于elementUI下拉框的教程吧,等慢慢写多了再凑吧凑吧成一个完整吧,提前关注,以免迷路!
我会弄一个专门测试用的elementUI页面来进行测试。
先来看下elementUI的下拉框代码:
表现如图:
那到这里很多同学其实就会觉得用selenium去定位的元素是:
<el-select>
结果发现定位失败....
然后打开页面源码赫然发现:
赫然发现:这个下拉框的真身是一个,哦不,是一群元素。
一个多层嵌套的div,最外层的class事el-select。
紧接着,展开就看到了一大堆看不懂的div,但却完全没发现里面的具体选项内容:
其实看到这里,你就明白了,在elementUI的世界其实并没有真正的下拉框,而是一个用div和js等组合的复杂组件。所以你用传统的selenium针对select下拉框的方法肯定行不通了...
而这里需要明确一个概念,就是当你选中了某个具体的选项内容后,比如我选的111,真正发生变化的是俩个地方:
放在了那个含有el-select__selected-item样式的div内的span中。
所以有些同学到此就会用js强行修改这个样式的内容为指定内容,结果却发现不好使。
那是因为,这个地方的显示,并不重要,只是给你人肉眼看的。
而真正影响之后数据的其实是一个VUE的变量,这个变量之后会用到诸如函数、接口等重要地方。
所以如果你没有修改这个变量,那就毫无意义。这个变量在源码中可以看到:
当然这里只是随便起的变量名:value,你可以用任意的自定义名称。
所以,按照咱们之前的《测开方法论》《测试开发方法论》导读
系列文章讲到,这种情况先设计出可以解决的所有方案,还有各自的步骤。
方法一:
按照传统控制div的方法,模拟鼠标点击。
点评:这种方法是最安全也是最正确的方法,因为你不能完全确定这个点击事件中是否只有一个变量的事,没准还有其他很多问题,比如动态加载,异步事件等等。所以只是想当然的觉得只是给一个value变量赋值,然后通过js强行赋值,那很可能就错过了一些其他事件,导致功能失败。
方法二:
通过js命令强行赋值,在浏览器的控制台或者selenium的execute_script命令中执行js命令。这种方法是有概率可以实现的,但肯定是不推荐的。vue通常不可能让你从外面直接操控内部的变量。
综上所述,方法一难度、正确性、稳定性、成功率。都完全优越于方法二。
所以,我们应该选择方法一进行尝试:
首先,别操之过急,我们先用简单的冒烟脚本,试试看谷歌浏览器和驱动这些是否能顺畅打开页面:(这里我笔误写成了drvier,不改了麻烦)
可以看到,页面打开了,虽说有点卡,但是selenium对高版本chrome就这样....
然后我们先按照方法一写具体脚本:用样式名:el-select来点击
结果可以看到是可以成功点开的
然后是选择具体的值,比如选中111要怎么做?注意,这里开始上难度了。
首先vue它是动态加载的,所以这些子元素,你在页面的f12里看都看不见更别提定位了。
所以接下来你可能会去百度或者问问AI怎么定位,如果结果发现给的语句都不好使,那就来试试我这个独家的秘方吧:
走到了这一步,我们接下来仍然有俩个方案可以具体选中下拉菜单的具体某项。
方法一:通过定位到那个隐藏的选项dom并点击,来操作,方便快捷。
方法二:通过模拟键盘操作(按下方向的次数和回车来实现),但显而易见的出错率高且慢。
所以我们通过的是方法一来定位。
注意,接下来的解法在AI中是搜不到的,属于本文首创,如果之后AI中可以搜到了,那我真特么的问候一下这些AI模型,啥都爬啊?
言归正传:
我们先看一下这个源码:
注意,这里是一个动态的ID,每次刷新页面,每次启动页面都会不同。
然后我们选中某个子选项,那个子选项的动态ID其实就取自这里的前三部分:
也就是说,取的是 'el-id-783',那最后部分是什么呢?
最后部分的数字,就在这个 el-id-783-1 和 el-id-783-5 之间。
也就是 2、3、4
恰好我们这个下拉框就这么三个选项,其实就正对着这个动态ID:
el-id-783-2,el-id-783-3,el-id-783-4
那我们通过脚本进行简单的字符串拼接即可定位到目标子选项并点击了。
(首先需要先定位到这个el-select__input,然后拿到里面的属性aria-controls,然后截取前面部分,再拼接成目标选项,再定位点击就可以)
代码如下:复制一下吧,别打错字误以为不好使。
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
drvier = webdriver.Chrome()
drvier.get('http://localhost:8080/#/')
time.sleep(1)
drvier.find_element(By.CLASS_NAME, "el-select").click()
time.sleep(3)
s = drvier.find_element(By.CLASS_NAME,'el-select__input')
idl = '-'.join(s.get_attribute('aria-controls').split('-')[:-1])
ss = drvier.find_element(By.ID,idl+'-2')
ss.click()
time.sleep(5)
drvier.quit()
然后我们看效果:
测试成功!
其实,没有定位不到的元素,万变不离其宗,前端无论什么框架,多少花样,你都要找到规律,一招搞定。