vue框架下面,没有id、没有name,vue帮开发做了很多脏活累活,却委屈了写页面自动化测试的人(当然,也给爬信息的也带来了一定的难处)。这里只能靠总结,用一些歪门邪道:
一、跟开发商量:
哪些是不能或者没有交给框架的,比如css名等,哪个能固定就用哪个。真不行,请他们吃顿饭,留点id来耍耍。
二、尽量找到唯一的,不变的:
1、页面上的文字:
其实有很多页面上的文字是产品固化在那边的,研发肯定不能随意修改。比如新增的时候弹出的一个框框叫"新增XXXX",这个只有在新增上下文中才会出现,并且当前页面基本上可以保证唯一,那就可以拿来使用。这时候的思路是:1先用文字定位到唯一的一个元素(不管在哪里);2再通过xpath上下左右去找自己想要的节点。比如相关代码:
# 先找到最外面的框框
new_contract_box = self.wait.until(
expected_conditions.presence_of_element_located((By.XPATH, f"//div[@aria-label='新增XXXX']")))
# 再二次定位找到想要的节点元素
first_input = new_contract_box.find_element(By.XPATH, ".//input")
有哪些可以定位文字的方法?可参考如下:
1、属性匹配:(By.XPATH, f"//div[@aria-label='新增XXXX']") 或 (By.XPATH, f"//div[contains(@aria-label,'新增XXXX')]")
2、文字匹配:(By.XPATH, f"//div[@text()='新增XXXX']")
3、dom属性匹配,比如innerText:先(By.XPATH, f"//div"),再循环for node in div_nodes: node.get_property("innerText")
2、css的组合:
(这一点待考究)我观察过不管是用框架,还是自己写的css,class里面的名字基本上是固定的。当几个css组合到同一个节点上时,这时候就可以形成唯一条件。
# 用所有的css一起去定位
self.driver.find_element(By.CSS_SELECTOR,
".el-button,.el-button--primary,.el-button--large,.login-btn").click()
三、结合鼠标事件用绝对定位法:
(这一招属于突发奇想的原创,可能别人也写过但我真没在有限的网络里面找到类似的答案,现在也经过了持续集成的洗礼,仅供参考,谨慎服用)
参考这个场景:
上面的input框,一个click事件后,vue自动生成一个下拉框供选择,选择下拉框里的"其他"后,回填回input框中,下拉框消失。
定位后发现,当点击input框后,自动生成的下拉框在离现在的input很远的地方生成代码(在body的尾巴上),而在dom里面没有明显的标记能把新生成的下拉框跟这个input关联,"其他"文字也不是唯一,并且这种下拉输入框在当前的页面上有好多个。
有点啰嗦,反正就一句话:没办法找到新生成的下拉框。
那我就不找了,思路转变成:直接用鼠标事件去点击下拉框里的某个选项,实现如下:
first_input = new_contract_box.find_element(By.XPATH, ".//input")
self.actions.move_to_element(first_input).click().move_by_offset(0, 60).click().perform()
解释一下代码:
第一行先是定位到input框。第二行用ActionChains把鼠标移动到input框上,做个点击先生成下拉框,然后根据input框向下偏移60px的位置,再做个点击,就正好点击到"其他"选项中了。其中60px根据实际情况进行调整,如有多个选项也根据实际情况进行调整。
四、利用浏览器的console提高效率:
$x("xpath语法"),找到以后把"xpath语法"拷贝过去给python代码使用。比如:
五、其他(后面更新经验了继续补充)