selenium语法
学习目标
- 完成web自动化环境搭建
- 掌握八大元素定位方法
- 掌握浏览器操作的方法
- 掌握鼠标键盘操作的方法
- 掌握获取元素信息操作的方法
- 掌握下拉框、滚动条、原生弹窗操作的方法
- 掌握iframe框架、浏览器句柄切换的方法
- 掌握截图操作的方式
- 掌握元素等待操作的方式
- 掌握cookie操作的方式
- 完成自定义练习
1. 了解自动化测试
自动化测试:由代码程序代替手工操作,完成测试目的
① 优点:
- 较少的时间内运行更多的测试用例
- 自动化脚本可以重复运行
- 减少人为错误
- 克服手工测试的局限性
② 误区:
- 自动化测试能完全代替手工测试【×】
- 自动化测试比手工测试厉害【×】
- 自动化测试能发现更多的bug【×】
- 自动化适合所有的项目【×】
③ 自动化测试分类
- web自动化(python+selenium+pytest+POM)
- app自动化(python+appium+pytest+POM)
- 接口自动化(python+request+pytest)
- 单元自动化(白盒测试)
注意:
2. web自动化环境准备
- 下载安装谷歌浏览器(版本不能太低)
- 下载浏览器驱动
- 确认当前浏览器的版本
- 下载驱动:谷歌驱动地址:http://chromedriver.storage.googleapis.com/index.html
- 解压出exe执行文件,复制粘贴到python根目录下
- 安装selenium包(建议使用3.14.1版本)
3. 自动化启动浏览器
from selenium import webdriver
import time
# 获取浏览器驱动
driver = webdriver.Chrome()
# 打开指定网页
driver.get('file:///E:/pagetest/注册A.html')
time.sleep(2) # 休眠2秒
driver.quit() # 退出浏览器驱动
4. 八大元素定位方法
- id:元素的id属性定位
- name:元素的name属性定位
- class_name:元素的class属性定位
- tag_name:元素的标签名称定位
- link_text:超链接文本定位
- partial_link_text:部分超链接文本定位
- css:元素的css选择器路径定位
- xpath:元素的标签路径定位(xpath路径)
①. id定位
'''
id定位:
注意事项:
①对于html页面来说,原则上id是不允许重复的,应当能够用id定位到唯一元素,但是不排除编码不规范的情况
②要使用id定位,要求元素必须要有id属性,id属性不是必填项
'''
# 定位元素
username = driver.find_element_by_id('userA')
# 操控元素
username.send_keys('admin')
②. name定位
'''
name定位:
注意事项:
①对于html页面来说,name允许重复,使用find_element_by_name会定位到第一个满足条件的元素
②要使用name定位,要求元素必须要有name属性,name属性不是必填项
'''
password = driver.find_element_by_name('passwordA')
password.send_keys("123456")
③. class_name定位
'''
class_name定位:
注意事项:
①对于html页面来说,class是允许重复,使用find_element_by_class_name会定位到第一个满足条件的元素
②要使用class_name定位,要求元素必须要有class_name属性,class_name属性不是必填项
③若一个元素拥有多个class属性,只要任意选择一个class即可
'''
tel = driver.find_element_by_class_name('telA')
tel.send_keys("13282135001")
email = driver.find_element_by_class_name('emailA')
email.send_keys("888888@qq.com")
④. tag_name定位
'''
tag_name定位:
注意事项:
①对于html页面来说,标签名会存在大量重复,使用find_element_by_tag_name会定位到第一个满足条件的元素
②元素一定会有标签名
'''
button = driver.find_element_by_tag_name('button')
button.click()
⑤. link_text定位
'''
link_text定位:
注意事项:
①对于html页面来说,超链接文本是允许重复的,使用find_element_by_link_text会定位到第一个满足条件的元素
②link_text的文字,是<a>标签内的文本,需要进行完全匹配
'''
sina = driver.find_element_by_link_text('新浪')
sina.click()
driver.back() # 回退页面
⑥. partial_link_text定位
'''
partial_link_text定位:
注意事项:
①对于html页面来说,超链接文本是允许重复的,使用find_element_by_partial_link_text会定位到第一个满足条件的元素
②partial_link_text的文字,是<a>标签内的部分文本,需要进行模糊匹配
'''
sina_2 = driver.find_element_by_partial_link_text('问 新')
sina_2.click()
driver.close() # 关闭当前页面
⑦. css选择器定位
'''
css选择器路径:
注意事项:
①css定位是根据css样式的选择器进行定位
②可以通过F12复制出selector路径,不需要自己写,但不能完全依赖复制功能
'''
username = driver.find_element_by_css_selector('#userA')
username.send_keys("admin")
email = driver.find_element_by_css_selector('body > div > fieldset > form > p:nth-child(4) > input')
email.send_keys("8888@qq.com")
⑧. xpath路径定位
'''
xpath路径定位:
注意事项:
①在XML文档中找元素信息,html也可以看做为xml文件
②xpath路径有2种:相对路径 和 绝对路径
③可以通过F12复制出xpath路径,不需要自己写,但不能完全依赖
'''
pwd = driver.find_element_by_xpath('//*[@id="passwordA"]')
pwd.send_keys("123")
tel = driver.find_element_by_xpath('/html/body/div/fieldset/form/p[3]/input')
tel.send_keys("18877772222")
5. By语法定位
原语法:find_element_by_id('userA')
By语法:find_element(By.ID, 'userA')
八大定位方法的By语法:
- id定位:find_element(By.ID, 'userA')
- name定位:find_element(By.NAME, 'passwordA')
- class_name定位:find_element(By.CLASS_NAME, 'telA')
- tag_name定位:find_element(By.TAG_NAME, 'button')
- link_text定位:find_element(By.LINK_TEXT, '新浪')
- partial_link_text定位:find_element(By.PARTIAL_LINK_TEXT, '问 新')
- css定位:find_element(By.CSS_SELECTOR, '#userA')
- xpath定位:find_element(By.XPATH, '//*[@id="passwordA"]')
①. By.ID
from selenium import webdriver
# 需要额外导入By包
from selenium.webdriver.common.by import By
# 定位元素
username = driver.find_element(By.ID, 'userA')
# 操控元素
username.send_keys('admin')
②. By.NAME
password = driver.find_element(By.NAME, 'passwordA')
password.send_keys("123456")
③. By.CLASS_NAME
tel = driver.find_element(By.CLASS_NAME, 'telA')
tel.send_keys("13282135001")
email = driver.find_element(By.CLASS_NAME, 'emailA')
email.send_keys("888888@qq.com")
④. By.TAG_NAME
button = driver.find_element(By.TAG_NAME, 'button')
button.click()
⑤. By.LINK_TEXT
sina = driver.find_element(By.LINK_TEXT, '新浪')
sina.click()
driver.back() # 回退页面
⑥. By.PARTIAL_LINK_TEXT
sina_2 = driver.find_element(By.PARTIAL_LINK_TEXT, '问 新')
sina_2.click()
driver.close() # 关闭当前页面
⑦. By.CSS_SELECTOR
username = driver.find_element(By.CSS_SELECTOR, '#userA')
username.send_keys("admin")
email = driver.find_element(By.CSS_SELECTOR, 'body > div > fieldset > form > p:nth-child(4) > input')
email.send_keys("8888@qq.com")
⑧. By.XPATH
pwd = driver.find_element(By.XPATH, '//*[@id="passwordA"]')
pwd.send_keys("123")
tel = driver.find_element(By.XPATH, '/html/body/div/fieldset/form/p[3]/input')
tel.send_keys("18877772222")
6. 元素生命周期
from selenium import webdriver
# 需要额外导入By包
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
username = driver.find_element(By.ID, 'userA') # 第一次定位username
button = driver.find_element(By.TAG_NAME,'button') # 定位按钮
button.click() # 点击按钮,会刷新页面
username2 = driver.find_element(By.ID, 'userA') # 第二次定位username
print(username) # 打印第一次定位的username
print(username2) # 打印第二次定位的username,会发现两次打印的编号不一致
username.send_keys('admin') # 往第一次定位的username里输入值,会失败
username2.send_keys('admin') # 往第二次定位的username里输入值,会成功
driver.close()
7. 定位一组元素
若使用原方法,则将find_element_by_id('userA') 改成 find_elements_by_id('userA')
若使用By方法,则将find_element(By.ID, 'userA') 改成 find_elements(By.ID, 'userA')
此时,返回的会是list类型的元素列表,需要使用下标定位具体的某一个元素对象
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get("file:///E:/pagetest/注册A.html")
inputs_1 = driver.find_elements_by_tag_name("input") # 定位标签名是“input”的所有元素
inputs_2 = driver.find_elements(By.TAG_NAME, "input") # 定位标签名是“input”的所有元素
print(len(inputs_2), inputs_2) # 打印元素列表的长度,即有多个满足条件的元素
inputs_2[0].send_keys("123456") # 使用下标定位某一个元素,才能进行正常元素操作
inputs_2[1].send_keys("1234567")
inputs_2[2].send_keys("123456789")
driver.close()
8. 浏览器操作
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# -------------------------对浏览器的操作-------------------------
driver.maximize_window() # 浏览器窗口最大化
time.sleep(1)
driver.set_window_size(500, 300) # 设置浏览器宽高,单位:像素 px
time.sleep(1)
driver.set_window_position(200, 300) # 设置浏览器坐标位置,单位:像素px
time.sleep(1)
driver.back() # 后退一页
time.sleep(1)
driver.forward() # 前进一页
time.sleep(1)
driver.refresh() # 刷新页面
time.sleep(1)
print(driver.title) # 获取当前页面标题
print(driver.current_url) # 获取当前页面url
driver.close() # 关闭当前浏览器窗口
driver.quit() # 退出浏览器驱动
9. 鼠标操作
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# ------------------------------鼠标操作------------------------
from selenium.webdriver.common.action_chains import ActionChains
action = ActionChains(driver) # 实例化鼠标操作类
button = driver.find_element_by_tag_name('button')
button.click() # 普通的单击操作,不属于【鼠标类】的方法,不实例化鼠标类,也可执行单击操作
username = driver.find_element_by_id('userA')
username.send_keys("admin")
action.double_click(username).perform() # 双击指定的元素,并提交事件
username = driver.find_element_by_id('userA')
username.send_keys("admin")
action.context_click(username).perform() # 在指定元素上右击鼠标,并提交事件
button = driver.find_element_by_tag_name('button')
action.move_to_element(button).perform() # 将鼠标移动到指定元素上
action.move_by_offset(280,465).perform() # 将鼠标移动到指定坐标xy上
driver.get("file:///E:/pagetest/drag.html")
red = driver.find_element_by_xpath('//*[@id="div1"]')
blue = driver.find_element_by_xpath('//*[@id="div2"]')
action.drag_and_drop(red,blue).perform() # 将[源元素]移动到[目标元素]上
time.sleep(1)
action.drag_and_drop_by_offset(blue, 100, 200).perform()
# 以当前元素位置为0点,x:正数向右移动 负数向左移 y:正数向下移 负数向上移
# 注意元素层级关系
注意:在同一条用例、同一个执行脚本中,尽量不要重复perform提交
10. 键盘操作
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# ----------------------键盘操作-------------------------
from selenium.webdriver.common.keys import Keys
username = driver.find_element_by_id('userA')
tel = driver.find_element_by_id('telA')
username.send_keys('admin')
username.send_keys(Keys.BACK_SPACE)
time.sleep(1)
username.send_keys(Keys.SPACE)
time.sleep(1)
username.send_keys(Keys.TAB)
username.send_keys(Keys.CONTROL, 'a')
time.sleep(1)
username.send_keys(Keys.CONTROL, 'c')
time.sleep(1)
tel.send_keys(Keys.CONTROL, 'v')
time.sleep(1)
tel.clear()
time.sleep(1)
driver.close()
11. 获取元素信息操作
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# --------------------获取元素信息---------------------
username = driver.find_element_by_id('userA')
print(username.size) # 获取元素尺寸
sina = driver.find_element_by_link_text('新浪')
print(sina.text) # 元素内的文本信息
print(username.get_attribute('placeholder')) # 获取元素的指定属性值
username.send_keys("admin")
print(username.get_attribute('value')) # input输入框有默认属性value,即用户的输入/选择的内容
span_1 = driver.find_element_by_xpath('/html/body/div/fieldset/form/p[5]/span')
print(span_1.is_displayed()) # 判断元素是否可见,可见返回True,不可见返回False
print(username.is_displayed())
button_1 = driver.find_element_by_css_selector('body > div > fieldset > form > p:nth-child(5) > button')
button_2 = driver.find_element_by_css_selector('#cancelA')
print(button_1.is_enabled()) # 判断元素是否可用,可用返回True,不可用返回False
print(button_2.is_enabled())
pga = driver.find_element_by_id('pga')
lia = driver.find_element_by_id('lia')
print(pga.is_selected()) # 判断元素是否被选中,选中返回True,未选中返回False
print(lia.is_selected())
driver.quit()
12. 下拉框操作
注意:此方法仅适用于原生下拉框操作,目前很多页面上的下拉框是由其他标签+css样式组成的,外表看上去像下拉框,但并非原生下拉框
from selenium import webdriver
import time
from selenium.webdriver.support.select import Select
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# 原生下拉框操作
city = driver.find_element_by_id('selectA')
select = Select(city)
select.select_by_index(2) # 选择下标=2的选项,此处下标从0开始
time.sleep(1)
select.select_by_value('sz') # 选择value值=sz的选项
time.sleep(1)
select.select_by_visible_text('北京') # 选择文本=‘北京’的选项
time.sleep(1)
driver.close()
13. 滚动条操作
注意:并非所有页面都支持此操作方式
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# 滚动条操作:
'''
selenium没有提供滚动条操作事件,但是提供了js代码运行方法,因此控制滚动条需要先编写js代码,再让selenium运行js
'''
# 将滚动条移动到最底部
js_1 = "window.scrollTo(0,10000)" # 左边距0,上边距10000
driver.execute_script(js_1)
time.sleep(1)
# 将滚动条移动到最上方
js_2 = "window.scrollTo(0,0)"
driver.execute_script(js_2)
time.sleep(1)
# 将滚动条移动到其他位置
js_3 = "window.scrollTo(0,100)"
driver.execute_script(js_3)
time.sleep(1)
driver.close()
14. 原生弹窗操作
注意:此操作方式仅使用于原生弹窗,有部分弹窗是由其他标签+css组成的,并非原生弹窗
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# 原生弹窗处理
'''
网页中常见的三种原生弹窗:
①alert弹窗:标题、提示文本、【确定】按钮
②confirm弹窗:标题、提示文本、【确定】按钮、【取消】按钮
③prompt弹窗:标题、提示文本、输入框、【确定】按钮、【取消】按钮
因为弹窗会影响页面其他元素的操作,所以当弹窗被触发后,应当先处理掉弹窗
'''
driver.find_element_by_id('alerta').click()
time.sleep(1)
alert = driver.switch_to.alert # 获取弹窗对象
print(alert.text) # 获取弹窗“提示文本”
alert.accept() # 点击【确定】按钮
time.sleep(1)
driver.find_element_by_id('confirma').click()
time.sleep(1)
confirm = driver.switch_to.alert # 获取弹窗对象
print(confirm.text)
confirm.accept() # 点击【确定】按钮
# confirm.dismiss() # 点击【取消】按钮
driver.find_element_by_id('prompta').click()
time.sleep(1)
prompt = driver.switch_to.alert # 获取弹窗对象
print(prompt.text)
prompt.send_keys('123456') # 输入(谷歌浏览器看不到输入的内容)
prompt.accept() # 点击【确定】按钮
# prompt.dismiss() # 点击【取消】按钮
driver.close()
15. iframe框架切换
注意:HTML代码中如果存在iframe框架,相当于是嵌套了另一个页面进来,需要切换框架焦点,才能操作嵌套进来的页面
from selenium import webdriver
import time
# --------------------页面中的iframe框架切换--------------------
driver = webdriver.Chrome()
driver.get("file:///E:/pagetest/注册实例.html")
driver.find_element_by_id('userA').send_keys('admin') # 定位主页面元素,并输入值
time.sleep(1)
frame_A = driver.find_element_by_id('idframe1') # 定位到A页面的iframe框架
driver.switch_to.frame(frame_A) # 焦点切换至A页面
driver.find_element_by_id('AuserA').send_keys("adminAAAA")
time.sleep(1)
driver.switch_to.default_content() # 回退到默认主界面,很重要!!!
frame_B = driver.find_element_by_id('idframe2') # 定位到B页面的iframe框架
driver.switch_to.frame(frame_B) # 焦点切换至B页面
driver.find_element_by_id('BuserA').send_keys('adminBBBBB')
time.sleep(1)
driver.close()
16. 浏览器句柄切换
注意:如果操作过程中,弹出了另一个浏览器窗口,则需要切换窗口句柄,才能操作新的浏览器窗口的页面
from selenium import webdriver
import time
# ---------------------浏览器窗口切换------------------------
'''
句柄:每个浏览器窗口的唯一标识
'''
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
handles = driver.window_handles # 获取全部句柄
print(handles)
driver.find_element_by_id('fw').click()
handles = driver.window_handles # 获取全部句柄
print(handles)
driver.switch_to.window(handles[-1]) # 切换到最新的句柄
handles_1 = driver.current_window_handle # 获取当前句柄
print(handles_1)
driver.find_element_by_xpath('/html/body/div[7]/div[1]/div[1]/ul[1]/li[2]/a').click()
time.sleep(1)
driver.quit()
17. 截图
'''
窗口截图:把被测系统的当前窗口界面截图,保存到指定目录下,保存成功 返回True,保存失败 返回False
文件保存路径:
1.截图的文件名不能包含以下字符:\ / : * ? # " < > |
2.可以使用相对路径 或 绝对路径
'''
from selenium import webdriver
import time
import datetime
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
cur_time = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S-%f')
print(cur_time)
driver.get_screenshot_as_file(f'./img/bug{cur_time}.png') # 相对路径
# driver.get_screenshot_as_file(r'E:\bug01.png') # 绝对路径
time.sleep(1)
driver.close()
18. 隐式等待
# 隐式等待:全局等待,在规定时间内等待页面中所需要的元素,如果超时未加载出元素,则报错
'''
如果设置隐式等待时间10s:
①10s内元素全部加载完成,会继续执行后续代码
②10s后,元素未全部加载完,则报错
③如果仅花费6s完成全部元素加载,剩下的4s不再等待
'''
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
driver.implicitly_wait(10)
element_1 = driver.find_element_by_xpath('/html/body/div/div[2]/div[1]/input[1]')
element_2 = driver.find_element_by_xpath('/html/body/div/div[2]/div[1]/input[2]')
driver.quit()
19. 显式等待
from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
driver = webdriver.Chrome()
driver.get('file:///E:/pagetest/注册A.html')
# 显式等待:针对单一元素进行等待,如果超时未加载出指定元素,则报错
'''
如果设置显式等待时间10s,每0.1s监测一次:
①10s内指定元素加载完成,会继续执行后续代码
②10s内的每次监测均未找到指定元素,则报错
③如果仅花费6s指定元素加载完成,剩下的4s不再等待
'''
element_1 = WebDriverWait(driver, 5, 0.1).until(lambda x: x.find_element_by_xpath('/html/body/div/div[2]/div[1]/input[1]'))
element_2 = WebDriverWait(driver, 10, 0.1).until(lambda x: x.find_element_by_xpath('/html/body/div/div[2]/div[1]/input[2]'))
driver.quit()
20. 强制等待
import time
time.sleep(2) # 强制等待2s
21. cookie操作
1. cookie操作
Cookie:一种客户端机制,浏览器第一次访问服务器时,由服务器返回,然后保存在浏览器中。
项目中常常会使用cookie记录一些不太机密的缓存信息,也常常用来记录登录状态。
'''
cookie操作目的:以添加cookie的方式,绕过复杂的登录流程
思路:
手动登录-->拿到自己有效的用户身份信息cookie-->运行python代码时,将用户身份信息追加到cookie缓存中-->刷新页面
'''
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.maximize_window()
time.sleep(5)
baidu = {'name': 'BDUSS', 'value': 's0R1ROWTVQczhLcDZycGlaOGZyWUlkaX5VbXlFOERTYmh1SW5LQn5XRXkxMzFqSUFBQUFBJCQAAAAAAAAAAAEAAACdST5IssWyu8rH0KG6otfTxNgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADJKVmMySlZjN2'}
driver.add_cookie(baidu)
driver.refresh()
time.sleep(2)
driver.quit()
自定义练习
任意选择以下的网站之一,完成自动化练习,编码100行,操作动作不限:
- 时光钥匙:https://www.shiguangkey.com/
- CSDN:https://www.csdn.net/
- 百度:https://www.baidu.com/
- 哔哩哔哩:https://www.bilibili.com/
- 京东:https://www.jd.com/