传统自动化测试:基于UI层,黑盒->程序或工具来执行
分层的自动化测试:倡导从UI单层到黑盒和白盒的多层的自动化测试。敏捷大师Mike Cohn首次提出测试金字塔的概念,Martin Fowler大师在此基础上提出了分层自动化测试的概念。
UI自动化测试主要是实现手工测试用例,可降低回归测试的成本。通常如果软件需求变动不频繁、项目周期较长、自动化测试脚本可重复利用,适合进行自动化测试。
主流的Web UI自动化测试库之一,到目前经历了4个大版本,本文内容基于selenium-4.4.3。selenium由一些插件和类库组成:selenium IDE(浏览器的录制与回放)、selenium Grid(在多台计算机或异构环境中进行测试)、selenium webDriver(客户端API接口,控制浏览器驱动)。
appium,(application+selenium)是移动平台上主流的自动化测试工具之一。封装了标准selenium客户端类库,为用户提供常见的json格式的selenium命令,以及额外的移动设备控制相关的命令。
"""一组基础的用例示例,注意v4版本的少数改动,比如定位一个元素现在用find_element(self,by,value),一组就用find_elements"""
from selenium import webdriver
from selenium.webdriver.common.by import By # 导入By这个类
import time
driver = webdriver.Chrome() # 创建浏览器对象driver
driver.get("https://cn.bing.com/?mkt=zh-CN") # 调用get()访问必应中国首页
driver.find_element(By.ID, "sb_form_q").send_keys('python') # 定位到输入框,并输入“python”
driver.find_element(By.ID, "search_icon").click() # 定位到搜索图标并点击
time.sleep(3) # 休息3秒
driver.close() # 关闭浏览器
id、name、class、tag
link(By.LINK_TEXT、By.PARTIAL_LINK_TEXT)
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("https://www.runoob.com/python3/python3-tutorial.html")
driver.find_element(By.LINK_TEXT, "JAVA").click() # 通过含herf的元素的文本内容来定位元素“JAVA”
time.sleep(2)
driver.find_element(By.PARTIAL_LINK_TEXT, "简介").click() # 通过部分文本内容找到“Java 教程”
time.sleep(2)
driver.close()
xpath:XML路径定位器,一般右键复制路径,或者掌握(nodename / // . … @ *)表达式后自己写
css选择器:类似xpath,复制或掌握相关语法后自己写路径
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
# 常见的有send_keys(value)、click()、clear()、submit()(提交表单)等等
# 设置浏览器窗口的宽500,高400
driver.set_window_size(500, 400)
# 窗口最大化
driver.maximize_window()
# 获取输入框的尺寸
size = driver.find_element(By.ID, 'kw').size
print(size)
# 获取左下角“关于百度”的文本
text = driver.find_element(By.CLASS_NAME, 'text-color').text
print(text)
# 返回元素的属性值,可以是id、name、type等任意属性
attribute = driver.find_element(By.ID, 'kw').get_attribute('name')
print(attribute)
# 返回的是元素是否可见的值,为True或者False
r = driver.find_element(By.ID, 'kw').is_displayed()
print(r)
time.sleep(3)
driver.close()
'''
webdriver中鼠标操作的相关方法都在ActionChains类中。常用的有:
perform() ——执行ActionChains类中存储的所有行为
context_click() ——右击 double_click() ——双击
drag_and_drop() ——拖动 move_to_element() ——悬停
'''
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.maximize_window()
e = driver.find_element(By.ID, 's-usersetting-top') # 找到“设置”按钮
ActionChains(driver).move_to_element(e).perform() # 执行“鼠标悬停”的动作
通常用得较少,特殊情况如需要输入特殊字符时采用。
from selenium.webdriver.common.keys import Keys # 要先导入Keys这个类
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://www.baidu.com")
e = driver.find_element(By.ID, 'kw')
e.send_keys('python123')
e.send_keys(Keys.BACK_SPACE) # 删除键
"""
send_keys(Keys.SPACE) ——空格键 send_keys(Keys.TAB) ——制表键
send_keys(Keys.ENTER) ——回车键 send_keys(Keys.ESCAPE) ——回退键
send_keys(Keys.CONTROL,'a') ——Ctrl+a,类似还有Ctrl+c,Ctrl+x,Ctrl+v
send_keys(Keys.F1) ——类似还有F2……F12
"""
from selenium import webdriver
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
print('Before search====================')
def test():
# 打印当前页面title
title = driver.title
print('title:' + title)
# 打印当前页面的URL
now_url = driver.current_url
print('url:' + now_url)
test()
driver.find_element(By.ID, 'kw').send_keys('selenium')
driver.find_element(By.ID, 'su').click()
print()
print('After search====================')
test()
# 打印搜索结果条数的文本
num = driver.find_element(By.XPATH, '//*[@id="tsn_inner"]/div[2]/span').text
print('result:' + num)
# 搜索前后获取的title、current_url、text等验证信息,可以用作自动化测试的断言
webdriver的元素等待有两种:显示等待、隐式等待。
显示等待
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
"""
WebDriverWait(driver, timeout, poll_frequency=0.5, ignored_exceptions=None)
在设置的时间内,默认每隔一段时间检查一次当前页面元素是否存在,如果超时,就抛出异常。
WebDriverWait()一般与until()或until_not()配合使用。until(method, message=''),
expected_conditions中包含多种预期条件判断方法,用于传入method。
"""
e = WebDriverWait(driver, 5, 0.5).until(EC.visibility_of_element_located((By.ID, 'kw')))
e.send_keys('selenium')
driver.close()
隐式等待
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from time import ctime
driver = webdriver.Chrome()
driver.implicitly_wait(5) # 设置显示等待时间,单位是s
driver.get('https://www.baidu.com')
# 在等待时间里一直找元素,找到了会继续执行程序,到最后都找不到的话,就会抛出异常
try:
print(ctime())
driver.find_element(By.ID, 'kw_no').send_keys('selenium')
except NoSuchElementException as e:
print(e)
finally:
print(ctime())
driver.close()
表单切换
切换到登录表单的案例:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get('http://www.126.com')
driver.maximize_window()
time.sleep(2)
"""
由于webdriver只能在一个页面上识别和定位元素,一开始是在最外层的,所以要先定位到表单,然后切换到登录表单里去。
switch_to.frame()默认可以直接传入表单的id或name值。该登录表单的id值是x-URS-iframe1665184560161.8542,
后面一串数字是随机变化的,于是采用css定位,用'^='来筛选以'x-URS-iframe'开头的元素,达到定位目的。
"""
login_frame = driver.find_element(By.CSS_SELECTOR, 'iframe[id^="x-URS-iframe"]')
driver.switch_to.frame(login_frame)
driver.find_element(By.NAME, 'email').send_keys('username')
driver.find_element(By.NAME, 'password').send_keys('password')
driver.find_element(By.ID, 'dologin').click()
# 切换到最外层的页面
driver.switch_to.default_content()
driver.close()
窗口切换
在百度的首页和账号注册页之间切换的案例:
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
driver.maximize_window()
# 获取当前窗口(百度首页)的句柄
search_windows = driver.current_window_handle
driver.find_element(By.LINK_TEXT, '登录').click()
driver.find_element(By.LINK_TEXT, '立即注册').click()
# 虽然打开了注册页面,但是焦点还是在最初的首页,所以要切换句柄
# 获取当前所有打开的窗口句柄
all_handles = driver.window_handles
# 进入注册窗口
for handle in all_handles:
if handle != search_windows:
driver.switch_to.window(handle)
print(driver.title)
driver.find_element(By.NAME, 'userName').send_keys('username')
driver.find_element(By.NAME, 'phone').send_keys('13500000000')
time.sleep(2)
driver.close()
driver.switch_to.window(search_windows) # 切换窗口
print(driver.title)
time.sleep(2)
driver.quit()
警告框
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.maximize_window()
driver.find_element(By.ID, 's-usersetting-top').click()
driver.find_element(By.LINK_TEXT, '搜索设置').click()
driver.find_element(By.LINK_TEXT, '保存设置').click()
# 获取警告框
alert = driver.switch_to.alert
time.sleep(2)
# 打印警告框提示信息
print(alert.text)
# 接受警告框
alert.accept()
下拉框
(1)select类型下拉框
# 要导入Select类
from selenium.webdriver.support.select import Select
# 先定位到下拉框元素sel,有3种方法选择要定位的下拉项:
Select(sel).select_by_index(index) # 索引
Select(sel).select_by_value(value) # value属性的值
Select(sel).select_by_visible_text(text) # 选项中的文本
(2)非select类型下拉框
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.maximize_window()
# 定位设置按钮
driver.find_element(By.ID, 's-usersetting-top').click()
driver.find_element(By.LINK_TEXT, '高级搜索').click()
# 定位到‘全部时间’下拉框
sel = driver.find_element(By.XPATH, '//*[@id="adv-setting-gpc"]/div')
print(sel.text)
# 这里的点击必不可少
sel.click()
time.sleep(2)
# 和select类型下拉框不同,这里直接定位到“最近一天”这个选项
driver.find_element(By.XPATH, '//*[@id="adv-setting-gpc"]/div/div[2]/div[2]/p[2]').click()
print(sel.text)
driver.quit()
有时为验证cookie的正确性需要进行获取、修改等操作。
'''相关方法'''
get_cookies() # 获取所有cookie
get_cookie(name) # 返回字典中key为‘name’的cookie
add_cookie(coolie_dict) # 添加
delete_cookie(name) # 删除
delete_all_cookies()
自动化测试模型分为:
早期自动化测试的一种形式,即单纯地模拟用户完整的操作场景。通过录制或编写对应应用程序的操作步骤而产生了相应的线性脚本,每个脚本相对独立,不产生依赖与调用。
在线性测试的基础上,把重复的操作封装成公共模块,测试过程中需要用到时,直接调用模块就行,减少了不必要的操作,提高了测试用例的可维护性。
数据的改变驱动自动化测试的执行,最终引起测试结果的改变。也就是把数据驱动所需要的测试数据参数化,可以有多重方式来存储和管理这些参数化的数据。比如把用户登录时要测试的用户名、密码两项在脚本中用user、password这两个参数代替,而不同测试用例的用户名、密码肯定不尽相同,于是统一放在一个xml文件里(还有Jason、txt、CSV等格式)。
也叫表驱动测试或基于动作测试。关键字驱动测试的框架(如Robot Framework)基本工作是将测试用例分为4部分:测试步骤、测试步骤中的对象(页面对象或元素,如用户名、密码)、测试对象执行的动作、测试对象需要的数据。
其核心思想是把编码从测试用例和测试步骤中分离出来,避免测试人员直接接触代码,使手工测试人员也可以编写自动化脚本。多是以“填表格”的形式来“写”脚本。