软件测试元素定位
#用CV工程师的方式逃离CV#从开发到测试的文明退化史
1. ID元素定位
- 基于元素属性中唯一的
id
值定位(动态ID除外),是首选定位方式
driver.find_element_by_id('id')
driver.find_element(By.ID, 'id')
2. name元素定位
- 基于元素属性中的
name
值定位(可能出现重名)
driver.find_element_by_name('name')
driver.find_element(By.NAME, 'name')
3. class_name元素定位
- 基于元素
class
样式定位(易重复) - 参数只能是一个class值(多个class需选其一)
driver.find_element_by_class_name('class_name')
driver.find_element(By.CLASS_NAME, 'class_name')
4. tag_name元素定位
- 通过元素标签名定位(重复度高,需二次筛选)
driver.find_element_by_tag_name('tag_name')
driver.find_element(By.TAG_NAME, 'tag_name')
5. css_selector元素定位
- 支持多种定位方式:id/class/属性/子元素/后代元素/index/兄弟元素等
5.1 通过ID定位
driver.find_element_by_css_selector('div#kw')
driver.find_element(By.CSS_SELECTOR, 'div#kw')
5.2 通过class定位
driver.find_element_by_css_selector('input.is_put')
driver.find_element(By.CSS_SELECTOR, 'input.is_put')
5.3 通过属性定位
driver.find_element_by_css_selector('input[name=kw]')
driver.find_element(By.CSS_SELECTOR, 'input[name=kw]')
5.4 通过子元素定位
- CSS使用
>
表示子元素
driver.find_element_by_css_selector('div#kw > input')
driver.find_element(By.CSS_SELECTOR, 'div#kw > input')
5.5 通过后代元素定位
driver.find_element_by_css_selector('div#kw input')
driver.find_element(By.CSS_SELECTOR, 'div#kw input')
5.6 通过index定位
driver.find_element_by_css_selector('div#kw > input:nth-child(1)')
driver.find_element(By.CSS_SELECTOR, 'div#kw > input:nth-child(1)')
5.7 通过兄弟元素定位
- 仅定位下方第一个兄弟元素
driver.find_element_by_css_selector('span#kw + input')
driver.find_element(By.CSS_SELECTOR, 'span#kw + input')
5.8 CSS常见语法一览表
语法 | 说明 | 示例 |
---|---|---|
* |
通用元素选择器 | * |
E |
标签选择器 | input |
.info |
class选择器 | .is_put |
#footer |
id选择器 | #kw |
E,F |
多元素选择器 | div, span |
E F |
后代元素选择器 | div input |
E > F |
子元素选择器 | div > input |
E + F |
毗邻元素选择器(第一个兄弟) | span + input |
E ~ F |
同级元素选择器(所有后续兄弟) | span ~ input |
E[att='val'] |
属性精确匹配 | input[name='kw'] |
E[att^='val'] |
属性值开头匹配 | a[href^='https'] |
E[att$='val'] |
属性值结尾匹配 | img[src$='.png'] |
E[att*='val'] |
属性值包含匹配 | div[class*='nav'] |
E:contains() |
内容包含匹配 | p:contains('Hello') |
E:not(s) |
反向选择器 | input:not([disabled]) |
6. link_text元素定位
- 基于超链接的完整文本定位(仅限
<a>
标签)
driver.find_element_by_link_text('link_text')
driver.find_element(By.LINK_TEXT, 'link_text')
7. partial_link_text元素定位
- 基于超链接的部分文本模糊匹配(仅限
<a>
标签)
driver.find_element_by_partial_link_text('part_text')
driver.find_element(By.PARTIAL_LINK_TEXT, 'part_text')
8. xpath元素定位
- 通过XML路径语法定位HTML元素
8.1 绝对路径定位(不推荐)
driver.find_element_by_xpath('/html/body/div[4]/div[1]/a')
driver.find_element(By.XPATH, '/html/body/div[4]/div[1]/a')
8.2 相对路径定位
driver.find_element_by_xpath('//form/span')
driver.find_element(By.XPATH, '//form/span')
8.3 元素属性定位
单属性:
driver.find_element_by_xpath("//input[@name='pwd']")
driver.find_element(By.XPATH, "//input[@name='pwd']")
多属性:
driver.find_element_by_xpath("//a[@title='tutorial' and @rel='follow']")
driver.find_element(By.XPATH, "//a[@title='tutorial' and @rel='follow']")
8.4 属性模糊匹配
starts-with:
driver.find_element_by_xpath("//label[starts-with(@class,'btn')]")
driver.find_element(By.XPATH, "//label[starts-with(@class,'btn')]")
contains:
driver.find_element_by_xpath("//label[contains(@class,'btn')]")
driver.find_element(By.XPATH, "//label[contains(@class,'btn')]")
8.5 文本定位
精确匹配:
driver.find_element_by_xpath("//span[text()='下一步']")
driver.find_element(By.XPATH, "//span[text()='下一步']")
模糊匹配:
driver.find_element(By.XPATH, "//span[starts-with(text(),'下一步')]")
driver.find_element(By.XPATH, "//span[contains(text(),'下一步')]")
8.6 xpath常见语法
表达式 | 说明 | 示例 |
---|---|---|
/ |
从根节点开始 | /html/div |
// |
从任意节点开始 | //input |
. |
当前节点 | //input/. |
.. |
父节点 | //input/.. |
@ |
属性选择 | //input[@name] |
* |
通配符 | //div/* |
9. XPATH 和 CSS 基本语法对比
功能 | CSS3 语法 | XPATH 语法 |
---|---|---|
所有元素 | * |
//* |
所有p元素 | p |
//p |
所有p元素的子元素 | p > * |
//p/* |
根据ID获取元素 | #id |
//*[@id='id'] |
根据Class获取元素 | .class |
//*[contains(@class,'class')] |
拥有某个属性的元素 | *[title] |
//*[@title] |
所有p元素的第一个子元素 | p > *:first-child |
//p/*[1] |
所有拥有子元素的p元素 | ✗ | //p[a] |
下一个兄弟元素 | p + * |
//p/following-sibling::*[1] |
10. Selenium 4.0 相对定位器
- 通过元素间的空间关系定位
10.1 Above(上方)
email_locator = locate_with(By.TAG_NAME, "input").above((By.ID, "password"))
10.2 Below(下方)
password_locator = locate_with(By.TAG_NAME, "input").below((By.ID, "email"))
10.3 Left of(左边)
cancel_locator = locate_with(By.TAG_NAME, "button").to_left_of((By.ID, "submit"))
10.4 Right of(右边)
submit_locator = locate_with(By.TAG_NAME, "button").to_right_of((By.ID, "cancel"))
10.5 Near(附近)
email_locator = locate_with(By.TAG_NAME, "input").near((By.ID, "lbl-email"))
10.6 链式定位
submit_locator = locate_with(By.TAG_NAME, "button")
.below((By.ID, "email"))
.to_right_of((By.ID, "cancel"))
11. 特殊定位方式
11.1 匹配所有元素
plants = driver.find_elements(By.TAG_NAME, "li")
for e in plants:
print(e.text)
11.2 元素内定位
parent = driver.find_element(By.TAG_NAME, 'div')
children = parent.find_elements(By.TAG_NAME, 'p')
11.3 活动元素定位
driver.find_element(By.ID, "kw").send_keys("搜索词")
active_elem = driver.switch_to.active_element
print(active_elem.get_attribute("name"))
12. 元素信息获取
12.1 是否显示
is_visible = driver.find_element(By.NAME, 'login').is_displayed()
12.2 是否被选定
is_checked = driver.find_element(
By.CSS_SELECTOR, "input[type='checkbox']:first-of-type"
).is_selected()
12.3 获取标签名
tag = driver.find_element(By.CSS_SELECTOR, "h1").tag_name
12.4 获取元素矩形
rect = driver.find_element(By.CSS_SELECTOR, "h1").rect
# 返回值包含: x, y, width, height
12.5 获取CSS值
color = driver.find_element(
By.LINK_TEXT, "More information..."
).value_of_css_property('color')
12.6 获取文本
text = driver.find_element(By.CSS_SELECTOR, "h1").text