软件测试基础
一.软件测试基本原则
1.测试显示软件存在缺陷
测试只能证明软件中存在缺陷,但并不能证明软件中不存在缺陷。软件测试是为了降低存在缺陷的可能性,即使没找到缺陷,也不能证明软件是完美的。
2.穷尽测试是不可能的
软件规模越来越大,复杂度越来越高,想做到完全性的测试是不可能的。在测试阶段,测试人员可以根据风险和优先级来进行集中和高强度的测试,从而保证软件的质量。
3.测试尽早介入
保证软件质量,降低风险和成本。测试人员一般在需求阶段就开始介入,使缺陷在需求和设计阶段就被发现,缺陷发现越早,修复成本越小
4.缺陷集群性
缺陷集群性表明小部分模块包含大部分缺陷。软件测试中存在Pareto原则:80%的缺陷发现在20%的模块中。一个功能模块发现的缺陷越高,存在未发现缺陷的概率也越高。
5.杀虫剂悖论
反复使用相同的杀虫剂会导致害虫对杀虫剂产生免疫而无法杀死害虫。软件测试也一样。如果一直使用相同的测试方法或手段,可能无法发现新的bug。
为了解决这个问题,测试用例应当定期修订和评审,增加新的或不同的测试用例帮助发现更多的缺陷。
测试人员不能一直依赖于现有的测试技术,而要不断的提升测试方法以提高测试效率。
6.测试活动依赖于测试内容
根据业务的不同,软件测试内部也分为不同的行业,比如游戏行业、电商行业、金融行业。不同的行业,测试活动的开展都有所不同,比如测试技术、测试工具的选择,测试流程都不尽相同,所以软件测试的活动开展依赖于所测试的内容。
7.“没有错误就是好”谬论
有可能99%没有bug的软件也是不能使用的。如果对错误的需求进行了彻底的测试,这种情况就发生了。软件测试不仅是找出缺陷,同时也需要确认软件是否满足需求。如果开发出来的产品不满足用户的需求,即便找到和修复了缺陷也作用不大。
二.软件测试流程
1、需求分析 目的:让产品、开发、测试、设计对需求理解达成—致,减少开发过程中由于理解不一致产生的 bug,同时尽早发现需求设计中存在的问题,尽早修改,降低修复成本产品经理收集需求,召集开发、测试、设计参与需求评审会议。
需求包括:产品文档、产品原型
注意:参与评审会议前,先熟悉需求 2、编写测试计划和测试方案 目的:定义测试的范围、测试的方法、所需的资源、进度等,明确需要测试的产品项,需要覆盖的功能特性,需要执行的测试任务,每项任务的负责人,识别相关的风险。
计划和方案由测试负责人或者测试经理输出,同时需要跟开发负责人沟通确定时间。
计划和方案确定好之后需要发邮件通知相关人员
3、编写测试用例 定义︰测试用例是测试过程中很重要的一类文档,它是测试工作的核心、是一组在测试时输入输出的标准、是软件需求的具体对照。测试用例能在很大的程度上反应一个测试人员的能力。
测试用例的编写和设计也是有对应的设计方法。
测试用例的要素:用例编号、用例名称、测试背景、前置条件、优先级、重要级、测试数据、测试步骤、预期结果、实际结果
4、测试用例评审 自的:针对所编写的用例进行查漏补缺参与人员:开发、产品、测试
5、接口测试(可选) 编写完用例后.开发没有转测试, 可以针对开发的后台服务器进行接口测试。
6、执行测试用例 准备工作:执行用例之前需要搭建测试环境。
通过手工或自动化执行测试用例.如果测试结果与用例的预期结果不符.那么就认为是BUG,也就是缺陷,需要将BUG通过缺陷管理工具记录下来方便管理跟踪。
自动化执行的用例是针对 7、提交测试报告 目的:在于总结测试阶段的测试过程及测试结果分析,描述系统是否达到需求并依此作为是否上线的依据。
测试报告内容:测试环境、测试模块、测试用例数、发现的BUG数、已解决BUG数、遗留BUG数、遗留风险、测试结论。
测试报告要以邮件的形式通知相关人员,包括开发、测试、项目经理、运维。
8、产品上线 产品上线之后需要做一些基本功能的验证,如果有问题,确认问题的影响以及修改问题的时间,如果一些界面元素的,问题不是很大,能够马上修改好的话就立马修改,如果问题影响大,那么会回退版本。
三.自动化测试能解决什么问题
1.解决-回归测试
2.解决-压力测试
3.解决-兼容性测试
4.提高测试效率,保证产品质量
回归测试:项目在发新版本之后对项目之前的功能进行验证
压力测试:可以理解多用户同时去操作软件,统计软件服务器处理多用户请求的能力
兼容性测试:不同浏览器(IE、Firefox、Chrome)等等
四.自动化测试的优点和误区
优点 1.较少的时间内运行更多的测试用例;
2.自动化脚本可重复运行;
3.减少人为的错误;
4.克服手工测试的局限性;
误区 1.自动化测试可以完全替代手工测试;
2.自动化测试一定比手工测试厉害;
3.自动化测试可以发掘更多的BUG;
4.自动化测试适用于所有功能;
五.哪些项目适合做自动化测试
1.需求变动不频繁
2.项目周期长
3.项目需要回归测试
六.自动化测试的分类
自动化测试分类:
-
Web自动化测试(本阶段学习的内容) -
移动自动化测试 -
接口自动化测试 -
单元测试-自动化测试 -
桌面的自动化测试 -
安全自动化测试 -
嵌入式设备的自动化测试
七.主流的Web自动化测试工具
1.QTP
QTP是一个商业化的功能测试工具,收费,支持web,桌面自动化测试。
2.Selenium selenium是一个开源的web自动化测试工具,免费,主要做功能测试。
3.Robot framework Robot Framework是一个基于Python可扩展地关键字驱动的测试自动化框架。
八.web自动化环境搭建
所需要的工具:
-
python -
pycharm编辑器 -
基于python的selenium模块 -
浏览器驱动 -
浏览器
九.selenium安装、卸载查看命令
1.selenium安装命令: pip install selenium
2.selenium卸载命令: pip uninstall selenium
3.selenium查看命令: pip show selenium
十.Web自动化测试步骤
1.安装浏览器驱动
- 查看谷歌浏览器版本号
- http://npm.taobao.org/mirrors/chromedriver/在这个链接下下载对应版本的驱动
- 解压驱动压缩包后放在Python文件的目录下
2.书写python代码
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
time.sleep(3)
driver.quit()
十一.Selenium-API操作
1.元素定位
目标:掌握id、name、class_name、tag_name、link_text、partial_link_text定位方法的使用
2.浏览器开发者工具
作用:快速定位元素,查看元素信息
- 打开方式:
- 进入浏览器点击F12,选择“elements”页签
- 在web页面上,右击元素选择检查,也可打开浏览器开发者elements的页签
3.Selenium定位元素的七种方式
-
id:通过元素的id属性值来定位元素的
element = driver.find_element_by_id(id)
- 实例(打开SSPU的OA办公界面并自动填入账号密码)
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
driver.find_element_by_id("username").send_keys("20181112937")
driver.find_element_by_id("password").send_keys("***********")
time.sleep(3)
driver.quit()
-
name:通过元素的name属性来定义元素
- 前提条件:元素必须要有name属性(name元素的属性值可以重复)
- name定义方法:
element = driver.find_element_by_name(name)
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
driver.find_element_by_name("username").send_keys("20181112937")
driver.find_element_by_name("password").send_keys("*********")
time.sleep(3)
driver.quit()
-
class_name:通过class的属性值来进行元素定位。class只使用其中一个进行元素定位
element = driver.find_element_by_class_name(class)
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
driver.find_element_by_class_name("login-username").send_keys("20181112937")
driver.find_element_by_class_name("login-password").send_keys("*********")
time.sleep(3)
driver.quit()
-
tag_name:通过标签名称来进行元素定位
- 问题:在同一个html页面中,相同标签的元素会有多个,如果有多个相同元素,默认选中第一个。(不建议使用)
- 定位方法:
element = driver.find_element_by_tag_name(tag_name)
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
driver.find_element_by_tag_name("input").send_keys("20181112937")
time.sleep(3)
driver.quit()
-
**link_text:用来定位超链接(a标签)元素 **
- 说明:通过a标签元素的全部文本内容进行元素定位
- 元素定位的方法:
element = driver.find_element_by_link_text(link_text)
r
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
driver.find_element_by_link_text("忘记密码?").click()
ime.sleep(3)
driver.quit()
-
partial_link_text:用来定位超链接(a标签)
- 说明:通过超链接的局部文本内容进行元素定位
- 元素定位方法:
element = driver.find_element_by_partial_link_text(partial_link_text)
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
driver.find_element_by_link_text("忘记密码?").click()
time.sleep(3)
driver.quit()
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://id.sspu.edu.cn/cas/login?service=https%3A%2F%2Foa.sspu.edu.cn%2Fsso%2Flogin.jsp%3FtargetUrl%3D%7Bbase64%7DaHR0cHM6Ly9vYS5zc3B1LmVkdS5jbi93dWkvbWFpbi5qc3A%3D")
elements = driver.find_elements_by_tag_name("input")
print(type(elements))
elements[0].send_keys("20181112937")
elements[1].send_keys("*********")
time.sleep(5)
driver.quit()
-
XPath:
- 使用XPath和CSS定位元素的原因:通过元素本身的信息无法精准定位到想要定位的元素时,可以通过xpath/css的层级结构进行定位
- XPath定位方法一:路径定位
element = driver.find_element_by_xpath(xpath)
element = driver.find_element_by_xpath(xpath)
element = driver.find_element_by_xpath(xpath)
element = driver.find_element_by_xpath(xpath)
-
CSS:
- tips:在selenium中推荐使用CSS定位,他比XPath更快
- CSS定位方法:
element = driver.find_element_by_css_selector(css_selector)
- CSS常用的选择器:
- id选择器:通过id属性选择元素
- class选择器:通过class属性选择元素
- 表达式:.class class表示class属性值
- 注意:只需要输入class中的一个值即可
- 元素选择器:通过标签名称(tag_name)选择元素
- 元素属性选择器:通过元素属性选择元素
- 表达式:[attribute=‘value’] attribute表示属性名称,value表示属性值
- 层级选择器:
- 父子层级 表达式:element1>element2 表示element2为element1的直接子元素
- 隔代层级 表达式:element1 element2 表示element2是element1下面的子元素,也称为后代元素
- 实例:
import time
十二.元素常用操作
- click() 单击元素
- send_keys() 模拟输入
- clear() 清除文本
十三.浏览器操作
-
maximize_window() :最大化浏览器窗口 --> 模拟浏览器最大化按钮 -
set_window_size(width, height):设置浏览器窗口大小 --> 设置浏览器宽、高(像素点),相当于通过浏览器边框改变浏览器宽高 -
set_window_position(x, y) :设置浏览器窗口位置 --> 设置浏览器位置 -
back():后退 --> 模拟浏览器后退按钮 -
forward() :前进 --> 模拟浏览器前进按钮 -
refresh(): 刷新 --> 模拟浏览器F5刷新 -
close():关闭当前窗口 --> 模拟点击浏览器关闭按钮 -
quit():关闭浏览器驱动对象 --> 关闭所有程序启动的窗口 -
title:获取页面title -
current_url:获取当前页面URL
import time
import time
十四.获取元素信息
-
获取元素的目的:用来判断操作结果 -
获取元素的常用方法:
十五.鼠标操作
- 实例化鼠标对象
action = ActionChains(driver)
- 调用鼠标方法
action.context_click(element)
- 执行鼠标事件
action.perform()
-
鼠标右击操作
- 注意:右击出来的菜单必须是html自定义的,否则无法操作
import time
-
鼠标双击操作 action.double_click(element)
实例: import time
-
鼠标悬停操作 action.move_to_element(element)
实例
-
鼠标拖动操作
action.drag_and_drop(element1,element2)
实例:
十六.键盘操作
-
键盘操作的步骤:
-
导包: from selenium.webdriver.common.key import Keys
-
使用封装好的键值进行操作 -
常用的键盘操作:
- send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
- send_keys(Keys.SPACE) 空格键(Space)
- send_keys(Keys.TAB) 制表键(Tab)
- send_keys(Keys.ESCAPE) 回退键(Esc)
- send_keys(Keys.ENTER) 回车键(Enter)
- send_keys(Keys.CONTROL,‘a’) 全选(Ctrl+A)
- send_keys(Keys.CONTROL,‘c’) 复制(Ctrl+C)
-
实例: import time
十七.元素等待
-
影响页面加载时间的因素
- 电脑配置(CPU,内存等)
- 网速
- 后台服务器(配置低,高并发的情况…)
-
元素等待的类型:
-
隐式等待:定位元素时,会先等待整个页面加载完成,如果能定位到元素则直接返回该元素,不触发等待;如果不能定位到该元素,则间隔一段时间后再去定位元素; 如果在达到最大时长时还没有找到指定元素,则抛出元素不存在的异常NoSuchElementException 。隐式等待只需要设置一次,对后面元素的定位方法都有效
-
显式等待:定位指定元素时,如果能定位到元素则直接返回该元素,不触发等待; 如果不能定位到该元素,则间隔一段时间后再去定位元素; 如果在达到最大时长时还没有找到指定元素,则抛出超时异常 TimeoutException,显式等待不需要等待整个页面的加载,而且只是针对单个元素有效
-
强制等待:强制等待就是暂停代码的执行
- 应用场景:
- 要等待的元素不需要去进行定位操作,但是该元素跟要操作的元素有业务的关联,一定要等待该元素加载完成后,才能对操作的元素操作成功
- 当需要获取的元素的文本信息是通过后台接口获取并渲染到元素中,此时需要加强制等待才能准确拿到对应的文本内容
十八.下拉框、弹出框、滚动条操作
十九.窗口切换
-
窗口切换:
-
原因:新打开的浏览器窗口如果不做窗口切换,无法对新打开的窗口进行相关操作 -
selenium中通过窗口句柄实现窗口切换的 -
实现方法:
- 获取当前窗口句柄
driver.current_window_handle
- 获取所有窗口句柄
driver.window_handles
- 切换窗口句柄
driver.switch_to.window(handle)
-
实例: import time
二十.frame切换
二十一.窗口截图
- **说明:**在selenium中,提供了截图方法,只需调用即可
- 方法:
driver.get_screenshot_as_file(imgpath)
二十二.验证码
- **说明:**一种随机生成的信息(数字,字母,汉字,图片等…)为了防止恶意的请求行为,增加应用的安全性
- 验证码的处理方式:
- 去掉验证码:测试环境下采用
- 设置万能验证码:生产环境和测试环境下采用
- 验证码识别技术:通过python-tesseract来识别图片类验证码:识别率很难达到100%
- 记录cookie:通过记录cookie来进行跳过登录
二十三.cookie
-
cookie的应用场景:
- 实现会话跟踪,记录用户登陆状态
- 实现记住密码和自动登录功能
- 用户未登录状态下,记录购物车中的商品
-
Selenium操作cookie:
- 获取指定cookie:
get_cookie(name)
- 获取本网站所有本地cookies:
geget_cookies()
- 添加cookie:
add_cookie(cookie_dict)
-
cookie实现跳过登录: import time
二十四.UnitTest框架
二十五.断言
二十六.参数化
-
安装化扩展插件 pip install parameterized
-
使用方式:
-
实例: import unittestfrom parameterized import parameterizeddef add(x, y): return x + y
二十七.跳过
二十八.生成HTML测试报告
二十九.软件测试知识点
- 数据库:(MySQL、MS-SQL、Oracle)
- 基础知识:增删改查,联表查询
- 数据库优化
- 测试过程要对数据进行校验,性能测试需要知道数据库的优化
- Linux、其他一些系统、中间件:
- Linux基本命令、高级命令
- 系统调优
- tomcat、nginx(高级工程师需要掌握)
- 项目流程以及测试流程,测试的相关理论:
- 手工测试的基础
- 流程一定要掌握(开发模型)
- 设计用例的方法
- python或Java
- 自动化测试:
- 性能测试:
- 安全测试:
- SQL注入
- XSS跨站脚本攻击
- 数据是否加密
- 越权测试
- CSRF:跨站请求伪造
三十.软件测试实战
import time
import unittest
from parameterized import parameterized
from selenium import webdriver
from selenium.webdriver.common.by import By
from util.utils import get_element
class TestLogin(unittest.TestCase):
case_data = [("13587654321", "12345678", "7777", "验证码错误", False ),
("", "13587654321", "8888", "用户名不能为空", False),
("13587654321", "", "7777", "密码不能为空", False),
("13587654321", "12345678", "", "验证码不能为空", False),
("13587654321", "123456789", "8888", "密码错误", False),
("13587654321", "12345678", "8888", "我的账户", True)]
@classmethod
def setUpClass(cls):
cls.driver = webdriver.Chrome()
cls.driver.get("http://tpshop-test.itheima.net/Home")
cls.driver.maximize_window()
def setUp(self) -> None:
self.driver.get("http://tpshop-test.itheima.net/Home")
@parameterized.expand(case_data)
def test_login_06(self, mobile, password, code, expect, is_success):
go_login = (By.CSS_SELECTOR, ".red")
get_element(self.driver, go_login).click()
ele_mobile = (By.ID, "username")
get_element(self.driver, ele_mobile).clear()
get_element(self.driver, ele_mobile).send_keys(mobile)
ele_password = (By.ID, "password")
get_element(self.driver, ele_password).clear()
get_element(self.driver, ele_password).send_keys(password)
ele_code = (By.ID, "verify_code")
get_element(self.driver, ele_code).clear()
get_element(self.driver, ele_code).send_keys(code)
ele_login = (By.CSS_SELECTOR, ".J-login-submit")
get_element(self.driver, ele_login).click()
time.sleep(2)
if is_success:
msg = self.driver.title
else:
msg = get_element(self.driver, (By.CSS_SELECTOR, ".layui-layer-content")).text
self.assertIn(expect, msg)
@classmethod
def tearDownClass(cls):
cls.driver.quit()
|