使用 selenium 已经好几个年头,从开始使用 selenium ide 录制、到手动编写脚本、到使用 execl 管理关键字驱动用例,到今年通过 python、flask、mysql、docker 搭建为一个部门内通用的自动化测试管理平台,觉得有必要把一些常见问题和技巧总结一下。
以百度首页为例,输入框、搜索按钮几个元素对应的 HTML 代码分别如下:(可在页面中右键》查看元素,或在浏览器中按 F12 打开开发模式查看元素)
搜索输入框:
<input id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
“百度一下”按钮:
<input type="submit" id="su" value="百度一下" class="bg s_btn">
使用元素的 id, 是最便利,也是最稳定的一种元素识别方式。所以在看到元素源代码包含 id 时,首先考虑使用 id。
如上面的搜索输入框、搜索按钮,分别有对应的 id : kw、 su。
driver.find_element_by_id("kw").send_keys("selenium test")
driver.find_element_by_id("su").click()
开发人员在开发时未必会给每一个元素都加上 id ,所以我们会遇到一些无法使用 id 定位的元素。
这种情况下,可根据元素的具体情况使用不同的方法进行定位。
如百度首页右上有新闻、地图、视频等链接。查看源码,这些链接是没有 id 的:
<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
<a href="http://www.hao123.com" name="tj_trhao123" class="mnav">hao123</a>
<a href="http://map.baidu.com" name="tj_trmap" class="mnav">地图</a>
<a href="http://v.baidu.com" name="tj_trvideo" class="mnav">视频</a>
<a href="http://tieba.baidu.com" name="tj_trtieba" class="mnav">贴吧</a>
<a href="http://xueshu.baidu.com" name="tj_trxueshu" class="mnav">学术</a>
<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F&sms=5" name="tj_login" class="lb" onclick="return false;">登录</a>
<a href="http://www.baidu.com/gaoji/preferences.html" name="tj_settingicon" class="pf">设置</a>
<a href="http://www.baidu.com/more/" name="tj_briicon" class="bri" style="display: block;">更多产品</a>
我们要找到一个只有这个元素才有的属性来进行定位:
如上面每个元素都有一个对应的 name 属性,如:tj_trnews 。 这个属性值如果是唯一的(即在当前页面只有一个元素的 name = tj_trnews),则定位起来也非常方便和稳定。 同理,可以用多种不同的方式定位上的元素:
通过name 定位 《新闻》 链接:
driver.find_element_by_name("tj_trnews").click()
通过link text 定位 《新闻》 链接:
driver.find_element_by_link_text("新闻").click()
通过partial link text 定位 《新闻》 链接 ,与link text 的区别在于完全匹配和模糊匹配:
driver.find_element_by_partial_link_text("新闻").click()
通过class 定位 《设置》 链接:
注:有些元素的 class 是相同的,此时未必能定位到同一个元素;另外有些元素的class属性是复合型的,如:
class="fa fa-eye",这时需要选择其中一个属性来进行定位。
driver.find_element_by_class_name("pf").click()
driver.find_element_by_class_name("fa-eye").click()
css 、xpath 是根据页面结构位置来定位元素的方式。如在 chrome 浏览器的开发模式中,选择对应节点,右键 copy ,可看到 copy selector 和 copy xpath 的两个选项,对应的就是复制当前元素对应的 css 和 xpath 路径。
selenium 中对应的使用方式:
css:
driver.find_element_by_css_selector("#u1 > a.pf").click()
xpath:
driver.find_element_by_xpath('//*[@id="u1"]/a[8]').click()
注意:
由于 css 、 xpath 是根据页面的结构查找元素的,所以存在以下问题:
有时会发现,有时明明已使用元素唯一的属性(如 id、name),执行时却提示无法找到元素。
这时可以检查一下,页面元素是否存在在 iframe(html 中的一个内联框架)中。
<div id="iframewrapper">
<iframe frameborder="0" id="iframeResult" style="height: 643.96px;">
<title>iframe</title>
<input type="submit" id="bt1" value="iframe中的按钮" class="bg s_btn btnhover">
</iframe></div>
<input type="submit" id="su" value="主页面的按钮" class="bg s_btn btnhover">
例如上面的 html 代码,页面上分别有 bt1 和 bt2 两个按钮,其中 bt1 是在 frame iframeResult 中,bt2 是在主页面。
这时,如果直接点击 bt1, 是无法找到元素的,必须先切换到 iframe 中:
先切换到目标iframe,其中 iframeResult 是目标iframe 的id:
driver.switch_to.frame("iframeResult")
然后再操作iframe中的元素:
driver.find_element_by_id("bt1").click()
如果再操作主页面的元素,需要切换回主页面:
driver.switch_to.default_content()
然后再操作主页面的元素:
driver.find_element_by_id("bt2").click()
一些通用的页面元素,如一些通用的按钮:“查询”、“新增” 等,或者是公共的菜单导航等,可以直接使用 link text 进行定位。这样不需要每个页面的按钮和菜单都逐个查看对应的 html 代码,而且测试用例中对步骤更为清晰明了。
如:
# 点击两级菜单:
driver.find_element_by_partial_link_text("系统管理").click()
driver.find_element_by_partial_link_text("数据字典").click()
...
# 输入查询条件后,点击查询按钮。 注意这里的查询由于样式设计,中间有空格,填写到脚本中时一定要复制完整。
driver.find_element_by_partial_link_text("查 询").click()
selenium 提供了对选择框的多种选择方法。
如以下是一个 select 组件:
<select id="select1">
<option index="0" value="volvo">Volvo</option>
<option index="1" value="saab">Saab</option>
<option index="2" value="mercedes">Mercedes</option>
<option index="3" value="audi">Audi</option>
</select>
操作方式可以有:
from selenium.webdriver.support.select import Select
按选项的index 值选择
Select(driver.find_element_by_id('select1')).select_by_index('1')
按选项的value 值选择
Select(driver.find_element_by_id('select1')).select_by_value('saab')
按选项的文本选择
Select(driver.find_element_by_id('select1')).select_by_visible_text('Saab')
用例步骤重试:如果某个步骤执行不成功(一般而言是元素没找到),建议重试 2-3 次。这样可以提高用例执行的稳定性。
用例执行重试:一条用例执行失败,有可能和当时的网络环境等相关。建议在失败后,重试 2-3 次,降低类似的误报率。
通过 chrome option 进行模拟
在初始化 driver 时,选择不同的浏览器类型进行测试。
# 根据runtype 选择浏览器类型; 根据 devicename 选择需要模拟的手机型号
if runType == 'Chrome':
desired_caps_web = webdriver.DesiredCapabilities.CHROME
deviceList = ['Galaxy S5', 'Nexus 5X', 'Nexus 6P', 'iPhone 6', 'iPhone 6 Plus', 'iPad', 'iPad Pro']
if devicename!='' :
if devicename not in deviceList:
devicename = deviceList[2]
chrome_option = {
'args': ['lang=en_US','start-maximized'],
'extensions': [], 'mobileEmulation': {'deviceName': ''}
}
chrome_option['mobileEmulation']['deviceName'] = devicename
else:
chrome_option = {
'args': ['lang=en_US','--start-maximized'],
'extensions': []
}
desired_caps_web['goog:chromeOptions']=chrome_option
elif runType == 'Firefox':
desired_caps_web = webdriver.DesiredCapabilities.FIREFOX
# 初始化
server_url = 'http://172.16.70.12:4444/'
driver = webdriver.remote.webdriver.WebDriver(command_executor=server_url,desired_capabilities=desired_caps_web)
这里不展开。