软件测试元素定位
#用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_name12.4 获取元素矩形
rect = driver.find_element(By.CSS_SELECTOR, "h1").rect
# 返回值包含: x, y, width, height12.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