软件测试笔记

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、测试基础

1.1、计算机基础

1.1.1、硬件

  • 软件测试的定义
    软件测试:在规定的条件下对程序进行操作,以发现程序错误,衡量软件量,并对其是否能满足设计要求进行评估的过程。
    简单地说,软件测试是一种实际输出与预期输出之间的审核或者比较过程。

  • 在这里插入图片描述

  • 功能测试,自动化测试,接口测试,性能测试jmeter、

一、软件测试的定义
	在规定的条件下对程序进行操作,以发现程序错误,衡量软件质量,并对其
	是否能满足设计要求进 行评估的过程。
二、为什么不让开发自已做测试
	1. 思维定式
	2. 测试力度
	3. 关注度
三、计算机定义
一种可以自动高效进行计算操作的电子设备,我们称之为电脑( PC )
四、计算机基本特点
	1. 计算机可以完成数学和逻辑运算
	2. 计算机可以对数据进行记忆和存储
	3. 计算机可以在程序指令下自动高效的进行计算
	计算机由硬件(看得见摸得到)和软件(安
	装在计算机中的程序)两部分组成
五、计算机硬件组成
	1. 输入设备:给计算机提供数据。例如:键盘 鼠标....
	2. 输出设备:将计算机处理后的数据展示出来。例如:屏幕 音响....
	3. 计算器+控制器: 中央处理器( cpu )
	4. 存储器:分为内存和外存,对数据进行管理
六、内存储器和外存储器特点
	1. 内存:决定了能同时运行多少个程序
	2. 外存:硬盘、移动硬盘,决定了能保存多少数据
	3. 内存运算速度比外存快
	4. 内存断电后数据丢失,外存不会
	5. 内存比外存价格高
七、计算机软件系统组成
	操作系统软件+应用软件组成
八、常见的操作系统软件
	1. 图形化桌面操作系统软件:WindowsMacOSLinux
	2. 移动设备操作系统:Android( 底层也是一款小型的 Linux )、 iOS 等
	3. 服务器操作系统:Linux(开源、稳定、免费) 、windows server(微软,收费)
	4. 嵌入式操作系统:Linux--pda、各种盒子

1.1.2、编码

九、二进制介绍
	二进制是一种数学进制,只有 01 二个基数。计算机底层里用到的就是二进制
	高电位、高电压 1、逻辑真 true,低电位、低电压、0、逻辑假 false
	进制之间可以随意转换;
十、编码
	人说的要让计算机底层识别,就必须使用编码来翻译。
	当出现中文的时候,对照表没有对应的内容,需要一个厉害一些的编码来帮助实现翻译的过
	程:utf8 国际编码
十一、计算机数据计量单位
	1. 1B(节字:bytes ) = 8b(比特:bit 位,人为规定的最小计量单位 )
	2. 1KB = 1024B
	3. 1MB(兆) = 1024KB
	4. 1GB = 1024MB
	5. 1TB = 1024GB
	6. 1PB = 1024TB

1.1.3、软件

十二、浏览器
	内核:核心技术;、
	五大浏览器:
	Ie、谷歌、火狐、欧朋、苹果
	注意:只有以上 5 个有自己的核心技术,其它浏览器都是用人家的技术换皮肤得来的,
	测试工作只测这 5 个;如果没有强制要求只测前三个
十三、常见的图片类型
	1. .jpg: 颜色信息比较丰富的一种图片格式
	2. .png: 可以支持透明的一种图片格式
	3. .gif: 支持动图,占用体积小,色彩表现力不如前两者
十四、网页打开过程相关知识
	域名:通过域名提供商去购买或租用的;自己的网站可以指向这个域名,今后在浏览器上输
	入域名即可打开你的网页;
	url:统一资源定位符(协议:域名/xx/xx),常说的网页的网址
	http 协议:超文本传输协议
	Ip 地址:每台电脑连上互联网都会被分配到一个不重复的 ip 地址数字串,好像门牌号一
	DNS:域名转换为对应的 IP 地址
	hosts:电脑中的一个文件而已,这个文件中的内容是 ip 地址和域名之间的对应
	关系的表,当你输入网址的时候,优先查看 hosts 中有无对应内容,有就打开自
	己电脑的中的数据,没有才会去互联网上去查找数据
十五、客户端、服务器、请求和响应
	客户端(Client):又称为用户端,是指与服务器相对应,为客户提供服务的程
	序。比如:用户使用的浏览 器、桌面应用程序、APP 等。
	服务器端(Server):是指网络中能对其它机器提供某些服务的计算机系统。
	请求:客户端向服务器要数据的动作
	响应:服务器给客户端数据的动

1.1.4、dos

十六、dos 命令
	打开 dos 命令窗口:win+r 可以打开“运行”,输入 cmd,回车或点击确定
	1、ping 网址 查看当前电脑和目标电脑之间的网络连接情况(ms 代表毫秒,1000ms
	毫秒 = 1s 秒)
	2、ipconfig -all 查看当前电脑的网卡信息;
	3、切换盘符: 盘符名: 注意:符号是冒号,必须是英文状态下的!
	4、dir 查看当前目录结构,用列表展示出来
	5、上下键:快速翻看之前写过的命令
	6、cd 目录/文件夹 切换到这个目录/文件夹中
	7、cd .. 返回上一级目录/文件夹
	8、cd / 返回当前盘符的根目录/根文件夹
	注意:空格别忘了加!

1.2、html

一、web 前端三大核心技术
	HTML:负责网页的架构
	CSS:负责网页的样式、美化
	JS:负责网页的行为
二、工具的使用
	务必按照下图去改变字体的大小
三、html 简介
	中文定义:超文本标记(标签、元素)语言;
	新建一个 html 网页:
	1、准备好一个写代码的文件夹!!!
	2、鼠标左键拖拽文件夹到工具的左侧--项目管理器中
	3、鼠标左键点击文件夹的名字(必须绿色背景才叫被点击选中)
	4、鼠标右键--新建--html 文件
	5、在弹出的对话框中,改文件扩展名之前的名字(.html 代表当前文件的
	扩招名、后缀名:描述当前文件类型)
	6、点击完成即可新建一个 html 文件
四、html 骨架标签
	骨架标签:新建的时候默认生成的那些标签;
	meta 标签可以设置网页的字符集(utf-8 国际编码)
	title 标签设置网页的标题
	body 标签设置网页的主体内容部分
五、文章标题标签
	h1 到 h6 分六级,依次减小效果,每个标题都是独占一行空间;
	注意:不能自己造标签,因为无法正常运行;
六、空格和回车
	空格和回车在代码中直接使用不准确;
	必须使用代码来实现:
	一个空格:  
	一个换行、一个回车: <br />
	注意:html 代码因为历史原因,导致语法较为松散;测试细节的时候,以浏览器最终
	运行效果为准;
七、p 标签和标签语义化
	p 就是负责放文章段落的;
	语义化:在合适地方使用合理的标签,就叫满足标签语义化;可以在搜索引擎排名中
	更靠前!点击率更高,带来更多的收益!
八、代码注释
	程序员给自己代码的提醒文字,浏览器不会直接显示;
	快捷键: ctrl+?再按一次会取消注释
	测试要注意:项目上线之前,要求程序员删除注释的内容,目的是加快网页的加载速
	度
	例: <!-- 这里的文字就当做注释来实现了 -->
九、文字相关的标签
	b 和 strong 都可以代表加粗,后者代表特别强调的语义;
	i 和 em 都可以实现倾斜,后者代表一般强调语义;
	s 和 del 都可以实现删除线效果,后者即将替代前者
	位置是最关键的,安装好浏览器软件后,都会在桌面上有快捷图标,通过浏览按钮,
	找到你桌面上的图标即可;
十、img 标签
	插入图片标签;
	键值对儿、kv 对儿、属性名和属性值;类似下面的例子
	人 身高="180" 年龄="18" 体重="100"
	步骤:
	1、先把图片准备好,复制到当前 html 文件同一级文件夹中
	2、src 代表资源,它后面的值应该写想要加载的那张图片的名字
	3、width 代表宽度(横向距离)、height 代表高度(纵向距离);注意:宽或高只
	设置其中一个属性,另外一个会按照原图的比例去进行缩放显示;如果宽和高都不设置,
	图片会按照原本的大小去显示
	4、title="鼠标悬停时候的提示文字"
	5、alt (1)当图片未正常加载的时候,文字才会被别人看到 (2)网页阅读器读
	取此内容给视障用户听,提升用户体验
	例:
	<img src=”想要加载的图片名字” width=”宽度” height=”高度” title=”鼠标悬停的提示
	文字” alt=”未加载图片时候的提示文字;可以读给网页阅读器听” />
十一、超链接标签
	超链接:点击之后实现页面内容的跳转
	打开线上的网站:href 属性对应的属性值应该设置成带有 http://
	例:<a href="http://www.baidu.com">点击我可以打开百度</a>
	如果想打开本地(你自己的电脑)的页面,只需要把目标文件和当前文件放在同一个
	目录中,在 href 属性中写目标文件的名字即可
	例:<a href="02 文章标题.html">点击我可以打开本地的页面</a>
	新窗口打开链接:默认超链接都是在当前窗口打开,如果想在新窗口打开,需要添加
	target 属性
	<a href="http://www.baidu.com" target="_blank">点击我可以在新窗口打开百度</a>
	空链接:暂时不知道点击之后跳转到哪里,使用空链接占位,当知道具体要跳转的位置
	后,再回来更改即可
	<a href="#">点击我可以打开隔壁老王的页面</a>
	测试工作的时候,如果发现程序员使用#来表达返回顶部效果,一定要提示程序员,要
	用动画效果实现,用户体验才更好!
一、路径
	路径:写想要找到的资源位置(前端需要了解:相对路径的资源不能跨越盘符查询)
	1、相对路径:相对于当前 html 文件去找其它资源的方式
	(1)同级查找:当前 html 和目标在同一级目录中;语法:直接写资源的名字即
	可
	<img src="t1.gif" alt="" />
	(2)上级查找:当前 html 和目标在上级目录中;语法:../写资源的名字即可
	<img src="../t1.gif" alt="" />
	(3)下级查找:当前 html 和目标在下级目录中;语法:文件夹名/写资源的名
	字
	<img src="tu/t1.gif" alt="" />
	2、绝对路径:资源在电脑中的具体位置(复制电脑中具体位置的时候,别忘了加这
	个资源的具体名字,以及斜杠!)
	<img src="F:\测试课程\直播课 03\tu2\t1.gif"/>
	注意:在前端语法中,绝对路径不推荐写!!!只推荐使用相对路径!!!
二、列表
	无序列表:ul 嵌套若干 li,每个 li 就是一个选项
	例:
	<ul>
	<li>基础班</li>
	<li>自动化测试</li>
	<li>功能测试</li>
	</ul>
	有序列表:ol 嵌套若干 li,每个 li 就是一个选项
	例:
	<ol>
	<li>周杰伦</li>
	<li>李荣浩</li>
	<li>蔡徐坤</li>
	</ol>
三、布局的标签
	布局标签:当没有任何语义的时候,就可以使用 div 或 span 来进行内容的包裹,目的
	是后期 css 代码可以找到对应标签中的内容来设置样式
	div:独占一行空间,称之为大盒子
	span:一行可以放置多个,称之为小盒子
	例:
	<div>我是 div</div>
	<span>我是 span</span>
四、音、视频、测试点
	audio 音、video 视频
	测试细节:因为历史发展原因,导致音、视频标签兼容性很差,对于测试工作来讲,
	需要测试三大主流浏览器是否能正常运行音、视频;
	Ie 测试低版本(ie7、891011)
	测试方法:打开 ie,f12,找到仿真(必须是 ie 高版本才能测试低版本)
	什么时候测试低版本:用户要求,再测试!
五、form 表单标签
	form 表单标签里面就是所有用户填写的表单数据;
	action="xxx.jsp" 把表单数据提交给哪一个后台程序去处理
	method="post" 传递数据时候的方式方法,post 代表隐式提交数据;get 明文传送
	数据
	input 标签的 type 类型:
	type="text" 普通的输入框
	type="password" 密码框
	type="radio" 单选框
	checked="checked" 此属性可以表达默认选中状态
	测试细节:
	1、点击查看是否为单选效果
	2、刷新的时候是否有默认选中的状态
	3、点击文字是否可以进行切换
	type="checkbox" 多选框、复选框
	checked="checked" 默认选中
	测试细节:
	1、刷新的时候是否有默认选中的状态
	2、点击文字是否可以进行切换
	注意:一切测试要追溯到用户的需求
	select 标签嵌套若干 option 标签,每组 option 就是一个下拉菜单中的选项
	selected="selected" 下拉菜单的默认选中
	测试细节:
	1、内容的顺序
	2、默认选中的状态
	3、内容的条数
	textarea 文本域
	测试细节:
	1、测试三大主流浏览器外观大小是否一致
	2、提醒程序员禁用拖拽大小的功能
	type="button" 普通按钮,需要 js 配合才能实现其它效果
	value 属性设置按钮身上的文字
	type="reset" 点击后可以让表单数据恢复默认值
	value 属性设置按钮身上的文字
	type="submit" 点击后可以让表单提交给指定后台处理
	value 属性设置按钮身上的文字
	点击后无论是否报错,都与我们无关,最终测试的时候,只要关注
	数据库中的内容是否正常添加即可
	placeholder="请输入用户名" 文字提醒属性

1.3、css

一、表单的用户体验提升
	1、可以添加 placeholder 属性,可以给文本框设置提示文字
	例:placeholder="请输入用户名"
	2、如果是专门写表单的页面,可以给第一个输入框设置一个默认获取鼠标焦点的属性
	autofocus
	例:autofocus="autofocus"
	注意:tab 可以让光标前进,shift+tab 可以光标后退
二、css 基础
	css 定义:可以设置网页中的样式、外观、美化
	css 中文名字:级联样式表、层叠样式表、样式表
三、css 基础语法
	1、style 标签写在 title 标签的后面
	2、选择器{ 属性名 1:属性值 1; 属性名 2:属性值 2; }
	color 代表颜色
	font-size 代表字号,px 代表像素单位(在 css 中 90%以上的情况,数字后面必须跟
	单位)
	例:
	<style type="text/css">
	div{ color: red; font-size: 100px; }
	</style>
四、开发人员调试工具
	1、打开方式:f12 或在网页中右键--检测
	2、找到菜单中的第一个选项:elements(元素、标签、标记)
	3、用鼠标左键点击想要查看的标签
	4、右侧就会出现对应的 css 代码
	5、想设置颜色:点击颜色前面的方框,使用调色盘改变颜色后,别忘了把颜色的代码
	放在程序中;
	6、设置数字大小:鼠标左键点击数字,按键盘的上、下可以调整大小,最终的代码也
	要自己更改才可以生效
五、标签选择器
	选择器:在大括号之前写的内容,就是选择器,找到你要选择的内容
	标签选择器:用标签的名字来进行页面元素、标签、标记的选择
	例:
	p{color: #edff05;}
六、id 选择器
	id 选择器:用 html 标签中的 id 属性来进行选取的方式
	语法规则:
	#id 的值{xxx}
	<p id="id 的值">xxx</p>
	例:
	#p1{color: red;}
	<p id="p1">黑马</p>
七、命名规则
	1、不能数字开头
	2、不能使用中划线、下划线之外的符号
	3、不推荐中文
	4、尽量做到见名知意(看到名字就知道意思)
	唯一性:
	1、id 命名不可以重复使用;在 js 中会因为 id 的命名冲突而导致报错
	2、每个标签只能有一组 id
八、class 类选择器
	类选择器:使用 html 中的 class 的值来进行选取的方式
	语法:
	.类名 2{xx}
	<p class="类名 1 类名 2 类名 3">xx</p>
	注意:class 类选择器可以重复命名; 每个标签可以有多个 class 类名,中间使用
	空格分割即可
	命名的规则:与 id 的命名规则完全一样
九、css 书写位置、引入方式
	1、内嵌式:css 写在 style 标签中,放在 title 标签的后面;因为 html 代码和 css 代码混
	在同一个文件中
	2、外链式:css 代码和 html 代码,实现代码的分离效果,使用 link 标签设置 href 属性,
	即可单独把 css 文件链入到当前的 html 文件中
	例:
	<link rel="stylesheet" type="text/css" href="css.css"/>
	应用场景:
	1、内嵌式应用在电商网站首页,因为对网页的打开速度有严格的要求,一次性把
	html 和 css 都加载进来;
	2、外链式应用在除了电商网站首页,实现代码的分离,方便后期修改
	3、了解行内式:css 代码写在标签的身上,强烈不推荐使用!修改不方便、重复代码太
	多,导致页面加载速度变慢!
	例:以下写法就是反面教材!!!
	<p style="color: red;">黑马</p>
十、扩展内容
	1:hover 伪类:鼠标移入动作执行后的 css 代码
	例:
	p:hover{color: blue;}
	注意:鼠标移入和鼠标悬停不是一个动作!
	2、并列、并集选择器:需要一句话选择多个元素的时候,可以使用逗号进行连接
	语法:
	h1,div,span,p{}
	3、后代选择器:后代选择器:使用空格来进行选取后代元素的方式
	语法:
	div span{ } 找 div 的后代 span(儿子、孙子、重孙子。。。都算后代)
	代码从左向右执行,我们就从左向右读代码
十一、js 简介
	Js 出生的时候为了解决表单数据的合法性验证;
	JavaScript:简写 js,它与 java 没关系!
	Js 可以控制 web 前端技术的前两者:结构和样式

1.4、后端

一、CSBS 软件架构
	CS 即客户端-服务器架构与 BS 即浏览器-服务器架构,区别总结 :
	效率:c/s 效率高,某些内容已经安装在系统中了,b/s 每次都要加载最新
	的数据
	升级:b/s 无缝升级;c/s 删除老版本再安装新版本
	安全:c/s 更安全,需要安装、注册、登录;b/s 有浏览器即可使用,安全程
	度低
	开发成本:b/s 成本低;c/s 需要不同的系统要不同的开发人员,成本高
二、语言发展史
	1、机器语言、机器码(01):计算机底层能识别
	2、汇编语言:最接近机器码的语言,依然晦涩难懂,比其它高级语言运行速度快
	3、高级语言:c、php、java、python。。。
三、软件测试分类
四、按阶段分类
	1、单元测试也叫模块测试;测试最小的程序模块;
	2、集成测试又叫组装测试,通常在单元测试的基础上 ,单独的模块合在一
	起测试
	3、系统测试,指的是将整个软件系统看为一个整体进行测试
	4、验收测试:
	(1) α 测试:Alpha 是内测版本,通常只在软件开发者内部交流,或忠实
	的粉丝之间发布,该版本软件的 bug 较多,普通用户最好不要安装
	(2) β 测试:Beta 是公测版本,是对所有用户开放的测试版本 ,免费发布,
	因为里面还会有一些 bug 的存在
	(3) γ 测试:Gamma 版本就是正式版的候选版本
五、是否查看源代码
	1、黑盒测试:关注业务逻辑,输入内容与输出结果之间
	2、白盒测试:去研究里面的源代码和程序结构
	3、灰盒测试:黑白之间的状态
六、按是否运行分类
	1、静态测试: 指不实际运行被测软件,而只是静态地检查程序代码、界面或文档中可
	能存在的错误过程。
	2、动态测试: 是指实际运行被测程序,输入相应的测试数据,检查实际输出结果和预
	期结果是否相符的过程。
七、按照是否自动化
	1、人工测试:也叫做手工测试,测试人员手动去进行的测试
	2、自动化测试:利用代码或者工具帮助人工进行测试
八、测试策略
	1、冒烟测试:冒烟测试就是对系统进行最基本功能的测试,保证基本的功能和
	流程能走通
	2、回归测试:当修复一个 BUG 后,把之前的测试用例在新的代码下进行再次测
	试
	3、随机测试:随机测试主要是对被测软件的一些重要功能进行复测,也包括测
	试那些当前的测试用例没有覆盖到的部分
	4、探索性测试:探索性测试意味着同时设计测试和执行测试。测试人员通过测
	试来不断学习被测系统。
九、缺陷
	软件缺陷:是指软件或程序中存在的各种问题及错误;会导致软件产品在某种
	程度上不能满足用户的需求
十、软件缺陷的判定标准
	1. 软件未达到需求规格说明书中标明的功能
	2. 软件出现了需求规格说明书指明不会出现错误的地方
	3. 软件的功能超出了需求规格说明书指明的范围
	4. 软件未达到需求规格说明书虽未指明但应该达到的目标
	5. 软件测试人员认为软件难以理解,不易使用,运行速度慢,或者最终用户体
	验不好。
十一、软件缺陷产生的原因
	软件缺陷产生是不可避免的,造成软件缺陷产生的原因主要归纳如下:
	1. 需求解释、记录或者定义错误
	2. 设计文档说明存在错误或者拼写错误
	3. 编码说明、程序代码有误
	4. 硬件或者软件系统上存在错误
十二、软件缺陷的类型
	功能错误
	界面错误
	兼容性缺陷
	易用性问题
	改进建议
十三、测试原则
	1、只能证明软件存在问题,不能证明不存在问题
	2、不能进行穷尽(穷举)测试,应该分类别测试
	3、测试工作要尽早的介入,降低修复成本
	4、缺陷存在集群现象,二八原则:20%的模块中存在 80%的缺陷
	5、测试依赖环境(系统、浏览器)
	6、杀虫剂现象
	7、不存在缺陷谬论
十四、软件测试的定义
	人工和自动化手段来进行测试,目的找到预期结果和实际结果之间的差异
十五、软件测试的目的
	用最少的人力、物力、财力,找到软件中的问题并修复,从而降低商业风险
十六、测试用例
	定义:是为特定的目的而设计的一组测试输入、执行条件和预期结果的文档。
	测什么?怎么测?
十七、js 基础语法
	ctrl+? 依然是注释的快捷键
	alert 弹出对话框,小括号中的内容可以实现提示文字的效果,必须放在英文状态下的
	单、双引号中,最后的分号不推荐省略,
	例:
	alert();
	alert('您的话费不足 请及时充值');
	alert("您网费不足");
	书写位置:script 标签写在 html 代码的最后位置,其它 js 程序都要写在这对标签中
十八、事件语法
	<script type="text/javascript">
	语法规则:
	事件源.事件类型=function(){
	事件发生的时候要执行的命令
	}
	//document 代表查找的范围在整个文档中
	// document.getElementById('bz') 事件源: 通过 id 的值为 bz 的按钮
	以下这一小段代码放在浏览器的 f12,找到第二个 console,复制进去回车运行,
	查看是否可以找到对应的标签
	// onclick 代表事件类型(鼠标左键点击)
	// function(){ 要执行的命令 }
	//例:
	documen.getElementById('xw').onclick=function(){
	alert('啊 我被点了');
	}
	//getElementsByClassName('xw') 找 class 为 xw 的标签
	//onclick 必须都是小写才可以!!
	// [数字] 代表第几个,从 0 开始记录数字(索引值、地址下标)
	document.getElementsByClassName('xw')[1].onclick=function(){
	alert('我有 class 我被点击了');
	}
	//onmouseover 鼠标移入事件
	//onmouseout 鼠标移出事件
	</script>

1.5、测试理论

1.6、js

二、linux

三、功能测试

3.1、测试理论

3.1.1、测试模型:

  • 瀑布模型
    在这里插入图片描述

  • v模型
    在这里插入图片描述

  • w模型
    在这里插入图片描述

  • 软件质量模型
    在这里插入图片描述

3.1.2、用例概念

  • 软件测试用例概念:一个为了特定的目的(检验开发的代码实现是否满足用户的需求)而设计的文档(包含测试输入、执行条件、预期结果),文档的形式可以是xmind、excel等。
    在这里插入图片描述
    在这里插入图片描述

  • 测试用例组成要素与用例模板

    - ID
      - 唯一性
      - 项目-模块-001
    - 模块
    - 优先级
      - 作用:体现用例执行的先后顺序
      - 分类:
        ---- 用例标题
      - 唯一性
      - 见名知意
    - 预置条件
    - 测试步骤
      - 尽可能详细
    - 测试数据
    - 预期结果
    
  • 测试用例作用:

在这里插入图片描述

  • 便于:
    • 理清测试思路,确保需覆盖测试的功能点无遗漏
    • 测试工作量的评估
    • 提前准备测试数据
    • 把控测试进度
    • 回归测试
    • 测试工作组织,提高效率,降低测试交接成本

3.2、测试用例设计方法

3.2.1、:等价类划分法(解放 穷举测试)

  • 概念:通过科学的方法找到具有共同特性的测试输入的子集,能够从穷举测试中解放(大大减少了测试用例的数量,从而提升测试效率。)

  • 分类

    • 有效等价类:满足需求

    • 无效等价类:不满足需求

  • 设计测试用例的步骤(重要)

    • 需求分析

    • 划分等价类

      • 有效
      • 无效
        • 规则(需求本身)
        • 长度
        • 类型
        • 是否为空(必填项)
        • 是否重复
    • 设计用例

3.2.2、:边界值分析法

  • 作用:对等价类的补充,统计表明程序最容易出错的地方就是在边界附近。

  • 概念:基于边界值【有效等价类和无效等价类的分界点】设计测试用例的一种【黑盒】方法

  • 边界值

    • 上点:边界之上的点

    • 内点:边界之内的点

    • 离点:离边界最近的左右两点

在这里插入图片描述

  • 设计测试用例步骤

    • 需求分析

    • 划分等价类

    • 确定边界

      • 上点
      • 内点
      • 离点
    • 设计测试用例

  • 典型应用场景

    • 存在边界 > >= < <= 大于 小于等于

  • 在这里插入图片描述

扩展知识:

  • 边界值优化【7点变5点】
    在这里插入图片描述在这里插入图片描述

    • 去掉-97,98
  • 结论:

    • 上点:必选(不考虑区间开闭)
    • 内点:必选(建议选择中间范围)
    • 离点:开内闭外(考虑开闭区间,开区间选择内部离点,闭区间选择外部离点)

3.2.3、:判定表分析法

  • 概念:存在多个输入条件、多个输出结果,输入和输入之间有组合关系,输入和输出之间有依赖或制约关系。

  • 判定表组成:

    • 条件桩:所有输入条件,如欠费状态、关机状态

    • 动作桩:所有的可能的输出结果,如允许主被叫、不允许主被叫

    • 条件项:单个条件的取值范围,一般都是有效等价类和无效等价类

      • 表示方式
        • 字符:
          • 真/有效等价类/Y
          • 假/无效等价类/N
        • 数字:
          • 真/有效等价类/1
          • 假/无效等价类/0
    • 动作项:基于每一种条件的组合,得到确认的结果,如打不通等

  • 设计测试用例的步骤

    1. 明确条件桩(找到所有的输入条件)
    2. 明确动作桩(找到所有的输出结果)
    3. 对条件桩进行全组合
    4. 明确每个组合对应的动作桩(基于每一种条件的组合情况,确定本组合下的输出结果。)
    5. 设计测试用例,每行数据对应一条测试用例
  • 真假表示说明:

    表示形式
    数字10
    符号YN
  • 使用场景:

    • 多条件组合情况
  • 案例1:用户呼叫

若用户欠费或关机,则不允许主被叫

在这里插入图片描述

  • 案例2:订单状态
订单检查,如果金额大于500元,又未过期,则发出批准单和提货单;
        如果金额大于500元,但过期了,则不发批准单与提货单;
        如果金额小于500元,则不论是否过期都发出批准单和提货单;
        在过期的情况下,不论金额大小还需要发出通知单。

在这里插入图片描述

  • 案例3:文件修改
如果想对文件进行修改,
   输入的第一列字符必须是A/B,第二列字符必须是一个数字,
   如果第一列字符不正确,则给出信息L;
   如果第二列字符不正确,则给出信息M。

在这里插入图片描述

3.4.3、:因果图(扩展)

  • 概念:用图解的方法表示输入的各组合关系,写出判定表,进而设计测试用例的一种【黑盒测试】方法。
  • 适用范围:适用于分析程序输入条件的各种组合情况,以及输入和输出之间的依赖关系。
  • 核心
    • 因:条件
    • 果:结果
  • 基本符号(掌握)
    • 恒等(-):条件成立,结果成立。
    • 非(~)NOT:条件成立,结果不成立;条件不成立,结果成立。
    • 或(V)OR:只要有一个条件成立,结果就成立;所有条件都不成立时,结果才不成立。
    • 与/且(^)AND:多个条件必须同时成立,结果成立;只要有一个不成立,结果就不成立。
  • 设计测试用例的步骤
    • 需求分析
    • 画出因果图
    • 将因果图转换为判定表
    • 生成测试用例
  • 案例1:文件修改
如果想对文件进行修改,
   输入的第一列字符必须是A/B,第二列字符必须是一个数字,
   如果第一列字符不正确,则给出信息L;
   如果第二列字符不正确,则给出信息M。

分析过程

小结

  • 输入条件比较少(2,3,4),推荐直接使用判定表。
  • 输入条件比较多(>4),推荐使用因果图。

3.2.4、:正交法(扩展)

  • 核心思想

  • 用最小的测试用例获得最大的测试覆盖率。

  • 正交表

说明

  • k代表因素(输入参数)

  • m叫水平(输入参数的取值)

  • n代表测试用例数

  • 读法:k因素m水平

  • 基于正交表设计测试用例

  • 步骤

    • 需求分析
    • 确定因素与水平(因素:控件名称;水平:每个控件对应的取值)
    • 确定要采用的正交表
    • 将正交表中的字母用文字代替
    • 设计测试用例(一行就是一条测试用例)
  • 案例1:字符属性设置程序

    窗体中有多个控件(字体、字符样式、颜色、字号),每个控件有多个取值
    字体:仿宋、楷体、华文彩云
    字符样式:粗体、斜体、下划线
    颜色:红色、绿色、蓝色
    字号:20号、30号、40号
    
列号字体字符样式颜色字号
试验号
1仿宋粗体红色20号
2仿宋斜体绿色30号
3仿宋下划线蓝色40号
4楷体粗体绿色40号
5楷体斜体蓝色20号
6楷体下划线红色30号
7华文彩云粗体蓝色30号
8华文彩云斜体红色40号
9华文彩云下划线绿色20号
  • 基于allpairs设计测试用例

  • 步骤

    • 需求分析
    • 确定因素与水平(因素:控件名称;水平:每个控件对应的取值)
    • 将确定的因素与水平复制到txt文件中
    • 打开DOS窗口,进入allpairs目录,运行命令:allpairs.exe test.txt > result.txt
    • 根据生成的新文件编写测试用例(一行就是一条测试用例)
  • 案例2:用户筛选按钮

    假设有一个用户筛选功能,有3个输入分别是体型、年龄段、性别,
                                           体型有3个取值:胖、适中、瘦;
                                           年龄段有3个取值:老人、青年、儿童;
                                           性别有2个取值:男,女;
    请设计测试用例。
    
TEST CASES
case体型年龄段性别
1老人
2青年
3适中老人
4适中青年
5儿童
6老人
7儿童
8适中儿童~男
9青年~男

3.2.5、:场景法(流程图法)

  • 概念:场景法就是模拟用户操作软件时的场景,主要用于测试多个功能之间的组合使用情况。

  • 使用测试阶段

    • 集成测试
    • 系统测试
    • 验收测试
  • 设计测试用例的步骤

    • 需求分析

    • 绘制流程图

    • 设计测试用例(一条流程路径就是一条测试用例)

  • 流程图常用符号

    在这里插入图片描述

    • 开始或结束:椭圆

    • 方向或路径:箭头

    • 处理或操作:长方形

    • 判断:菱形

    • 输入或输出:平行四边形

  • 绘制流程图

    • 第1步:确认场景中关键业务步骤

    • 第2步:确定业务之间的先后顺序

    • 第3步:用箭头连接即可

  • 绘制工具

    • Microsoft Visio

    • 软件介绍

    • Visio的安装

      • 以管理员身份运行Visio2003_SP3.exe
      • 默认安装即可,中间不需要修改或填写任何内容
    • Visio的基本使用:

      • 新建
    • 画图

      • 选中—del—删除操作

      • ctrl 鼠标左键 拖拽 画纸边缘 – 扩大画纸

        • ctrl 滚轮 – 放大缩小
        • 组合与取消组合
      • 操作练习

        • 新建一个流程图

        • 熟悉几个主要的组成元素

        • 熟悉visio的两个工具

        • 使用一下Del删除无关元素操作

        • 调整一下纸张大小(Ctrl+鼠标左键)

        • 组合与取消组合操作练习

  • 案例1:电商购物流程

  • 案例2:缺陷跟踪管理流程


3.2.6、:错误推测法

  • 概念:利用经验智慧发现程序中可能犯错的地方。

  • 使用场景

    • 重要功能

    • 使用同类型产品

    • 任务急、时间紧、资源少


3.2.7、:测试用例方法总结

  • 具有输入功能,但输入之间没有组合关系==》【等价类】
  • 输入有边界 如长度、类型==》【边界值】
  • 多输入、多输出、输入与输入之间存在组合关系、输入与输出之间存在依赖或制约关系==》【判定表、因果图】
  • 用最少的测试用例获得最大测试覆盖率时 ==》【正交法】
  • 多个功能的组合测试 ==> 【场景法、流程图】
  • 最后推荐使用【错误推测法】来进一步补充测试用例

3.3、缺陷管理

1.1 缺陷的定义(重点)

  • 产品实现不满足用户需求
  • 测试执行时,实际结果和预期结果不一致

1.2 缺陷的判定标准(重点)

  • 未达到需求说明书指明的功能
  • 出现了需求说明书指明不应该出现的错误
  • 实现了需求说明书之外的功能
  • 未达到需求说明书虽未明确提及但是应该实现的目标(如:性能要求等)
  • 用户角度发现的各种问题与错误

1.3 缺陷产生的原因及根本原因

  • 缺陷产生的原因
    • 需求文档存在错误
    • 需求变更
  • 设计存在错误
    • 代码错误
  • 缺陷产生的根本原因
    • 需求变更
    • 沟通不畅、信息不同步
    • 软件复杂
    • 进度压力

1.4 软件缺陷的核心内容(重点)

  • 标题:描述缺陷的基本信息,如(输入密码长度为5时,注册成功。)
  • 前置条件:描述缺陷出现依赖的相关基础条件,如(未注册手机号)
  • 复现步骤:测试用例里面的执行步骤
  • 实际结果:执行被测试软件过程中,系统给出的结果
  • 预期结果:参照需求说明书,在测试用例中设计的预期结果
  • 附件:方便开发定位bug的关键信息,包含图片、日志log等

1.5 缺陷基本要素(重点)

  • ID编号:唯一

  • 模块:根据产品进行具体的划分,如登录、注册

  • 缺陷状态:表明缺陷处理进度

  • 严重程度:从技术维度来衡量,bug的破坏力

  • 优先级:从业务的角度,决定bug修改的先后顺序

  • 缺陷类别:用于分类整理缺陷

1.6 缺陷的状态(重点)

  • new:新建
  • open:打开
  • fix:已修复
  • close:关闭
  • reopen:重新打开
  • reject:已拒绝
  • postpone:延期

1.7 缺陷严重程度(重点)

  • 5-致命的

  • 4-非常高

  • 3-高

  • 2-中

  • 1-低

1.8 缺陷优先级(重点)

  • 5-紧急的
  • 4-非常高
  • 3-高
  • 2-中
  • 1-低
### 思考题:优先级和严重程度的区别(了解)

+ Priority is Business【优先级是从公司运营角度(人力配置,资金投入等)】
+ Severity is Technical【严重级别是从技术角度】

- 优先级还要考虑团队的工作进度,阻塞工作的缺陷,要优先解决
- 考虑解决缺陷的能力,难度,风险

+ 最终优先级

  + 确定权:产品经理、项目经理等

  + 建议权:测试

1.9 缺陷类别(了解)

  • 功能错误

  • UI界面错误

  • 兼容性

  • 易用性

  • 改进建议

  • 其他

2.1 缺陷信息(重点)

  • 核心要素
    • 标题:描述缺陷的基本信息,如(输入密码长度为5时,注册成功。)
    • 前置条件:描述缺陷出现依赖的相关基础条件,如(未注册手机号)
    • 复现步骤:测试用例里面的执行步骤
    • 实际结果:执行被测试软件过程中,系统给出的结果
    • 预期结果:参照需求说明书,在测试用例中设计的预期结果
    • 附件:方便开发定位bug的关键信息,包含图片、日志log等
  • 基本要素
    • ID编号:唯一
    • 模块:根据产品进行具体的划分,如登录、注册
    • 缺陷状态:表明缺陷处理进度
    • 严重程度:从技术维度来衡量,bug的破坏力
    • 优先级:从业务的角度,决定bug修改的先后顺序
    • 缺陷类别:用于分类整理缺陷

2.2 缺陷报告的重要性(了解)

  • 体现测试的一个专业性

  • 多站在开发的角度去思考问题(换位思考)

2.3 编写缺陷报告注意事项(理解)

  • 可复现
  • 唯一性
  • 一个问题只提交一个bug记录

2.4 缺陷书写规范(理解)

  • 标题:应保持简短、准确,提供缺陷的本质信息
  • 复现步骤:应包含如何使别人能够很容易的复现该缺陷的完整步骤
  • 实际结果:是执行复现步骤后软件的现象和产生的行为
  • 预期结果:通常需要列出期望的结果是什么
  • 附件:对缺陷描述的补充说明

2.5 缺陷跟踪流程(重点)

场景1:确认BUG解决

  • 测试【new】》开发【open】》开发【fix】==》测试【close】

场景2:验证未通过,缺陷仍存在

  • 测试【new】》开发【open】》开发【fix】==》测试【reopen】

场景3:开发延期处理

  • 测试【new】》开发【open】》开发【postpone】

场景4:拒绝处理

  • 测试【new】》开发【open】》开发【reject】

2.6 缺陷的统计(了解)

  • 严重程度
  • 提交人
  • 缺陷类型

3.4、禅道使用-禅道(重点)

3.1 禅道使用流程

1.产品经理创建产品

2.产品经理创建需求

3.项目经理创建项目

4.项目经理确定项目要做的需求

5.项目经理分解任务,指派到人

6.开发人员实现需求

7.测试人员测试,提交bug

3.2 禅道用户角色(了解)

  • 超级管理员
  • 产品经理
  • 项目经理
  • 开发
  • 测试

3.3 超级管理员使用禅道(扩展)

  • 取消弱口令:【系统】–【安全】

    • 密码安全:不检查
    • 修改弱口令密码:不强制

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j3Lruitl-1684125232868)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E7%A6%85%E9%81%93/%E8%B6%85%E7%BA%A7%E7%AE%A1%E7%90%86%E5%91%9801.png)]

  • 修改密码

  • 修改公司信息:【组织】–【公司】–【编辑】–【公司名称】

  • 添加部门:【组织】–【部门】

  • 添加用户:【组织】–【用户】–【添加用户】/【批量添加】

    • 注意:

      • 用户名是数字,字母,下划线,大于3位
      • 注意:用户的职位和分组,决定了用户的相应权限
    • 添加用户

    • 批量添加

3.4 产品经理使用禅道(扩展)

  • 创建产品:【产品】–【添加产品】–编辑产品信息
  • 维护模块:【产品】–【模块】–按层级编辑模块信息
  • 维护计划:【产品】–【计划】
  • 产品经理提需求:【产品】–【需求】–【提需求】
    • 默认不开启评审,需求是激活状态
  • 需求评审
    • 需要评审的需求处于‘草稿’状态
    • 评审是一个线下的活动(开会),只在禅道中更新评审结果
    • 评审的结果
      • 确认通过
      • 有待明确
      • 拒绝
  • 需求变更
    • 需要评审的变更需求处于‘变更中’状态
    • 评审结果
      • 确认通过
      • 有待明确
      • 撤销

3.5 项目经理使用禅道(扩展)

  • 创建项目:【项目】–【添加项目】–编辑具体项目信息
  • 创建团队:【项目】–【团队】–【团队管理】
  • 关联需求:【项目】–【需求】–【关联需求】
  • 分解任务(执行模块:任务中新建):【项目】–【需求】–【分解任务】/【批量分解】

3.6 开发使用禅道(扩展)

  • 领取任务:
    • 方式1:【项目】–【任务】–选择开始
    • 方式2:【我的地盘】–【任务】–选择开始
  • 提测
    • 1.打版本(执行模块):【项目】–【版本】–【创建版本】
    • 2.提交测试(执行模块):【项目】–【版本】–【提交测试】

3.7 测试使用禅道(重点)

3.7.1 创建用例
  • 【测试账号】登录
  • 【测试】–【用例】–【建用例】
  • 【测试】—【用例】-- 点击右上角“建用例”的下拉菜单,选择【批量添加】
3.7.2 导入用例
  • 第一步:导出测试用例模板

    • 进入【测试】—【用例】,右上角按钮【导出】–【导出模板】,选择【GBK】字符,点击保存
  • 第二步:按照模板编写测试用例

  • 第三步:导入编写好的用例文件

    • 进入【测试】–【用例】,右上角【导入】–【导入CSV】,选择测试用例文件,选择“GBK”,点击保存
3.7.3 评审用例
  • 【admin】登录,进入【后台】–【自定义】–【用例】—【评审流程】,【开启评审】的功能
  • 测试人员登录,进入【测试】–【用例】,新建一个需要评审的用例(不勾选“不需要评审”)
  • 在【测试】–【用例】,对需要评审的用例,点击操作栏“评审”按钮,进行评审。
    • “确认通过”:用例从【待评审】状态改为【正常】状态
    • “继续完善”:用例保持【待评审】状态
3.7.4 版本关联用例
  • 测试人员登录系统,进入【测试】—【版本】,查看提交测试的版本

  • 点击操作栏中的“关联用例”按钮,勾选用例(正常状态),点击保存。

3.7.5 执行用例
  • 测试登录系统,进入【测试】—【版本】—【用例】,点击操作栏中的执行按钮

  • 用例执行的结果:【通过】,【失败】,【阻塞】,【忽略】

  • 失败的用例,可以点击“转BUG”,填写BUG信息,点击保存。

  • 可以直接提BUG:进入测试–BUG,点击“提BUG”,填写信息,点击保存

3.7.6 禅道中BUG跟踪过程
  • 测试提交缺陷
  • 开发解决缺陷
  • 测试回归验证
    • 确认修复,关闭缺陷
    • 并未修复,激活缺陷,重新指派给开发解决
  • 关闭后的缺陷再次出现,测试激活该缺陷
今日目标
  • 能够说出缺陷的判定标准
  • 能够说出描述缺陷的6大核心内容
  • 能够描述缺陷状态、严重程度、优先级的作用
  • 能够按照提供的缺陷模版完成一个缺陷的提交
  • 能够说出缺陷的跟踪流程
  • 能够在禅道中提交测试用例
  • 能够在禅道中提交缺陷

3.5、tpshop实战

今日目标
  • 了解Windows下WAMP环境搭建

  • 掌握熟悉项目的四大步骤

  • 掌握业务组织架构图的绘制方法

  • 掌握项目的测试流程

    1. 需求分析与评审
    2. 编写测试计划与测试方案
    3. 设计测试用例与评审
    4. 执行用例与缺陷跟踪
    5. 编写测试报告
  • 了解测试人员在需求评审中的职责

  • 熟悉测试计划和测试方案的核心内容

  • 熟悉测试用例和缺陷模板的核心要素

  • 熟悉项目中的用户表,商品表,订单表

一、环境搭建
1. 基础环境介绍
1.1 LNMP与WAMP
  • LNMP:linux + nginx + mysql + php
  • WAMP:windows + apache + mysql + php
1.2 项目环境的组成部分(重点)
  • 操作系统

    • Windows
    • Linux
  • web服务器

    • 作用

      • 处理浏览器访问请求
      • 存放服务资源:项目文件、图片等
    • 常见web服务器

      • nginx
      • apache
      • tomcat
    • 服务器与web服务器说明

  • 数据库

    • 关系型数据库
      • oracle
      • MySQL
      • SQL Server
      • DB2
    • 非关系型数据库
      • redis
      • mongodb
  • 项目

    • PHP
    • JAVA
    • C
    • Python
2. 搭建测试环境
2.1 搭建环境步骤(Windows)
  • 准备工作
    1. 集成环境安装包:phpstudy
    2. 项目部署包:tpshop
    3. 部署文档
  • 安装集成环境
    • web服务器:apache
    • 数据库:mysql
  • 部署项目
    • 将TPshop项目压缩包解压后文件夹里的全部内容放入phpStudy安装路径D:\phpStudy\WWW中
2.2 域名的设置(扩展)
  • 进入目录C:\Windows\System32\drivers\etc
  • 用记事本打开hosts文件
  • 127.0.0.1 hahaha.tpshop.com
  • 保存退出
  • 浏览器通过域名访问商城
3 TPshop项目介绍
3.1 熟悉项目的步骤
  • 业务特性
  • 用户与角色
  • 组织架构图
  • 技术栈
3.2 熟悉项目的信息来源
  • 文档:需求文档、测试用例、用户手册等
  • 环境:
    • 开发环境
    • 测试环境
    • 线上环境/生产环境
  • 人:测试组员/测试经理,开发人员,产品经理

熟悉tpshop项目:

  • 业务特性
    • 一个电商网站
  • 项目的用户与角色
    • 前台
      • 游客
      • 注册会员
    • 后台
      • 超级管理员
      • 仓管员
      • 客户人员
  • 组织架构图
    • 作用:整体性认识被测试的项目。
    • 绘制:
      • 后台
        • 系统==》子系统==》模块==》子模块
        • 见到具体的页面截止
      • 前台
        • tpshop购买流程
          • 注册登录==》商品展示==》购物车==》支付==》订单管理
        • 前台绘制原则
          • 一个独立的页面就是一个模块
          • 具有共同特点的模块可以进行归纳整理合并,推荐大家按照核心业务流程涉及的模块进行归整。
  • 项目的技术栈
    • 数据库:mysql
    • web服务器:apache
    • 开发语言:php
    • 操作系统:windows(Linux)
4. 测试流程(重点)
  • 需求分析与评审
  • 编写测试计划于测试方案
  • 设计测试用例与评审
  • 执行测试用例与缺陷跟踪
  • 编写测试报告
4.1 需求分析与评审(掌握)
  • 什么是软件需求?

    • 解决问题
    • 达到目标
  • 为什么要做需求评审?

    • 确认需求完整与准确
    • 理解一致
    • 降低因为需求不明确带来的项目失败的风险
  • 怎样做需求评审?

    • 需求评审会议
    • 参与人
      • 产品经理/项目经理
      • 开发/UI
      • 测试
      • DBA
  • 测试工程师在需求评审中的主要职责是什么?

    • 确认自己理解需求、无疑义:·确认自己对需求要有清晰的理解,没有疑惑

    • 确认需求无明显错误、能够支撑后续的用例设计等:·确认需求文档完整,准确,能够指导后期工作

    • 提出一些改进建议:·对需求中不合理的地方提出自己的修改建议

  • 需求评审实战——实名认证

    • 第一轮需求评审
      • 图1
        • 上传的身份证需要打上水印,仅供当前产品使用
        • 身份证正面照片与示例中的反面案例?
        • 包含身份证有效期的反面照不需要上传吗?
      • 图2
        • 姓名与身份证号显示不对齐
        • 提示语位置超出界面范围
        • 识别后的姓名信息可以修改,但是证件号不可以进行修改
      • 图3
        • 技术上存在疑惑,系统能实时给出实名认证判定结果?
      • 图4
        • 认证通过以后应该是结束
        • 通过后,不需要返回上一步
      • 图5
        • 认证不通过以后建议重新发起认证流程
        • 简化业务流程,认证失败后不需要返回上一步
    • 第二轮需求评审
      • 图1
        • 身份证的正反面的示例图片的修改
      • 图6
        • 提示语错误,不应该是“支付失败”与实名认证完全无关
      • 图1~图6
        • 流程节点(审核中)缺失,所有的图片都应该增加该节点状态
      • 图4
        • 节点状态应该是审核中,而不是验证完成
4.2 编写测试计划与测试方案(了解)
  • 负责人

    • 测试组长、经理(第一负责人、管理经验)

    • 测试工程师

  • 测试计划

    • 概念:是指描述了要进行的测试活动的范围、方法、资源和进度的文档。

    • 核心内容:

      • 范围与目标

      • 角色与职责

      • 进度与资源

      • 风险与应对

      • 准入准出标准

  • 测试方案

    • 概念:是从测试的技术角度去分析需求,在方向上明确要怎么测,分析结果重点在于测试策略与技术实现。

    • 核心内容

      • 方法

      • 环境

      • 工具

  • 面试题:测试计划与测试方案的区别?

    • 测试计划是【管理型】文档,测试方案是【技术性】文档

    • 测试计划主要解决【做什么?】【谁来做?】,测试方案主要解决【怎么做?】

    • 主要内容存在差异:

      • 测试计划主要内容如下:

        • 目标与范围
        • 角色与职责
        • 资源与进度
        • 风险与应对
        • 准入与准出
      • 测试方案主要内容如下:

        • 策略与方法
        • 环境
        • 工具的选择
4.3 设计测试用例与评审(重点)
  • 基本测试策略
    • 冒烟测试
      • 基本功能检查
      • 核心业务流程测试
    • 单功能测试
      • 轮播图
      • 购物车
      • 后台会员管理
      • 抢购
    • 集成测试与回归
    • 系统测试与回归
    • 验收测试与回归
  • 测试用例核心要素
    • ID
    • 模块
    • 优先级
    • 标题
    • 测试数据
    • 前置条件
    • 测试步骤
    • 预期结果
4.4 执行测试用例与bug跟踪(重点)
  • 缺陷模板核心要素

    • ID

    • 标题

    • 优先级

    • 严重程度

    • 预置条件

    • 测试数据

    • 复现步骤

    • 预期结果

    • 实际结果

    • 缺陷类型

    • 缺陷状态

4.5 编写测试报告(了解)
  • 测试概要
  • 缺陷统计与分析
  • 测试结论
5. 数据库
5.1 数据库信息获取渠道
  • 数据表设计文档
  • DDL
5.2 用户表【tp_users】
  • 5.2.1 查询用户表中最后一条记录
-- 练习1:查询用户表中最后一条记录
select * from tp_users order by user_id desc limit 1;
  • 5.2.2 修改用户表中某个用户的用户昵称
-- 练习2:修改用户表中某个用户的用户昵称
(1)查询修改前数据
select nickname from tp_users where user_id = 2599; 
(2)修改数据
update tp_users set nickname = 'jack' where user_id = 2599; 
(3)确认修改结果
select nickname from tp_users where user_id = 2599; 
5.3 商品表【tp_goods】
  • 5.3.1 查询商品表中排在前10位的商品信息,注意只显示字段:id,名称,库存,售价
-- 练习3:查询商品表中排在前10位的商品信息,注意只显示字段:id,名称,库存,售价
(1)确认表
(2)确认字段
(3)选择sql
select goods_id,goods_name,store_count,shop_price from tp_goods limit 10;
  • 5.3.2 修改商品名称:将商品名称【小米手机5,十余项黑科技,很轻狠快】修改为【小米手20】
-- 练习4:将商品名称【小米手机5,十余项黑科技,很轻狠快】修改为【小米20】
update tp_goods set goods_name = '小米20' where goods_name LIKE '小米手机5%';
注意:前台页面显示内容变化。
5.4 订单表【tp_order】
  • 5.4.1 查询手机号是’xxxxxxx’的会员账号的昵称以及所下订单的订单编号
-- 练习5:查询手机号是'13488888888'的会员账号的昵称以及所下订单的订单编号
select tp_users.nickname,tp_order.order_sn from tp_users LEFT JOIN tp_order ON tp_users.user_id = tp_order.user_id where tp_users.mobile=13488888888;

别名:
select u.nickname,o.order_sn from tp_users as u LEFT JOIN tp_order as o ON u.user_id = o.user_id where u.mobile=13488888888;
5.5 导航表【tp_navigation】
  • 5.5.1 修改导航栏中“手机城”的数据,将显示名称改掉“手机大卖场”
-- 练习6:修改导航栏中“手机城”的数据,将显示名称改掉“手机大卖场”
update tp_navigation set name = '手机大卖场' where name='手机城';
今日总结
  • 了解Windows下WAMP环境搭建
  • 掌握熟悉项目的四大步骤
  • 掌握业务组织架构图的绘制方法
  • 掌握项目的测试流程
    • 需求分析
    • 编写测试计划与测试方案
    • 设计测试用例与评审
    • 执行用例与缺陷跟踪
    • 编写测试报告
  • 了解测试人员在需求评审中的职责
  • 熟悉测试计划和测试方案的核心内容
  • 熟悉测试用例和缺陷模板的核心要素
  • 熟悉项目中的用户表,商品表,订单表

二、轮播图
1、需求分析与评审
  • 测试工程师在需求评审中的主要职责是什么?
    • 确认自己理解需求、无疑义
    • 确认需求无明显错误、能够支撑后续的用例设计等
    • 提出一些改进建议
2、编写测试计划
  • 负责人

    • 测试组长、经理(第一负责人、管理经验)

    • 测试工程师

  • 测试计划

    • 概念:是指描述了要进行的测试活动的范围、方法、资源和进度的文档。
    • 核心内容:
      • 范围与目标
      • 角色与职责
      • 进度与资源
      • 风险与应对
      • 准入准出标准
3、设计测试用例与评审
3.1 设计测试用例
  • 设计测试用例方法

    • 需求==》测试点==》测试用例

    • 一个测试点就是一条测试用例

  • 测试用例设计步骤

    • 需求分析

    • 拆分测试点

    • 设计用例

3.2 测试用例评审
  • 同行评审(内部评审):测试组长、经理、测试工程师
  • 项目内评审:产品、项目、开发、客户、测试
4、执行测试用例与缺陷跟踪
4.1 执行测试用例
  • 查看标题

  • 看预置条件

  • 按照执行步骤进行测试

  • 比对预期结果与当前测试的实际结果

4.2 缺陷跟踪管理
  • 缺陷报告

    • ID
    • 标题
    • 模块
    • 严重程度
    • 优先级
    • 复现步骤
    • 前置条件
    • 预期结果
    • 实际结果
    • 缺陷类型
    • 缺陷状态
  • 工具:禅道

5、 编写测试报告
  • 测试概要
    • 本次测试对象:轮播图功能
    • 工作:
      • 设计测试用例11条,并且提交了相关excel产物
      • 完成用例在版本V1.0上测试工作,发现3个bug(s3:1个,s4:2个),建议发布新版本之前修复即可
  • 缺陷统计与分析
    • 分析图
  • 测试结论
    • 无重大bug,但是不建议上线,需要改进的bug3个
三、购物车
1、需求分析与评审
  • 测试工程师在需求评审中的主要职责是什么?
    • 确认自己理解需求、无疑义
    • 确认需求无明显错误、能够支撑后续的用例设计等
    • 提出一些改进建议
2、编写测试计划
  • 负责人

    • 测试组长、经理(第一负责人、管理经验)

    • 测试工程师

  • 测试计划

    • 概念:是指描述了要进行的测试活动的范围、方法、资源和进度的文档。
    • 核心内容:
      • 范围与目标
      • 角色与职责
      • 进度与资源
      • 风险与应对
      • 准入准出标准
3、设计测试用例与评审
3.1 设计测试用例

在这里插入图片描述

  • 设计测试用例方法

    • 需求==》测试点==》测试用例

    • 一个测试点就是一条测试用例

  • 测试用例设计步骤

    • 需求分析

    • 拆分测试点

    • 设计用例

3.2 测试用例评审
  • 同行评审(内部评审):测试组长、经理、测试工程师

  • 项目内评审:产品、项目、开发、客户、测试

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5hH0f9vp-1684253119889)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200624160759562.png)]

4、执行测试用例与缺陷跟踪
4.1 执行测试用例
  • 查看标题

  • 看预置条件

  • 按照执行步骤进行测试

  • 比对预期结果与当前测试的实际结果

4.2 缺陷跟踪管理
  • 缺陷报告

    • ID
    • 标题
    • 模块
    • 严重程度
    • 优先级
    • 复现步骤
    • 前置条件
    • 预期结果
    • 实际结果
    • 缺陷类型
    • 缺陷状态
  • 工具:禅道

5、 编写测试报告
  • 测试概要

    • 本次测试对象:轮播图功能
    • 工作:
      • 设计测试用例11条,并且提交了相关excel产物
      • 完成用例在版本V1.0上测试工作,发现3个bug(s3:1个,s4:2个),建议发布新版本之前修复即可
  • 缺陷统计与分析

    • 分析图
  • 测试结论

    • 无重大bug,但是不建议上线,需要改进的bug3个
今日总结
  • 轮播图
    • 掌握轮播图测试点分析
    • 掌握轮播图测试用例编写
    • 掌握轮播图测试用例执行与缺陷跟踪
  • 购物车
    • 掌握购物车测试点分析
    • 掌握购物车测试用例编写
    • 掌握购物车测试用例执行与缺陷跟踪
购物车
编写测试用例常见问题

1、测试步骤需要写清楚,怎么判定加、减成功或者失败

2、编辑商品数量【+】【-】功能时,漏了当前商品数量为库存量(库存小于200的情况)

3、预期结果中写明,测试执行后需要在软件界面上观察的现象。不是拷贝标题

4、测试编辑商品数量时,漏了当前商品数量为库存量(库存小于200的情况)——有效数据

5、测试编辑商品数量时,漏了当前商品数量为库存量+1(库存小于200的情况)——无效数据

无效的情况(0、21种商品)

标准:考虑这种情况是否存在,用户是否可能操作?

  • 不用考虑无效的情况
    • 删除商品:21种商品,不可能存在,不用测试21种商品的删除
    • 【+】【1】编辑商品:当前商品数量为0/201,不可能存在,因此不用测试当前商品数量为201时的【+】【1】
  • 需要考虑无效的情况:
    • 修改编辑商品数量:输入0,201,可能存在,用户可以操作,因此要测试这两种无效
四、后台会员列表
1、需求分析与评审
  • 测试工程师在需求评审中的主要职责是什么?
    • 确认自己理解需求、无疑义
    • 确认需求无明显错误、能够支撑后续的用例设计等
    • 提出一些改进建议
2、编写测试计划
  • 负责人

    • 测试组长、经理(第一负责人、管理经验)

    • 测试工程师

  • 测试计划

    • 概念:是指描述了要进行的测试活动的范围、方法、资源和进度的文档。
    • 核心内容:
      • 范围与目标
      • 角色与职责
      • 进度与资源
      • 风险与应对
      • 准入准出标准
3、设计测试用例与评审
3.1 设计测试用例
  • 设计测试用例方法

    • 需求==》测试点==》测试用例

    • 一个测试点就是一条测试用例

  • 测试用例设计步骤

    • 需求分析

    • 拆分测试点

    • 设计用例

3.2 测试用例评审
  • 同行评审(内部评审):测试组长、经理、测试工程师
  • 项目内评审:产品、项目、开发、客户、测试
4、执行测试用例与缺陷跟踪
4.1 执行测试用例
  • 查看标题

  • 看预置条件

  • 按照执行步骤进行测试

  • 比对预期结果与当前测试的实际结果

4.2 缺陷跟踪管理
  • 缺陷报告

  • 工具:禅道

5、 编写测试报告
  • 测试概要
  • 缺陷统计与分析
  • 测试结论
今日总结
  • 后台会员列表
    • 掌握后台会员列表测试点分析
    • 掌握后台会员列表测试用例编写
    • 掌握后台会员列表测试用例执行与缺陷跟踪
今日目标
  • 抢购
    • 掌握抢购测试点分析
    • 掌握抢购测试用例编写
    • 掌握抢购测试执行与缺陷跟踪
  • 了解非功能测试
五、 抢购
1、抢购管理列表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Lr2IP04I-1684395592094)(image/image-20200627111932880.png)]

2、添加抢购活动

在这里插入图片描述

3、抢购活动的状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-utPVg2pj-1684395592097)(image/image-20200627114447888.png)]

4、商品抢购活动展示效果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ufMmfC4r-1684395592097)(image/image-20200627160454277.png)]

5、 购物车中的抢购商品

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zXCRTpvz-1684395592097)(image/image-20200627160524961.png)]

6、 抢购活动的首页导航栏设置
  • 在系统—设置—自定义导航栏,新增一个自定义导航

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W7MGT88r-1684395592098)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200627114611344.png)]

7、 抢购活动前台主页的显示
六、 非功能性测试
1、 兼容性测试
  • 概念:不同平台、系统都能正常工作

  • 测试关注点(web)

    • 浏览器

      • IE、Chrome、Firefox

      • IE以实际客户环境为准

        image-20200627164423838
    • 操作系统

      • 不同的操作系统:Windows、Linux、mac等
      • 相同的操作系统不同的版本:win7、win8、win10
    • 网络

    • 分辨率

2、界面测试(UI)
  • 布局

  • 风格

  • 按钮

  • 测试基本原则

    • 参照UI设计图
3、易用性
  • 易用性:易懂,易学,易用,易吸引
  • 测试关注点
    • 用户群体
    • 计算机水平
    • 项目复杂性
    • tab/enter等
4、性能测试
  • 对性能有要求
  • 用户量大
  • 并发测试、压力测试、负载测试
5、安全性
  • 测试关注点(业务层面)
    • 输入数据
      • 敏感信息遮挡处理(密码、身份证、银行卡、存款等)
      • 不能复制
    • 传输数据
      • 数据要加密
      • 加密要有复杂度(加密算法MD5…)
    • 输出数据
      • 数据库中敏感信息要加密
  • sql注入(了解):攻击者把SQL语句(如:【’ ’ or 1=1 #】,【’ ’ or 1=1 – 】等)作为参数传入web应用程序,最终达到欺骗服务器执行恶意的SQL语句。
  • 渗透测试(了解):专业的安全工程师负责测试
    • 趣味小故事
      • 黑掉阿里内网—道哥 【https://www.toutiaobaike.com/wuhanqing/1917.html】
      • 入侵腾讯—菜霸【https://www.seoxiehui.cn/article-54102-1.html】
面试题:测试用例设计
  • 功能
  • 非功能
    • 兼容性
    • UI界面
    • 易用性
    • 性能测试
    • 安全性测试
面试题1:登录
具体需求: 有一个登录页面,有一个账号和一个密码输入框, 一个提交按钮。 
此题的考察目的: 
1、了解需求(测什么都是从了解需求开始); 
2、是否有设计 Testcase 的能力 
3、是否熟悉各种测试方法;
4、是否有丰富的 web 测试经验; 
5、是否了解 web 开发;

了解需求: 
1、登录界面应该是弹出窗口式的,还是直接在网页里面; 
2、账号长度和密码的强度(比如需要多少位、大小写敏感、特殊字符混搭等); 
3、界面美观是否有特殊要求?(即是否要进行 UI 测试); 
4、····

用例设计: 
测试需求分析完成后,开始用例设计,主要可以从以下几个方面考虑: 
功能测试:
1、输入正确的账号和密码,点击提交按钮,验证是否能正确登录。(正常输入) 
2、输入错误的账号或者密码, 验证登录会失败,并且提示相应的错误信息。(错误校验) 
3、登录成功后能否跳转到正确的页面(低) 
4、账号和密码,如果太短或者太长,应该怎么处理(安全性,密码太短时是否有提示) 
5、账号和密码,中有特殊字符(比如空格),和其他非英文的情况(是否做了过滤) 
6、记住账号的功能 
7、登录失败后,不能记录密码的功能 
8、账号和密码前后有空格的处理 
9、密码是否加密显示(星号圆点等) 
10、牵扯到验证码的,还要考虑文字是否扭曲过度导致辨认难度大,考虑颜色(色盲使用者),刷新或换一个 按钮是否好用 
11、登录页面中的注册、忘记密码,登出用另一帐号登录等链接是否正确 
12、输入密码的时候,大写键盘开启的时候要有提示信息。 
13、什么都不输入,点击提交按钮,看提示信息。(非空检查)

界面测试:
1、布局是否合理 2个输入框和一个按钮是否对齐 
2、输入框和按钮的长度,高度是否符合要求 
3、界面的设计风格是否与 UI 的设计风格统一 
4、界面中的文字简洁易懂,没有错别字。

性能测试:
1、打开登录页面,需要几秒 
2、输入正确的账号和密码后,登录成功跳转到新页面,不超过 5 秒

安全性测试:
1、登录成功后生成的 cookie 是否有 httponly(降低脚本盗取风险) 
2、账号和密码是否通过加密的方式,发开给 web 服务器 
3、账号和密码的验证,应该是用服务器端验证,而不能单单是在客户端用 js 验证 
4、账号和密码的输入框,应该屏蔽 SQL 注入攻击 
5、账号和密码的输入框,应该禁止输入脚本(防止 XSS 攻击) 
6、错误登录的次数限制(防止暴力破解) 
7、考虑是否支持多用户在同一机器上登录; 
8、考虑一用户在多台机器上登录

可用性测试: 
1、是否可以全用键盘操作,是否有快捷键 
2、输入账号,密码后按回车,是否可以登录 
3、输入框是否可以以 tab 键切换

兼容性测试:
1、主流的浏览器下能否显示正常已经功能正常(IE6~11, 谷歌、火狐等 ) 
2、不同的平台是否能正常工作,比如 windows, mac等 
3、移动设备上是否正常工作,比如 iphone, android 
4、不同的分辨率

本地化测试:
1、不同语言环境下,页面的显示是否正确。 

软件辅助性测试:软件辅助功能测试是指测试软件是否向残疾用户提供足够的辅助功能 
1、高对比度下能否显示正常(视力不好的人使用)
面试题2:微信朋友圈

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FwsOJQH1-1684395592098)(image/微信朋友圈.png)]

6、 用例设计主要问题

主要问题存在于
1、测试点分析:逻辑性不强
​ 对于整个页面功能划分不清晰;
​ 不同测试点归类不清晰;
​ 不能形成相对固定的套路,书写耗费大量时间…
2、测试用例:关于,要细致到什么程度,不太明确 (先把优先级高的用例写下来,优先级用例低的测试时带上测下)
​ 对于UI效果等的检查也要写进初次测试的用例吗?

3、测试用例设计时是依据需求说明书还是系统?

  • 流程规范的公司,一定是基于需求说明书(或原型图)来设计测试用例
  • 进入项目的时间节点来看
    • 项目初期介入,依据需求说明书
    • 项目中后期介入,依据还是需求说明书
      • 有可能在实际测试过程中,没有需求说明书,可以参考当前的系统,同时需要结合自身测试经验进行结果的甄别
    • 项目维护阶段介入,依据需求说明书
      • 有可能在实际测试过程中,没有需求说明书,可以参考当前的系统、用户手册、bug清单等

4、这个用例没啥问题 就是时间问题 没写完

测试数据

  • 注意测试数据的时效性(测试准备)
    • 如注册时的手机号在第一次注册时是未注册的,第二次再注册时就变为已注册了,所以不是特定的数据场合下,我们可以省略这些测试数据。
  • 标题与预期结果要明确
    • 注意:如果需求中没有说明类似的错误提示消息,我们应该借助于其他同类型产品的处理方案或消息来设置用例的预期结果。

测试标题

  • 直接点明测试的目的

  • 简明扼要,不要太冗长

    • 比如异常类测试时,重点关注导致异常的条件即可,(其他正确参数可以放在预置条件里面、实际工作中约定的规则下可以不写其他正常的参数)
    • 如果是正常类测试时,可以依据有效等价类的类别(如登录时,qq、手机号、邮箱等)来细分设计测试用例
  • 标题一般来说不重复

优先级

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wp51RxVd-1684395846538)(C:\Users\guoha\AppData\Roaming\Typora\typora-user-images\1684391026752.png)]

今日总结
  • 抢购

    • 掌握抢购测试点分析
    • 掌握抢购测试用例编写
    • 掌握抢购测试执行与缺陷跟踪
  • 了解非功能测试

今日目标
  • 掌握状态迁移法的使用
  • 掌握订单的状态测试
  • 掌握流程图主要元素及画法
  • 能够绘制tpshop下单及发货流程图
  • 掌握tpshop业务流程测试用例的编写
1、状态迁移法
  • 概念:

    • 基于系统中模块或节点之间的状态。来描绘状态与状态之间的关系,从而找到状态之间转化的路线设计测试用例的一种方法。
  • 适用场景

    • 需要针对复杂业务场景设计测试用例时
  • 使用步骤:

    1. 找出系统所有的节点

    2. 绘制状态迁移图

    3. 绘制状态迁移树

    4. 找出状态之间的转换路径

  • 案例分析——飞机售票系统

飞机售票系统:
(1)客户向航空公司打电话预定机票,此时机票信息处于【预定】状态。
(2)顾客支付了机票费用后,机票信息变为【已支付】状态。
(3)旅客当天到达机场,拿到机票后,机票信息变为【已出票】状态。
(4)登机检票后,机票信息变为【已使用】状态。
(5)在检票之前任何时间都可以取消自己的订票信息,取消后,订单信息处于【已取消】状态。
  1. 明确状态节点:【预定】、【已支付】、【已出票】、【已使用】、【已取消】

  2. 绘制状态迁移图

    image-20200629150214121
  3. 绘制状态迁移树

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sqac5Vuf-1684395846539)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200629150844908.png)]

  4. 抽取测试路径设计用例

路径1:预定==》已支付==》已出票==》已使用
路径2:预定==》已取消
路径3:预定==》已支付==》已取消
路径4:预定==》已支付==》已出票==》已取消
2、订单测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GWQZ0s7R-1684395846540)(image/image-20200624101916980.png)]

需求说明:
1.用户在网站完成下单后,订单状态为“等待付款”
2.用户完成付款后,订单状态变为“待发货” 
3.管理员对订单进行确认并发货后,订单状态变为“待收货” 
4.用户收到商品后,在系统中进行确认收货,订单状态变为“待评价” 
5.用户使用商品后,对商品进行评价,评价提交后,订单状态变为“已完成” 
6.商品发货前,用户可以对订单进行取消操作,取消后订单状态变为“已取消” 
7.用户付款前,管理员可以认定订单无效,此时订单处于“已作废”状态
  1. 找出流程节点与状态

    【等待付款】、【待发货】、【待收货】、【待评价】、【已完成】、【已取消】、【已作废】

  2. 绘制状态迁移图

  3. 绘制状态迁移树

    image-20200629152955237
  4. 找到状态之间转换的所有路径

    路径1:【等待付款】》【待发货】》【待收货】》【待评价】》【已完成】

    路径2:【等待付款】==》【已作废】

    路径3:【等待付款】==》【已取消】

    路径4:【等待付款】》【待发货】》【已取消】

3、业务流程测试
3.1 流程图介绍(复习)

流程图:

流程图是对过程、算法、流程的一种图像表示,在技术设计、交流及商业简报等领域有广泛的应用。
通常用一些图框来表示各种类型的操作,在框内写出各个步骤,然后用带箭头的线把它们连接起来,以表示执行的先后顺序。用图形表示算法,直观形象,易于理解。有时候也被称之为输入-输出图。
image-20200624103002349
  • 椭圆:开始/结束
  • 箭头:路径,流程的走向
  • 平行四边形:数据的输入/输出
  • 长方形:处理/步骤/过程
  • 菱形:判定/判断
3.2 绘制流程图

绘制原则:

  • 不要漏掉流程路径
  • 现有判断,再有判断结果
  • 推荐讲主业务流程放在最中间,便于阅读

案例1:ATM取款流程

image-20200625090359718

案例2:缺陷管理流程

在这里插入图片描述

3.3 业务流程测试
  • 业务流程测试的关注点:

    • 关注点在核心业务是否能够跑通
  • 重点不是关注单个功能模块的细节点

  • 业务流程测试的价值:

    • 客户角度:对客户最有价值的是业务的实现,不是单功能模块的质量
    • 测试人员角度:分配任务往往是针对功能模块划分,业务流程的测试容易遗漏
  • 进行业务流程测试的时机

    • 上线前进行业务流程测试的确认

    • 单功能模块基本可用的情况下,尽早进行(冒烟测试)

3.4 业务流程测试用例设计
  • 需求分析,明确流程
  • 画出流程图
  • 编写测试用例,一条路径对应一条测试用例
    • 路径比较多时,可以对所测业务路径设置优先级
3.5 测试团队中体现专业价值,个人价值
  • 熟悉项目阶段,画出组织架构图,展现工作成果
  • 进入项目,进行一段时间的测试之后,画出项目的业务流程图
    • 体现个人对项目业务的深入理解
    • 业务流程图可以作为整个团队的知识积累
4、tpshop业务流程测试
4.1 绘制tpshop下单流程
image-20200625102206284
4.2 绘制tpshop发货流程

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IkVxDm6N-1684395846540)(image/image-20200625102437101.png)]

4.3 设计tpshop业务流程测试用例
  • 前台下单

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HBpnfChx-1684395846541)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200625113703712.png)]

  • 后台发货

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MlXUr2ZT-1684395846541)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200625113723372.png)]

今日总结
  • 掌握状态迁移法的使用
  • 掌握订单的状态测试
  • 掌握流程图主要元素及画法
  • 能够绘制tpshop下单及发货流程图
  • 掌握tpshop业务流程测试用例的编写
七、 功能测试与数据库、Fiddler
今日目标
  • 掌握功能测试涉及到的四种数据库场景
  • 了解HTML和HTTP协议
  • 熟悉HTTP请求和响应的内容
  • 熟悉HTTP请求方法get和post
  • 了解fiddler的应用场景
  • 掌握fiddler过滤功能的使用
  • 掌握fiddler修改请求数据方法
1、功能测试与数据库
1.1 项目与数据库的关系

在这里插入图片描述

  • 项目中的数据是存储在数据库中的

  • 对数据库修改(增删改查)会影响项目页面显示

  • 实操练习:

    • 修改数据库中“小米手机5,十余项黑科技,很轻狠快”的商品名称,在前台页面看到变化

      修改数据库中“小米手机5,十余项黑科技,很轻狠快”的商品名称,在前台页面看到变化
      
      

    1、数据表 tp_goods
    2、字段 goods_name
    3、操作语句 update 表名 set 字段名 = 字段值 where 条件

    修改前:
    select * from tp_goods where goods_name = ‘小米手机5,十余项黑科技,很轻狠快’ – 精确查询
    select * from tp_goods where goods_name like ‘小米手机5%’ – 模糊查询

    修改:
    update tp_goods set goods_name = ‘小米手机55’ where goods_name = ‘小米手机5,十余项黑科技,很轻狠快’

    修改后:
    select * from tp_goods where goods_name = ‘小米手机5,十余项黑科技,很轻狠快’ – 精确查询
    select * from tp_goods where goods_name like ‘小米手机5%’

    - 修改数据库中'力士精油香氛幽莲魅肤沐浴乳1000ml(新老包装随机发货)'的商品价格,在前台页面看到变化
    
      ```sql
      修改数据库中'力士精油香氛幽莲魅肤沐浴乳1000ml(新老包装随机发货)'的商品价格,在前台页面看到变化
      
      1、数据表    tp_goods
      2、字段      shop_price
      3、操作语句  update 表名 set 字段名 = 字段值 where 条件
      
      修改前:   -- 精确查询
      select * from tp_goods where goods_name like '力士精油香氛%'                      -- 模糊查询
      
      修改:
      update tp_goods set shop_price = 9.9 where goods_name like '力士精油香氛%' 
      
      修改后:
      select * from tp_goods where goods_name like '力士精油香氛%'  
    
1.2 数据库典型应用场景(重点)
  • 验证数据的准确性与完整性
  • 借助数据库进行缺陷定位
  • 借助数据库构造测试场景(需要特定的测试数据)
  • 借助数据库数据备份更新
1.2.1 验证数据的准确性与完整性
  • 执行用例过程中,有时需要到数据库验证数据的准确性与完整性

    image-20200630094809772
    
    
1.2.2 借助数据库进行缺陷定位
  • 进行BUG定位时,有时需要到数据库查看数据的详细信息

    BUG定位----前台后性别不一致(保密和女)
    SELECT sex from tp_users where mobile = 13488888888;
    
    页面设置为保密,点击保存显示为【男】。
    (1)数据库查询结果是【0】,前端bug
    (2)数据库查询结果是【1】,后端bug
    
1.2.3 借助数据库构造测试场景(需要特定的测试数据)
  • 构造某种测试场景时,可以在数据库里直接修改数据,要比使用界面更有效率

    select goods_num from tp_cart
    
    update tp_cart set goods_num = 99999  
    
1.2.4 借助数据库数据备份更新
  • 软件升级过程中,有时会涉及到历史数据的处理,这种情况需要执行升级SQL,并验证结果

    用户表新增蚂蚁积分字段(myjf),每个用户默认100积分
    ALTER TABLE tp_users ADD COLUMN myjf int(3) DEFAULT 100;
    
2、功能测试与抓包工具
  • 抓包:(package capture)就是将网络传输发送与接收的数据包进行截获、重发、编辑、转存等操作,也用来检查网络安全。抓包经常被用来进行数据截取等。

  • 功能测试用到抓包工具的场景:

    • 通过抓包工具截取观察网站的请求信息,帮助我们更深入的了解网站

    • 通过抓包工具截取、观察网站的请求与返回信息,帮助测试进行BUG定位与描述

    • 通过抓包工具拦截修改请求信息,绕过界面的限制,测试服务端的功能

  • 常用的抓包工具:Fiddler、Charles、F12开发人员工具等

2.1 HTML与HTTP协议
  • URL:统一资源定位符
  • HTML:超文本标记语言
  • HTTP:超文本传输协议

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MYmPiKoh-1684396174435)(.\image\http.jpg)]

2.1.1 URL
  • 示例:http://localhost/index.php?m=Home&c=Goods&a=goodsInfo&id=46
  • 格式:
    • 协议:客户端和服务器通讯的标准,http、https、ssh等
    • ip或域名
    • 端口号:协议默认的端口号是可以省略的
      • http:默认端口80
      • https:默认端口443
      • ssh:默认端口22
    • 资源路径:资源存放的位置,资源可以是各种超文本信息,如音频、视频等
    • 参数(如?m=Home&c=Goods&a=goodsInfo&id=46
      • 格式:
        • 用?与URL的主体部分分开
        • 参数的格式参数名=参数值,有多个参数时用&拼接即可
2.1.2 HTML

HTML:HyperText Markup Language ,超文本标记语言

  • 超文本:声音、视频、图片、超链接等

  • 标记:就是通过【<标记符>内容</标记符>】的格式让内容具有不同的表现形式,从而达到超文本的目的

    • 如:<title>百度一下,你就知道</title>

    • 互联网上浏览的网页,本质上就是超文本标记语言。

2.1.3 HTTP

HTTP: HyperText Transfer Protocol ,超文本传输协议,是互联网上最常用的协议之一。

2.2 HTTP请求与响应

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ztPCGXgi-1684396174435)(.\请求与响应.png)]

2.2.1 基本概念
  • 客户端:用于发送请求,如浏览器、APP等
  • 服务器:处理客户端请求并返回数据,如apache、nginx等
  • 请求:客户端向服务器索要数据
  • 响应:服务里处理完成后,返回给客户端的数据与信息
2.2.2 HTTP请求
  • 请求内容

    • 请求行:

      • 位置是在第一行

      • 请求方式、请求地址、协议及版本

    • 请求头:

      • 位置是在第一行之后,到空行之前

      • 用来描述客户端信息的相关参数,一般以键值对的形式存在,如描述浏览器类型等

    • 请求体:

      • 位置是在空行之后

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IptBIf03-1684396174435)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200630144814848.png)]

  • 请求方式(GET 和 POST)

    • get:用于查询,如搜索商品
    • post:用于提交数据,相对比较安全,如登录、注册等
2.2.3 HTTP响应
  • 响应内容

    • 响应行:位置是在第一行,包含协议及版本、响应状态码、状态消息

    • 响应头:位置是在第一行之后,到空行之前,告诉客户端服务器相关信息,如web服务器类型等

    • 响应体:位置是在空行之后,如登录成功

  • 响应状态码:由3位数字组成,第一位数字代表响应消息的级别

    • 2XX:成功,如200
  • 3XX:重定向,如301

    • 4XX:客户端存在问题,如404
  • 5XX:服务器端存在问题,如501

面试题:GET和POST的区别
  • 最直观的区别就是GET把参数包含在URL中,POST通过request body(请求体)传递参数。
  • GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
  • GET在浏览器回退时是无害的,而POST会再次提交请求。
  • GET请求只能进行url编码,而POST支持多种编码方式。
  • GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
  • GET请求在URL中传送的参数是有长度限制的,而POST么有(注意:这个限制是由浏览器导致)。
  • 对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
  • GET参数通过URL传递,POST放在Request body中。
2.3 抓包工具

功能测试与Fiddler

  • 通过抓包工具截取观察网站的请求信息,帮助我们更深入的了解网站

  • 通过抓包工具截取、观察网站的请求与返回信息,帮助测试进行BUG定位与描述

  • 通过抓包工具拦截修改请求信息,绕过界面的限制,测试服务端的功能

2.3.1 Fiddler原理
  • 原理:
    • 请求先发送给Fiddler,Fiddler接收请求后转发给服务器
    • 服务器处理请求后将响应数据返回给Fiddler,Fiddler在转发给客户端(浏览器)

2.3.2 Fiddler安装
  • 安装依赖

    • Miscrosoft .Net Framework
  • 安装步骤

    1. 点击【I Agree】
    2. 选择安装目录,默认即可,点击【Install】
    3. 等待安装完成,点击【Close】
  • 启动Fiddler:以Windows10系统为例说明

    • Windows ==》Fiddler 》右键【更多】》打开文件所在位置 ==》找到Fiddler图标 ==》右键【发送到桌面快捷方式】
2.3.3 Fiddler使用
2.3.3.1 抓包(Inspectors)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AyGc03wt-1684396174435)(image/image-20200625145214255.png)]

  • 请求

    • 请求行

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zRpsEvKt-1684396174436)(D:/%E5%8C%97%E4%BA%AC%E4%BF%AE%E6%AD%A3%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%E5%B0%B1%E4%B8%9A22%E6%9C%9F/%E9%BB%91%E9%A9%AC%E8%BD%AF%E4%BB%B6%E6%B5%8B%E8%AF%95%E5%B0%B1%E4%B8%9A1%E6%9C%9F%EF%BC%8820200430%EF%BC%89/02%20%E5%8A%9F%E8%83%BD%E6%B5%8B%E8%AF%95%E5%8F%8A%E7%94%B5%E5%95%86%E5%AE%9E%E6%88%98/06%20%E5%AE%9E%E6%88%98%E6%A3%80%E9%AA%8C/01%20Linux+%E6%95%B0%E6%8D%AE%E5%BA%93/02%20%E6%95%B0%E6%8D%AE%E5%BA%93/image/image-20200313162720402.png)]

    • 请求头

    • 请求体

  • 响应

    • 响应行
    • 响应头
    • 响应体
2.3.3.2 删除请求
  • 菜单删除:

  • 命令行删除:cls、clear

  • 键盘delete

  • 快捷键:Ctrl + X

2.3.3.3 设置过滤
  1. 点击Filters页签,勾选“Use Filters”

  2. Hosts下方的第二个下拉框,选择“Show Only the following Hosts”

  3. 在下方输入框中输入要抓包的主机地址(多个地址用英文分号隔开,如:localhost;127.0.0.1)

  4. 点击右上角的“Actions”,选择“Run Filterset Now”

  5. 如果取消过滤,去掉“Use Filters”的勾选

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vzBVrXMB-1684396174437)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200313163845092.png)]

2.3.3.4 设置断点

  • 修改请求
    1. 进入添加会员的页面,填写正确的手机号码和其他信息
    2. 打开fiddler拦截开关:Rules ==》 Automatic Breakpoints ==》 Before Requests
    3. 回到添加会员界面,点击提交按钮
  1. 回到Fiddler,修改【请求体】,如修改手机号码内容

  2. 点击Fiddler中请求下方的绿色按钮“Run to Completion”

  3. 关闭Fiddler拦截开关:Rules ==》 Automatic Breakpoints ==》 Disabled

  • 修改响应(扩展)

    1. 进入添加会员的页面,填写正确的手机号码和其他信息
    2. 打开fiddler拦截开关:Rules ==》 Automatic Breakpoints ==》 After Responses
    3. 回到添加会员界面,点击提交按钮
    4. 回到Fiddler,修改【响应体】,如修改【操作提示】的内容
    5. 点击Fiddler中请求下方的绿色按钮“Run to Completion”
    6. 关闭Fiddler拦截开关:Rules ==》 Automatic Breakpoints ==》 Disabled
2.3.3.5 AutoResponder(扩展)
  • 自动响应

    1.进入AutoResponder

    2.选择列表左侧请求,点击【Add Rule】添加mock请求(或点击【Add Rule】手动填写请求地址)

    3.选择响应结果,模拟测试场景(此处支持打开本地文件,根据文件内响应数据(例如json文件)进行mock)

    4.点击右下角【save】,保存响应设置

    5.勾选上方选项:

    (1)Enable rules:开启或禁用自动重定向功能,勾选上时,激活规则

    (2)Unmatched requests passthrough:未匹配的请求穿透,即勾选上时,不影响那些没满足我们处理条件的请求

    (3)勾选了这个选项,在规则里面就可以设置是立即返回响应,还是隔多少毫秒返回响应

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VnlOspVA-1684396174437)(D:/ce/%E7%AC%94%E8%AE%B0/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/image/image-20200630171639905.png)]

2.3.3.6 Composer(扩展)
2.3.3.7 弱网测试(扩展)

  • 概念:在当今移动互联网盛行的时代,网络的形态除了有线连接,还有2G/3G/Edge/4G/Wifi等多种手机网络连接方式。不同的协议、不同的制式、不同的速率,使移动应用运行的场景更加丰富。

    从测试角度来说,需要额外关注的场景就远不止断网、网络故障等情况了。对于弱网的数据定义,不同的应用所界定的含义是不一样且不清晰的,不仅要考虑各类型网络最低速率,还要结合业务场景和应用类型去划分。按照移动的特性来说,一般应用低于2G速率的都属于弱网,也可以将3G划分为弱网。除此之外,弱信号的Wifi通常也会被纳入到弱网测试场景中。

  • 为何要进行弱网测试?

    例如:进地铁、上公交、进电梯等,如果app没有对各种网络异常进行兼容处理,那么用户可能在日常生活中遇到APP闪退、ANR、数据丢失等问题。因此,app网络测试,特别是弱网测试显得尤为重要。

    我当前所在项目的产品是一款适配于低资源环境的医疗IT系统,目前主要是在坦桑尼亚地区使用。根据资料显示,在坦桑尼亚等东非国家,普遍使用的都是2G网络,覆盖率达到40%以上,3G网络的覆盖都非常少,并且稳定性较差。由此,对于当前的App应用交付要求即至少在弱网以及无网状态下能正常运行。

  • 步骤

    • 打开Fiddler,设置代理,并允许远程连接
    • 手机连接电脑的热点网络,或者同在一个局域网内
    • 手机网络连接中,设置网络代理,IP是电脑的同网段IP地址,端口是8888
    • 打开网速模拟模式开关(Rules → Performances → Simulate Modem Speeds )

    • 手机访问APP,或者用手机浏览器访问网络,观察功能响应或者页面刷新速度

    • 如果需要自定义网络的速度,需要到自定义规则中配置(Rules → Customize Rules)

      网络环境测试机带宽参考测试数据:
      在这里插入图片描述

2.3.3.8 HTTPS请求(扩展)

在这里插入图片描述

点击【OK】,重启Fiddler。

今日总结

  • 掌握功能测试涉及到的四种数据库场景
  • 了解HTML和HTTP协议
  • 熟悉HTTP请求和响应的内容
  • 熟悉HTTP请求方法get和post
  • 了解fiddler的应用场景
  • 掌握fiddler过滤功能的使用
  • 掌握fiddler修改请求数据方法

四、python

五、接口测试

------今日学习目标1------

1、接口测试理论

1.1、概念

  • 接⼝:系统之间(外部系统与内部系统,内部系统与内部系统)数据交通的通道。
  • 接⼝测试:校验 接⼝回发的 响应数据 与 预期结果 是否⼀致。在这里插入图片描述
  • 接⼝测试,可以绕过前端界⾯。直接对 服务器进⾏测试!!!

1.2、价值

  • 可以发现⻚⾯测试发现不了的问题
  • 符合 质量控制前移理念
  • 低成本,⾼收益!

1.3、实现方式

  • ⼯具
    • postman:使⽤简单,上⼿难度低。功能较少。
    • jmeter:使⽤难度较⼤。上⼿难度⼤。功能⻬全。
  • 代码
    • Python + requests + Unittest
    • java + HttpClient

2、HTTP协议

  • 协议:就是 规则!要求使⽤协议的双⽅必须 严格 遵守

HTTP协议简介

  • 简介:超⽂本传输协议,基于请求与响应的 应⽤层协议。
  • 特点
    1. 客户端、服务器模式
    2. 简单快速
    3. 灵活
    4. ⽆连接
    5. ⽆状态

URL格式

在这里插入图片描述
完整语法格式:协议 😕/ IP地址:端⼝号/资源路径?查询参数

  • 协议
    http、https。 作⽤:指定数据传输规则
  • IP地址
    也就是 域名。 作⽤:在⽹络环境中,唯⼀定位 ⼀台主机
  • 端⼝号
    作⽤:在 主机上,唯⼀定义个应⽤程序。
    可以省略。如果省略,跟随协议。 http - 80 。 Https - 443
  • 资源路径
    作⽤:应⽤对应的数据资源。
    可以省略。如果省略,资源路径为 “/”
  • 查询参数
    作⽤:给资源传递参数
    可以省略。如果省略,没有 ?分割符。
    可以有多组。每组 k=v 格式。各组之间 ⽤ “&” 隔分。

练习

  • 请写出以下URL的各个组成部分。这个URL没有写出端⼝号,它的端⼝是什么?

    http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=do_login
    //可以省略。如果省略,跟随协议。 http - 80 。 Https - 443
    

HTTP请求

  • 产⽣端
    ⼀定产⽣于 客户端。当 客户端给服务器发送请求时,使⽤该协议。(请求报⽂、请求包)

  • 整体格式

    • 请求⾏:请求⽅法、URL、协议版本

    • 请求头:k :v

    • 空⾏:代表 请求头 结束。

    • 请求体:发送给服务器请求时,携带的数据在这里插入图片描述

    • 【示例】:

      POST http://demo.zentao.net/user-login.html HTTP/1.1
      Host: demo.zentao.net
      User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101
      Firefox/68.0
      Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
      Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
      Accept-Encoding: gzip, deflate
      Referer: http://demo.zentao.net/user-login.html
      Content-Type: application/x-www-form-urlencoded
      Content-Length: 54
      Connection: keep-alive
      Upgrade-Insecure-Requests: 1
      account=demo&password=efc4a3b32e48054865e5a8321cfda3e4
      
  • 请求⾏

    • ⼀定位于 http请求协议的,第⼀⾏。格式:请求⽅法(空格) URL(空格) 协议版本
    • 请求⽅法:
      • GET:查询 —— 没有请求体
      • POST:添加 (注册、登录)
      • DELETE:删除 —— 没有请求体
      • PUT:修改
    • URL:⻅上。
    • 协议版本:常⻅ HTTP/1.1
  • 请求头

    • 位于 请求⾏之下,空⾏之上的部分。 数据组织格式 ⼀定是 k:v 对。
    • Content-Type : 作⽤,指定 请求体的数据类型。
      • application/json:请求体数据类型为json
      • application/x-www-form-urlencoded:请求体的数据类型 为 表单类型。
  • 请求体

    • 位于 空⾏ 之下。
    • 有的 请求协议 是没有请求体。如:get、delete
    • 请求体的数据类型, 受 请求头中 Content-Type 的值影响。

练习1

  • 以下是抓取的某个HTTP协议数据包的请求报⽂,请问其中,请求⾏,请求头,请求体分别是什么?

    POST ://tpshop-test.itheima.net/index.php HTTP/1.1
    Host: tpshop-test.itheima.net
    Connection: keep-alive
    Content-Length: 53
    Accept: application/json, text/javascript, */*; q=0.01
    Origin: http://tpshop-test.itheima.net
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
    AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90
    Safari/537.36
    Content-Type: application/x-www-form-urlencoded; charset=UTF-8
    Referer: http://tpshop-test.itheima.net/Home/user/login.html
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: is_mobile=0; province_id=1; city_id=2; district_id=3;
    is_distribut=1; PHPSESSID=1b80tii77mhle0fqd2bg52ucg5; cn=0
     username=13800138006&password=123456&verify_code=8888
    

HTTP响应

  • 产⽣端:
    ⼀定产⽣与 服务端。 当服务器接收到 http请求协议 之后,才会产⽣ http响应协议(响应报⽂、响应包)。

  • 整体格式:

    • 响应⾏:协议版本、状态码、状态码描述

    • 响应头:K:V 格式数据。

    • 空⾏:代表响应头 结束。

    • 响应体:服务回发给客户端的 数据。⼏乎 所有的 响应包,都有响应体。在这里插入图片描述
      【示例】:

      HTTP/1.1 200 OK
      Date: Fri, 22 May 2009 06:07:21 GMT
      Content-Type: text/html; charset=UTF-8
      <html>
       <head></head>
       <body>...</body>
      </html
      
  • 状态⾏

    • ⼀定位于 http响应协议的,第⼀⾏。格式:协议版本 (空格) 状态码 (空格) 状态码描述
  • 状态码:5 类:

    • 1xx:指示信息
    • 2xx:成功
    • 3xx:重定向
    • 4xx:客户端错误
    • 5xx:服务端错误在这里插入图片描述
  • 响应头

    • 位于 响应⾏之下,空⾏之上的部分。 数据组织格式 ⼀定是 k:v 对。
  • 响应体

    • 位于 空⾏ 之下。
    • ⼏乎所有 响应协议 都有响应体。
    • 响应体中 包含的数据,是接⼝测试过程中,所要使⽤的 实际结果!
  • 练习1

    • 以下是HTTP协议的响应报⽂内容,请问,状态⾏、响应头、响应体分别是哪⼏个部分?
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 29 Jun 2020 03:36:28 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Set-Cookie: is_mobile=0; expires=Mon, 29-Jun-2020 04:36:28 GMT;
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Content-Length: 805
{"status":1,"msg":"\u767b\u9646\u6210\u529f","result":
{"user_id":3338,"email":"","password":"519475228fe35ad067744465
c42a19b2","paypwd":null,"sex":0,"birthday":0,"user_money":"0.00
","frozen_money":"0.00","distribut_money":"0.00","underling_num
ber":0,"pay_points":100,"address_id":0,"reg_time":1590980161,"l
ast_login":1590980161,"last_ip":"","qq":"","mobile":"1380013800
 6","level_name":"\u6ce8\u518c\u4f1a\u5458"},"url":""}

3、ihrm项目介绍

  • ⼈⼒资源管理系统
  • URL:http://ihrm-test.itheima.net/
    • 模块:
    • 员⼯管理
    • 组织架构(部⻔管理)
    • 招聘管理
    • 考勤管理
    • 绩效管理
    • 在这里插入图片描述

4、接口规范

传统风格接口

  • 接⼝统⼀采⽤ get/post 实现 所有操作。
  • URL 与 资源不是 ⼀⼀对应的。在 URL 中查看出,是何种操作
  • 状态码统⼀ 返回 200在这里插入图片描述

RESTful风格接口

  • 接⼝使⽤的⽅法,与 http协议的 请求⽅法,⼀⼀对应。
  • get - 查、post - 增、put - 改、delete - 删
  • URL 与 资源 ⼀⼀对应!不能从 URL 中,看出 是 何种操作。 需要通过 结合 请求⽅法 来识别何种操作。
  • 响应状态码 使⽤较为全⾯在这里插入图片描述

小结

  • 传统⻛格接⼝:只⽤ get、post⽅法。 URL 不唯⼀。 统⼀返回 200
  • RESTful⻛格接⼝:URL 唯⼀,定位资源。结合 请求⽅法对应不同操作。 返回状态码 较灵活。在这里插入图片描述

5、接口测试流程.

    1. 需求分析(产品经理的需求⽂档)
    1. 接⼝⽂档解析(开发编写的 接⼝API⽂档)
    1. 设计 接⼝测试⽤例(编写 Excel 表格形式的⽤例)
    1. 准备接⼝测试脚本
    • postman ⼯具 ⽣成脚本
    • python 代码 编写脚本
    1. 执⾏测试⽤例,跟踪缺陷
    1. ⽣成 接⼝测试报告
    1. 接⼝⾃动化持续集成(可选)在这里插入图片描述

6、接口文档解析

什么是接口文档

  • 也叫 API ⽂档,⼀般由 后端开发⼯程师编写。⽤来描述 接⼝信息的 ⽂档。

接口文档的作用

  • 协同:团队⼈员⼯作协同配合
  • 约束:项⽬更新修改同步维护

解析接口文档

  • 为什么要解析
    • 通过分析接⼝⽂档,熟悉接⼝信息。
    • 通过接⼝⽂档获取,接⼝测试所使⽤的 请求数据、预期结果。
  • 解析的核⼼⽬标
      1. 请求报⽂关键数据
      • 请求⽅法、URL、请求数据(请求头、请求体)
      1. 响应报⽂关键数据
      • 响应状态码、响应数据(响应体)

练习

  • 解析⼈⼒资源管理系统接⼝⽂档,将解析结果,写⼊《接⼝⽂档解析模版.xlsx》在这里插入图片描述

------今日学习目标2--------

7、Postman:基础使用

简介和安装

  • 简介

    • postman ⼀款 ⽀持调试 和 测试的⼯具,开发、测试⼯程师都可以使⽤。
  • 安装

    • 参⻅ 课前下发的 ”Postman相关安装“ ⽬录下《Postman安装.pdf》⽂件 及 相关资料。

案例一
在这里插入图片描述

在这里插入图片描述

案例二

  • 【提交表单数据】:使⽤ Postman 向 tpshop 商城 登录接⼝ 发送 登录请求在这里插入图片描述在这里插入图片描述

案例三

  • 【提交JSON数据】:发送IHRM项⽬的登录接⼝请求并查看响应结果在这里插入图片描述

8、接口用例设计

接口测试的测试点

  • 也叫 接⼝测试维度。在这里插入图片描述

  • 功能测试

    • 单接⼝功能测试:
      • ⼀个单独的业务,就对⼀个独⽴的接⼝。如:登录业务,对应登录接⼝。
    • 业务场景功能测试:
      • 多个接⼝被连续调⽤。(模拟⽤户的实际使⽤场景)
  • 性能测试

    • 响应时⻓:从发送请求到接收到服务器回发响应包所经历的时间。
    • 错误率:服务器运⾏出错的概率
    • 吞吐量:服务器单位时间内,处理请求的数量。
    • 服务器资源利⽤率:cpu、内存、⽹络、磁盘等 硬件资源的占⽤率。
  • 安全测试

    • 攻击安全:⽊⻢、病毒…
      • 由具备专业安全技术,会使⽤专业安全测试⼯具的 安全测试⼯程师 负责。
    • 业务安全:
      • 必须登录,才能访问 ⽤户数据。
      • 敏感数据加密存储。
      • SQL注⼊

接口用例设计方法

  • 单接口测试

    • ⼀个单独的业务,就对⼀个独⽴的接⼝。如:登录业务,对应登录接⼝。注册业务,对应注册接⼝。⽀付业务,对
      应⽀付接⼝。
    • 正向:
      • 必选 参数。 所有必选项,给正确数据
      • 组合 参数。 所有必选 + 任意可选,给正确数据。
      • 全部 参数。 所有必选 + 所有可选。给正确数据。
    • 反向:
      • 功能异常:数据格式正确,不能履⾏接⼝功能。
      • 数据异常:数据格式不正确(空值、特殊字符、汉字、字⺟、⻓度、范围 ---- 等价类、边界值)
      • 参数异常:
        • 多参:多出 必选参数
        • 少参:缺少 必选参数
        • ⽆参:没有 指定参数
        • 错误参数:参数名 错误。在这里插入图片描述
  • 业务场景测试

    • ⼀定在 单接⼝ 测试 之后!
      • 尽量模拟⽤户实际使⽤场景。
      • 尽量⽤最少的⽤例,覆盖最多的接⼝请求。
      • ⼀般情况下,覆盖正向测试即可。

单接口测试用例

  • 分析测试点
    • 登录
      在这里插入图片描述

    • 添加员工在这里插入图片描述在这里插入图片描述

    • 查询员工在这里插入图片描述在这里插入图片描述

    • 伪删除说明

      • 不使⽤SQL语句 delete,真正删除指定记录。 ⽽使⽤ update 将 指定字段值修改,代表这条记录被 “删除” 了在这里插入图片描述

业务场景测试用例

  • 分析测试点

    • 指导思想:模拟⽤户实际使⽤,⽤较少的测试⽤例,覆盖更多接⼝,测试正向即可。
    • 登录 - 添加员⼯ - 查询员⼯ - 修改员⼯ - 删除员⼯ - 查询员⼯列表在这里插入图片描述

------今日学习目标3------

9、Potman断言

Postman断言简介

  • 让 Postman工具 代替 人工 自动判断 预期结果 和 实际结果 是否一致
  • 断言代码 书写在 Tests 标签页中。 查看断言结果 Test Results 标签页

Postman常用断言

  • 1.断言响应状态码

    • Status code:Code is 200在这里插入图片描述
      在这里插入图片描述
  • 2.断言包含某字符串

    • Response body: Contains string在这里插入图片描述在这里插入图片描述
  • 3.断言JS0N数据

    • Response body: JSON value Check在这里插入图片描述
      在这里插入图片描述

Postman断言工作原理

在这里插入图片描述

10、Postman关联

简介

  • 当接口和接口之间,有依赖关系时,需要借助 postman 关联技术,来实现。
  • 如:
    • 登录接口 返回的 令牌数据,被 添加员工接口依赖。
    • 添加员工接口 返回 员工id,被 查询员工接口依

实现步骤

  • 假定:接口B 产生的数据,被 接口A 依赖
      1. 发送 接口B 请求,获取响应数据。
      1. 将 响应数据,放入公共容器(全局变量、环境变量)中
      1. 接口A 从 公共容器中,提取数据,发送请求。在这里插入图片描述

核心代码

// 1. 获取 响应数据,转为 json格式,保存到变量 jsonData中。
var jsonData = pm.response.json()
// 2.1 使用 全局变量做容器。
pm.globals.set("全局变量名", 全局变量值)
// 2.2 使用 环境变量做容器。
pm.environment.set("环境变量名", 环境变量值)
// 3. 在 postman 界面中(URL、请求头headers、请求体body) 提取 全局、环境变量 数据。
{{全局变量名}}/{{环境变量名}}

创建环境

  • 全局变量:在 整个postman中都可以使用的变量。不需要 单独创建环境。
  • 环境变量:在 特定的环境下,才能使用的变量。需要给此变量创建单独的环境。
    • 在这里插入图片描述
      在这里插入图片描述

案例1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

案例2

在这里插入图片描述
在这里插入图片描述

11、Postman参数化

简介

  • 什么是参数化:
    • 测试数据,组织到 数据文件中,通过脚本的反复迭代,使用不同的数据,达到测试不同用例的目标
    • 应用场景:
      • 一般在测试同一个接口的不同 测试点时,只有测试数据不同。考虑使用 参数化

数据文件简介

  • CSV:
    • 优点:数据组织格式简单
    • 缺点:
        1. 不能测试 bool 类型。因为 postman 读取 csv后,将所有非数值类型数据,自动添加 ”“ 变为字符串
        1. 不能存储复杂数据类型(元组、列表、字典)。
        1. 不能实现 参数测试。
    • 应用场景:数据量较大,数据组织格式简单在这里插入图片描述
  • JSON:
    • 优点:
      1. 可以测试 bool类型
      2. 能使用 复杂数据类型
      3. 可以实现 参数测试。
    • 缺点:相同数据量,json文件要远大于 csv 文件。
    • 应用场景:数据量较少,数据组织格式复杂。需要进行 参数测试!在这里插入图片描述

导入数据文件到oostman

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

读取数据文件数据

  • 理论
    • 根据 使用位置 不同,有两种方法。
      • 第一种:请求参数(请求行、请求头、请求体)中,使用 数据文件中 的数据
        csv文件:{{字段名}}; json文件:{{键名}}
      • 第二种:代码(Tests)中,使用 数据文件中 的数据
        • 使用 postman 内置的 关键字 data,索引 字段名 或 键名
        • csv文件:data.字段名; json文件:data.键名
  • 案例
    在这里插入图片描述
  • 不能再使用send发送请求,点击此按钮,使用数据文件中数据,批量执行测试
    在这里插入图片描述
  • 打开postman控制台
    在这里插入图片描述

------今日学习目标4------

12、=Postman测试报告=

  • 参见 课前下发的 ”Postman相关安装“ 下的《Postman环境安装.pdf》文件中 “安装Postman插件newman” 小节。

安装node.js

# 安装
双击 .msi 文件,一路下一步安装即可。无需特殊设定。
# 测试安装成功
npm -v

安装newman

# 安装newman
npm install -g newman
# 测试安装成功
newman -v
# 安装newman插件 - 扩展版
npm install -g newman-reporter-htmlextra

导出用例集

  • 导出
    在这里插入图片描述

  • 导入
    在这里插入图片描述

导出环境文件

  • 如果,测试用例脚本中,包含 环境使用。必须要导出 环境文件!!!

在这里插入图片描述

=newman生成测试报告==

# 完整命令
newman run 用例集文件.json -e 环境文件.json -d 数据文件.json/.csv -r htmlextra --reporter-htmlextra-export 测试报告名.html
-e 和 -d 是 非必须的。
如果没有使用 环境,不需要指定 -e
如果没有使用 数据文件(做参数化),不需要指定 -

newman run 测试脚本文件 -e 环境变量文件 -g 全局变量文件 -d 测试数据文件 -r html --
reporter-html-export report.html
eg: newman run demo.postman_collection.json -r html 
newman run demo.postman_collection.json -r html --reporter-html-export report.html

  • 示例1: 指定 用例集文件 和 数据文件在这里插入图片描述
  • 示例2:指定 用例集文件 和 环境文件在这里插入图片描述
    在这里插入图片描述

13、iHRM项目实战

初始化项目环境

  • 新建用例集
    在这里插入图片描述

  • 创建用例集
    在这里插入图片描述

登录模块

  • ==登录成功接口=

    • 请求接口在这里插入图片描述

    • ==添加断言=在这里插入图片描述

  • 其他接口共性分析

      1. 由于是同一个接口,因此:请求方法、URL、请求头 完全一致。
      1. 测试点(测试用例名称)、和 请求数据(请求体),各不相同
      1. 响应结果(用作断言),共 3 种情况
        1. 操作成功
        1. 用户名或密码错误
        1. 抱歉,系统繁忙…
  • 实现其他接口在这里插入图片描述

员工管理业务场景

  • 总析

    • 共有 两 种依赖:
      1. 登录成功的 令牌, 被 添加、修改、删除、查询 接口依赖。
      2. 添加员工成功 得到的 员工id,被 修改、删除、查询 接口依赖。
  • ==提取令牌=

    • 代码写在 “登录成功”接口请求 的 Tests 标签页中

      // 1. 从 登录响应结果中,获取 json 响应体
      var jsonData = pm.reponse.json()
      // 2. 从 json响应体中,提取 data值,拼接上 “Bearer ” 前缀, 形成 完整的令牌
      var token = "Bearer " + jsonData.data
      // 3. 将 完整的令牌 保存到环境变量中。
      pm.environment.set("env_token", token)
      // ------- 以上 3步 简化为一步!
      pm.environment.set("env_token", "Bearer "+pm.reponse.json().data)
      

      在这里插入图片描述

  • ==添加员工=

    • 注意:
      1. 登录的令牌,在 请求头中使用
      2. 请求体中的手机号,要保证唯一。在这里插入图片描述
  • 提取添加员工的id

    • 代码写在 “添加员工成功” 接口请求 的 Tests 标签页中

      // 获取添加员工成功的 响应结果 json
      var jsonData = pm.response.json()
      // 提取 员工id
      var emp_id = jsonData.data.id
      // 设置到 环境变量
      pm.environment.set("env_emp_id", emp_id)
      
  • ==查询员工= 在这里插入图片描述

  • 其他员工操作

    • 修改在这里插入图片描述
    • 删除在这里插入图片描述
    • 查询在这里插入图片描述

批量运行测试用例

在这里插入图片描述在这里插入图片描述

=生成测试报告=

  • 登录接口生成测试报告:
    1. 导出用例集文件。(没有使用环境,不需要导出环境文件)
    2. 使用命令 生成测试报告
    newman run ihrm项目.postman_collection.json -r htmlextra --reporter-htmlextra-export ihrm登录接口
    测试报告.html
    
    在这里插入图片描述
  • 带有业务场景接口,生成测试报告:
    1. 导出用例集文件。
      newman run ihrm项目.postman_collection.json -r htmlextra --reporter-htmlextra-export ihrm登录接口
      测试报告.html
    2. 必须 要导出 环境文件。
    3. 使用命令 生成测试报告
    带有业务场景接口,生成测试报告:
    1. 导出用例集文件。
    newman run ihrm项目.postman_collection.json -r htmlextra --reporter-htmlextra-export ihrm登录接口
    测试报告.html
    2. 必须 要导出 环境文件。
    3. 使用命令 生成测试报告
    
    在这里插入图片描述
  • 注意:由于添加员工时,手机号要求唯一! 因此上述生成报告的命令, 第二次+ 执行,生成的报告中,会有断
    言失败。

------今日学习目标5------

14、Requests库

1、Requests库安装和简介

  • 简介:
    • Requests库 是 Python编写的,基于urllib 的 HTTP库,使用方便。
  • 安装:`
    • `方法1:

      pip install requests
      
    • 方法2:

      pip install requests -i https://pypi.douban.com/simple/
      豆瓣镜像:https://pypi.douban.com/simple/
      

在这里插入图片描述

  • 查验:
    • 步骤1:pip 中查验

      # 方法1
      pip list
      # 方法2
      pip show 库名
      
    • 步骤2:pycharm 中查验在这里插入图片描述在这里插入图片描述

2、=设置http请求语法==

在这里插入图片描述
在这里插入图片描述

3、=应用案例==

  • 案例1在这里插入图片描述

  • 案例2
    在这里插入图片描述

  • 案例3在这里插入图片描述

  • 案例4在这里插入图片描述

4、Cookie

Cookiej简介

  • 简介:工程师 针对 http协议是无连接、无状态特性,设计的 一种技术。 可以在浏览器端 存储用户的信息
  • 特性:
    • cookie 用于存储 用户临时的不敏感信息。
    • cookie 位于浏览器(客户端)端。默认大小 4k(可以调整)
    • cookie 中的数据,可以随意被访问,没有安全性可言。
    • cookie 中存储的数据类型, 受浏览器限制。

Cookie+Sessioni认证方

  • 在计算机中,认证用户身份的方式有多种!课程中接触 2种:
    • ihrm项目:token认证。
    • tpshop项目:cookie+Session认证。
      在这里插入图片描述

5、Session

Session简介

  • 简介:也叫 会话。通常出现在网络通信中,从客户端借助访问终端登录上服务器,直到 退出登录 所产生的通信数据,保存在 会话中。服务端缓存的数据。
  • 特性
    • Session 用于存储 用户的信息。
    • Session 位于服务端。大小直接使用服务器存储空间
    • Session 中的数据,不能随意被访问,安全性较高。
    • Session 中存储的数据类型,受服务器影响,几乎能支持所有的数据类型。

Session自动管理Cookie

  • 因为 Cookie 中的 数据,都是 Session 传递的。因此,Session 可以直接 自动管理 cookie

面试题Cookie和Session区别:

  1. 数据存储位置:
    cookie存储在浏览器;session存储在服务器。
  2. 安全性:
    cookie中的数据可以随意获取,没有安全性可言。Session的数据多为加密存储,安全较高!
  3. 数据类型:
    cookie支持的数据类型受浏览器限制,较少;Session直接使用服务器存储,支持所有数据类型
  4. 大小:
    cookie大小默认 4k; Session 大小约为服务器存储空间大小

6、 获取指定响应数据

常用

  • 获取 URL:resp.url
  • 获取 响应状态码:resp.status_code
  • 获取 Cookie:resp.cookies
  • 获取 响应头:resp.headers
  • 获取 响应体:
    • 文本格式:resp.text
    • json格式:resp.json()

15、UnitTest框架

  • UnitTest 是开发人员用来实现 “单元测试” 的框架。测试工程师,可以在自动化 “测试执行” 时使用。
  • 使用 UnitTest 的好处:
      1. 方便管理、维护测试用例。
      1. 提供丰富的断言方法。
      1. 生成测试报告。(需要插件 HTMLTestReport)

1、UnitTest框架回顾

TestCase
在这里插入图片描述

Fixture
在这里插入图片描述

TestSuite
在这里插入图片描述

TestRunner
在这里插入图片描述
示例:测试类在这里插入图片描述
示例:生成测试报告在这里插入图片描述

2、ihrm案例

  • 登录成功在这里插入图片描述
  • 断言方法:在这里插入图片描述

------今日学习目标6------

16、数据库操作应用场景

  • 校验 测试数据
    • 接口发送请求后明确会对数据库中的某个字段进行修改,但,响应结果中无该字段数据时。
      • 如:ihrm 删除员工接口。 is_delete 字段,没有 在响应结果中出现! 需要 借助数据库 校验!
  • 构造 测试数据
    • 测试数据使用一次就失效。
      • 如:ihrm 添加员工接口,使用的手机号!
    • 测试前,无法保证测试数据是否存在。
      • 如:ihrm 查询员工接口,使用的 员工id

17、PyMySQL操作数据库

1、安装PyMySQL

  • 方法1:
pip install PyMySQL
  • 方法2:
pip install PyMySQL -i https://pypi.douban.com/simple/

2、操作步骤

在这里插入图片描述在这里插入图片描述

3、==事务的概念

  • 事务,是关系型数据库(mysql)特有的概念。
  • 事务,可以看做一个虚拟的 容器,在容器中存放一系列的数据库操作,看做一个整体。内部的所有操作,要
    么都一次性全部成功,只要有一个失败,就全部失败
  • 事务操作:只有 2 种情况
    • 提交:conn.commit()
    • 回滚: conn.rollback()

4、PyMySQL连接数据库

==建立连接方法=
在这里插入图片描述

入门案例

  • 查询数据库,获取MySQL服务器 版本信息
# 1. 导包
import pymysql
# 2. 建立连接
conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
PyMySQL操作数据库
==SQL 语法回顾==
查询语法:
添加语法:
更新语法:
删除语法:
password="iHRM_student_2021", database="test_db", charset="utf8")
# 3. 获取游标
cursor = conn.cursor()
# 4. 执行 sql 语句(查询)
cursor.execute("select version()")
# 5. 获取结果
res = cursor.fetchone()
print("res =", res[0])
# 6. 关闭游标
cursor.close()
# 7. 关闭连接
conn.close()

5、PyMySQL操作数据库

SQL语法回顾
在这里插入图片描述

=数据库查询==

  • 查询操作流程
    在这里插入图片描述
  • cursor游标
    在这里插入图片描述
  • 常用方法
    在这里插入图片描述
  • 案例
    • 查询t_book表,获取 第一条 数据
    • 查询t_book表,获取 前两条 数据
    • 查询t_book表,获取 全部 数据
    • 查询t_book表,获取 第3条和第4条 数据
# 1. 导包
import pymysql
# 2. 建立连接
conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
password="iHRM_student_2021", database="test_db", charset="utf8")
# 3. 获取游标
cursor = conn.cursor() # 指向 0 号位置。
# 4. 执行 sql 语句(查询)--- t_book
cursor.execute("select * from t_book;")
# 5. 获取结果 - 提取第一条
res1 = cursor.fetchone()
print("res1 =", res1)
# 修改游标位置:回零
cursor.rownumber = 0
# 5. 获取结果 - 提取前 2 条
res2 = cursor.fetchmany(2)
print("res2 =", res2)
# 修改游标位置:回零
cursor.rownumber = 0
res3 = cursor.fetchall()
print("res3 =", res3)
# 修改游标位置:指向第 2 条记录
cursor.rownumber = 2
res4 = cursor.fetchmany(2)
print("res4 =", res4)
# 6. 关闭游标
cursor.close()
# 7. 关闭连接
conn.close()
  • 异常捕获
    在这里插入图片描述
    在这里插入图片描述
 1. 导包
import pymysql
==数据库UID==
更新操作流程
# 定义全局变量,初值为 None
conn = None
cursor = None
try:
# 2. 建立连接
conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
password="iHRM_student_2021", database="test_db", charset="utf8")
# 3. 获取游标
cursor = conn.cursor() # 指向 0 号位置。
# 4. 执行 sql 语句(查询)--- t_book
cursor.execute("select * from t_book;")
# 5. 获取结果 - 提取第一条
res1 = cursor.fetchone()
print("res1 =", res1)
# 修改游标位置:回零
cursor.rownumber = 0
# 5. 获取结果 - 提取前 2 条
res2 = cursor.fetchmany(2)
print("res2 =", res2)
# 修改游标位置:回零
cursor.rownumber = 0
res3 = cursor.fetchall()
print("res3 =", res3)
# 修改游标位置:指向第 2 条记录
cursor.rownumber = 2
res4 = cursor.fetchmany(2)
print("res4 =", res4)
except Exception as err:
print("查询语句执行出错:", str(err))
finally:
# 6. 关闭游标
cursor.close()
# 7. 关闭连接
conn.close()

数据库UD

  • 更新操作流程
    在这里插入图片描述
  • 案例
    • 单独实现如下操作: ①:新增一条图书数据(id:5 title:西游记 pub_date:1986-01-01 ) ②:把图书名称
      为‘西游记’的阅读量加一 ③:删除名称为‘西游记’的图书

      • 插入数据
      """
      新增一条图书数据(id:5 title:西游记 pub_date:1986-01-01 )
      insert into t_book(id, title, pub_date) values(5, '西游记', '1986-01-01');
      1. 导包
      2. 创建连接
      3. 获取游标
      4. 执行 insert 语句
      5. 提交/回滚事务
      6. 关闭游标
      7. 关闭连接
      """
      # 1. 导包
      import pymysql
      # 定义全局变量
      conn = None
      cursor = None
      try:
      # 2. 创建连接
      conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
      password="iHRM_student_2021",
      database="test_db", charset="utf8")
      # 3. 获取游标
      cursor = conn.cursor()
      # 4. 执行 insert 语句
      修改数据:
      cursor.execute("insert into t_book(id, title, pub_date) values(175, '西游记', '1986-01-
      01');")
      # 查看 sql执行,影响多少行
      print("影响的行数:", conn.affected_rows())
      # 5. 提交事务
      conn.commit()
      except Exception as err:
      print("插入数据错误:", str(err))
      # 回滚事务
      conn.rollback()
      finally:
      # 6. 关闭游标
      cursor.close()
      # 7. 关闭连接
      conn.close()
      
      • 修改数据
      """
      把图书名称为‘西游记’的阅读量加一
      update t_book set `read` = `read` + 1 where id = 6;
      1. 导包
      2. 建立连接
      3. 获取游标
      4. 执行 update语句
      5. 提交、回滚事务
      6. 关闭游标
      7. 关闭连接
      """
      # 1. 导包
      import pymysql
      conn = None
      cursor = None
      try:
      # 2. 建立连接
      conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
      password="iHRM_student_2021",
      database="test_db", charset="utf8")
      # 3. 获取游标
      cursor = conn.cursor()
      # 4. 执行 update语句。字段名,需要使用 反引号(`)包裹
      cursor.execute("update t_book set `read` = `read` + 1 where id = 1023;")
      删除数据:
      print("影响的行数:", conn.affected_rows())
      # 5. 提交、回滚事务
      conn.commit()
      except Exception as err:
      print("更新失败:", str(err))
      # 回滚事务
      conn.rollback()
      finally:
      # 6. 关闭游标
      cursor.close()
      # 7. 关闭连接
      conn.close()
      
      • 删除数据
      """
      删除名称为‘西游记’的图书
      delete from t_book where title = '西游记';
      1. 导包
      2. 建立连接
      3. 获取游标
      4. 执行 delete 语句
      5. 提交、回滚事务
      6. 关闭游标
      7. 关闭连接
      """
      # 1. 导包
      import pymysql
      conn = None
      cursor = None
      try:
      # 2. 建立连接
      conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
      password="iHRM_student_2021",
      database="test_db", charset="utf8")
      # 3. 获取游标
      cursor = conn.cursor()
      # 4. 执行 delete语句。
      cursor.execute("delete from t_book where id = 151;")
      print("影响的行数:", conn.affected_rows())
      # 5. 提交、回滚事务
      conn.commit()
      数据库工具类封装
      封装的目的
      将 常用的数据库操作,封装到 一个方法。 后续再操作数据库时,通过调用该方法来实现。
      提高代码的 复用性!
      ==设计数据库工具类==
      ==实现类方法==
      获取、关闭连接
      except Exception as err:
      print("更新失败:", str(err))
      # 回滚事务
      conn.rollback()
      finally:
      # 6. 关闭游标
      cursor.close()
      # 7. 关闭连接
      conn.close()
      

18、数据库工具类封装

1、封装的目的

  • 将 常用的数据库操作,封装到 一个方法。 后续再操作数据库时,通过调用该方法来实现。
  • 提高代码的 复用性!

2、设计数据库工具类

 # 封装数据库工具类
class DBUtil(object):
@classmethod
def __get_conn(cls):
pass
@classmethod
def __close_conn(cls):
pass
# 常用方法:查询一条
@classmethod
def select_one(cls, sql):
pass
# 常用方法:增删改
@classmethod
def uid_db(cls, sql):
pass

3、=实现类方法==

  • 获取、关闭连接

    # 封装数据库工具类
    class DBUtil(object):
    # 添加类属性
    conn = None
    @classmethod
    def __get_conn(cls):
    # 判断 conn 是否为空, 如果是,再创建
    if cls.conn is None:
    cls.conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
    password="iHRM_student_2021", database="test_db",
    charset="utf8")
    # 返回 非空连接
    return cls.conn
    @classmethod
    def __close_conn(cls):
    # 判断,conn 不为空,需要关闭。
    if cls.conn is not None:
    cls.conn.close()
    cls.conn = None
    
  • 查询一条记录

    # 封装数据库工具类
    class DBUtil(object):
    # 常用方法:查询一条
    @classmethod
    def select_one(cls, sql):
    cursor = None
    res = None
    try:
    # 获取连接
    cls.conn = cls.__get_conn()
    # 获取游标
    cursor = cls.conn.cursor()
    # 执行 查询语句
    cursor.execute(sql)
    # 提取一条结果
    res = cursor.fetchone()
    except Exception as err:
    print("查询sql错误:", str(err))
    finally:
    # 关闭游标
    cursor.close()
    增删改数据
    完整封装代码实现
    # 关闭连接
    cls.__close_conn()
    # 将查询sql执行的 结果,返回
    return res
    if __name__ == '__main__':
    res = DBUtil.select_one("select * from t_book;")
    print("查询结果为:", res)
    
  • 增删改数据

    # 封装数据库工具类
    class DBUtil(object):
    # 常用方法:增删改
    @classmethod
    def uid_db(cls, sql):
    cursor = None
    try:
    # 获取连接
    cls.conn = cls.__get_conn()
    # 获取游标
    cursor = cls.conn.cursor()
    # 执行 uid 语句
    cursor.execute(sql)
    print("影响的行数:", cls.conn.affected_rows())
    # 提交事务
    cls.conn.commit()
    except Exception as err:
    # 回滚事务
    cls.conn.rollback()
    print("增删改 SQL 执行失败:", str(err))
    finally:
    # 关闭游标
    cursor.close()
    # 关闭连接
    cls.__close_conn()
    if __name__ == '__main__':
    DBUtil.uid_db("update t_book set is_delete = 1 where id = 1111;")
    
    
  • 完整封装代码实现

    import pymysql
    # 封装数据库工具类
    class DBUtil(object):
    # 添加类属性
    conn = None
    @classmethod
    def __get_conn(cls):
    # 判断 conn 是否为空,如果是,再创建
    if cls.conn is None:
    cls.conn = pymysql.connect(host="211.103.136.244", port=7061, user="student",
    password="iHRM_student_2021", database="test_db",
    charset="utf8")
    # 返回 非空连接
    return cls.conn
    @classmethod
    def __close_conn(cls):
    # 判断,conn 不为空,需要关闭。
    if cls.conn is not None:
    cls.conn.close()
    cls.conn = None
    # 常用方法:查询一条
    @classmethod
    def select_one(cls, sql):
    cursor = None
    res = None
    try:
    # 获取连接
    cls.conn = cls.__get_conn()
    # 获取游标
    cursor = cls.conn.cursor()
    # 执行 查询语句
    cursor.execute(sql)
    # 提取一条结果
    res = cursor.fetchone()
    except Exception as err:
    print("查询sql错误:", str(err))
    finally:
    # 关闭游标
    cursor.close()
    # 关闭连接
    cls.__close_conn()
    # 将查询sql执行的 结果,返回
    作业
    1. 完成每日反馈!
    2. 完成《接口测试-06-作业.md》中习题。
    return res
    # 常用方法:增删改
    @classmethod
    def uid_db(cls, sql):
    cursor = None
    try:
    # 获取连接
    cls.conn = cls.__get_conn()
    # 获取游标
    cursor = cls.conn.cursor()
    # 执行 uid 语句
    cursor.execute(sql)
    print("影响的行数:", cls.conn.affected_rows())
    # 提交事务
    cls.conn.commit()
    except Exception as err:
    # 回滚事务
    cls.conn.rollback()
    print("增删改 SQL 执行失败:", str(err))
    finally:
    # 关闭游标
    cursor.close()
    # 关闭连接
    cls.__close_conn()
    if __name__ == '__main__':
    res = DBUtil.select_one("select * from t_book;")
    print("查询结果为:", res)
    DBUtil.uid_db("update t_book set is_delete = 1 where id = 1111;")
    

------今日学习目标7------

19、接口对象封装

1、解决的问题

  • 代码冗余度⾼(有⼤量重复代码)
  • 代码耦合度⾼
  • 代码维护成本⾼

2、核心思想:代码分层

在这里插入图片描述

  • 分层思想:
    • 将 普通⽅法实现的 ,分为 接⼝对象层 和 测试脚本层。
  • 接⼝对象层:
    • 对 接⼝ 进⾏封装。封装好之后,给 测试⽤例层 调⽤!
    • ⾯向对象 类 封装 实现。
  • 测试⽤例层:
    • 调⽤ 接⼝对象层 封装的⽅法,拿到 响应结果,断⾔进⾏接⼝测试!
    • 借助 unittest 框架实现

20、封装Tpshop商城

1、普通方式实现

import unittest
import requests

class TestTpshopLogin(unittest.TestCase):
 # 测试 登录成功
 def test01_login_ok(self):
 # 创建 session 实例
 session = requests.Session()
 # 使⽤实例,调⽤get 发送获取验证码请求
 session.get(url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=verify&r=0.21519623710645064")
 # 使⽤实例,调⽤post 发送登录请求
 resp = session.post(
 url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=do_login&t=0.7094195931397276",
 data={"username": "13012345678", "password": "123456", "verify_code":
"8888"})
 print("响应结果 =", resp.json())
 # 断⾔:
 self.assertEqual(200, resp.status_code)
 self.assertEqual(1, resp.json().get("status"))
 self.assertEqual("登陆成功", resp.json().get("msg"))
 # 测试 ⼿机号不存在
 def test02_tel_not_exists(self):
 # 创建 session 实例
 session = requests.Session()
 # 使⽤实例,调⽤get 发送获取验证码请求
 session.get(url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=verify&r=0.21519623710645064")
 # 使⽤实例,调⽤post 发送登录请求
 resp = session.post(
 url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=do_login&t=0.7094195931397276",
 data={"username": "13847834701", "password": "123456", "verify_code":
"8888"})
 print("响应结果 =", resp.json())
 # 断⾔:
 self.assertEqual(200, resp.status_code)
 self.assertEqual(-1, resp.json().get("status"))
 self.assertEqual("账号不存在!", resp.json().get("msg"))
 # 测试 密码错误
 def test03_pwd_err(self):
 # 创建 session 实例
 session = requests.Session()
 # 使⽤实例,调⽤get 发送获取验证码请求
 session.get(url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=verify&r=0.21519623710645064")
 # 使⽤实例,调⽤post 发送登录请求
 resp = session.post(
 url="http://tpshop-test.itheima.net/index.php?
m=Home&c=User&a=do_login&t=0.7094195931397276",
 data={"username": "13012345678", "password": "123456890",
"verify_code": "8888"})
 print("响应结果 =", resp.json())
 # 断⾔:
 self.assertEqual(200, resp.status_code)
 self.assertEqual(-2, resp.json().get("status"))
 self.assertEqual("密码错误!", resp.json().get("msg"))

2、登录接口对象层

  • 封装思想:

    • 将 动态变化的数据,设计到⽅法的参数。
    • 将 固定不变的,直接写成⽅法实现。
    • 将 响应结果,通过返回值传出。
  • 分析在这里插入图片描述

  • 封装实现

    class TpshopLoginApi(object):
     # 发送验证码请求
     @classmethod
     def get_verify(cls, session):
     session.get(url="http://tpshop-test.itheima.net/index.php?
    m=Home&c=User&a=verify&r=0.21519623710645064")
    
     # 发送登录请求
     @classmethod
     def login(cls, session, login_data):
     resp = session.post(
     url="http://tpshop-test.itheima.net/index.php?
    m=Home&c=User&a=do_login&t=0.7094195931397276",
     data=login_data)
     return resp
    

3、登录接口测试用例层

  • 优化前:

    
    import unittest
    import requests
    from tpshop_login_api import TpshopLoginApi
    class TestTpshopLogin(unittest.TestCase):
     # 测试 登录成功
     def test01_login_ok(self):
     # 创建 session实例
     s = requests.Session()
     # ⽤实例,调⽤⾃⼰封装的 获取验证码 接⼝
     TpshopLoginApi.get_verify(s)
     # 调⽤ ⾃⼰封装的接⼝,登录
     abc = {"username": "13012345678", "password": "123456", "verify_code":
    "8888"}
     resp = TpshopLoginApi.login(s, abc)
     print(resp.json())
     self.assertEqual(200, resp.status_code)
     self.assertEqual(1, resp.json().get("status"))
     self.assertEqual("登陆成功", resp.json().get("msg"))
     # 测试 ⼿机号不存在
     def test02_tel_not_exists(self):
     # 创建 session实例
     s = requests.Session()
     # ⽤实例,调⽤⾃⼰封装的 获取验证码 接⼝
     TpshopLoginApi.get_verify(s)
     # 调⽤ ⾃⼰封装的接⼝,登录
     abc = {"username": "13048932745", "password": "123456", "verify_code":
    "8888"}
     resp = TpshopLoginApi.login(s, abc)
     print(resp.json())
     # 断⾔
     self.assertEqual(200, resp.status_code)
     self.assertEqual(-1, resp.json().get("status"))
     self.assertIn("账号不存在", resp.json().get("msg"))
     # 测试 密码错误
     def test03_pwd_err(self):
     # 创建 session实例
     s = requests.Session()
     # ⽤实例,调⽤⾃⼰封装的 获取验证码 接⼝
     TpshopLoginApi.get_verify(s)
     # 调⽤ ⾃⼰封装的接⼝,登录
     abc = {"username": "13012345678", "password": "123456789", "verify_code":
    "8888"}
     resp = TpshopLoginApi.login(s, abc)
     print(resp.json())
     # 断⾔
     self.assertEqual(200, resp.status_code)
     self.assertEqual(-2, resp.json().get("status"))
     self.assertIn("密码错误", resp.json().get("msg"))
    
  • 优化后

    import unittest
    import requests
    from tpshop_login_api import TpshopLoginApi
    # 封装 通⽤ 的 断⾔函数
    def common_assert(self, resp, status_code, status, msg):
     self.assertEqual(status_code, resp.status_code)
    
     self.assertEqual(status, resp.json().get("status"))
     self.assertIn(msg, resp.json().get("msg"))
    class TestTpshopLogin(unittest.TestCase):
     # 添加类属性
     session = None
     @classmethod
     def setUpClass(cls) -> None: # 在 类中 所 有 测试⽅法执⾏之前,⾃动执⾏1次。
     cls.session = requests.Session()
     def setUp(self) -> None: # 在 每个 测试⽅法执⾏之前,⾃动执⾏1次。
     # 调⽤ ⾃⼰封装的接⼝,获取验证码
     TpshopLoginApi.get_verify(self.session)
     # 测试 登录成功
     def test01_login_ok(self):
     # 调⽤ ⾃⼰封装的接⼝,登录
     data = {"username": "13012345678", "password": "123456", "verify_code":
    "8888"}
     resp = TpshopLoginApi.login(self.session, data)
     # 断⾔
     common_assert(self, resp, 200, 1, "登陆成功")
     # 测试 ⼿机号不存在
     def test02_tel_not_exists(self):
     # 调⽤ ⾃⼰封装的接⼝,登录
     data = {"username": "13048392845", "password": "123456", "verify_code":
    "8888"}
     resp = TpshopLoginApi.login(self.session, data)
     # 断⾔
     common_assert(self, resp, 200, -1, "账号不存在")
     # 测试 密码错误
     def test03_pwd_err(self):
     # 调⽤ ⾃⼰封装的接⼝,登录
     data = {"username": "13012345678", "password": "123456890", "verify_code":
    "8888"}
     resp = TpshopLoginApi.login(self.session, data)
     # 断⾔
     common_assert(self, resp, 200, -2, "密码错误")
    
1、封装断言方法

在这里插入图片描述

# 封装 通⽤ 的 断⾔函数
def common_assert(self, resp, status_code, status, msg):
 self.assertEqual(status_code, resp.status_code)
 self.assertEqual(status, resp.json().get("status"))
 self.assertIn(msg, resp.json().get("msg"))
# 调⽤
common_assert(self, resp, 200, 1, "登陆成功")
common_assert(self, resp, 200, -1, "账号不存在")
common_assert(self, resp, 200, -2, "密码错误")

21、封装iHRM登录

1、登录接口

1、普通方式实现
import unittest
import requests
class TestIhrmLogin(unittest.TestCase):
 # 登陆成功
 def test01_login_success(self):
 resp = requests.post(url="http://ihrm-test.itheima.net/api/sys/login",
 json={"mobile": "13800000002", "password": "123456"})
 print(resp.json())
 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(True, resp.json().get("success"))
 self.assertEqual(10000, resp.json().get("code"))
 self.assertIn("操作成功", resp.json().get("message")
2、登录接口对象层
  • 思路:

    • 动态变化的,写⼊参数
    • 固定不变,直接写到⽅法实现内
    • 响应结果,通过返回值 return
  • 分析:在这里插入图片描述

  • 封装实现:

    # 接⼝对象层
    import requests
    class IhrmLoginApi(object):
     @classmethod
     def login(cls, json_data):
     resp = requests.post(url="http://ihrm-test.itheima.net/api/sys/login",
     json=json_data)
     return resp
    
3、登录接口测试用例层
import unittest
from ihrm_login_api import IhrmLoginApi
# 定义测试类
class TestIhrmLogin(unittest.TestCase):
 # 测试⽅法 - 登录成功
 def test01_login_success(self):
 # 调⽤ ⾃⼰封装 login
 login_data = {"mobile": "13800000002", "password": "123456"}
 resp = IhrmLoginApi.login(login_data)
 print("登录成功:", resp.json())
 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(True, resp.json().get("success"))

 self.assertEqual(10000, resp.json().get("code"))
 self.assertIn("操作成功", resp.json().get("message"))
 # 测试⽅法 - ⼿机号未注册
 def test02_mobile_not_register(self):
 # 调⽤ ⾃⼰封装 login
 login_data = {"mobile": "1384780932", "password": "123456"}
 resp = IhrmLoginApi.login(login_data)
 print("⼿机号未注册:", resp.json())
 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(False, resp.json().get("success"))
 self.assertEqual(20001, resp.json().get("code"))
 self.assertIn("⽤户名或密码错误", resp.json().get("message"))
 # 测试⽅法 - 密码错误
 def test03_pwd_error(self):
 # 调⽤ ⾃⼰封装 login
 login_data = {"mobile": "13800000002", "password": "890"}
 resp = IhrmLoginApi.login(login_data)
 print("密码错误:", resp.json())
 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(False, resp.json().get("success"))
 self.assertEqual(20001, resp.json().get("code"))
 self.assertIn("⽤户名或密码错误", resp.json().get("message"))
 # 测试⽅法 - ⼿机号为空
 def test04_mobile_is_none(self):
 # 调⽤ ⾃⼰封装 login
 login_data = {"mobile": None, "password": "123456"}
 resp = IhrmLoginApi.login(login_data)
 print("⼿机号为空:", resp.json())
 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(False, resp.json().get("success"))
 self.assertEqual(20001, resp.json().get("code"))
 self.assertIn("⽤户名或密码错误", resp.json().get("message"))
 # 测试⽅法 - 多参
 def test12_more_params(self):
 # 调⽤ ⾃⼰封装 login
 login_data = {"mobile": "13800000002", "password": "123456", "abc":"123"}
 resp = IhrmLoginApi.login(login_data)
 print("⼿机号为空:", resp.json())

 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(True, resp.json().get("success"))
 self.assertEqual(10000, resp.json().get("code"))
 self.assertIn("操作成功", resp.json().get("message"))
 # 测试⽅法 - ⽆参
 def test14_none_params(self):
 # 调⽤ ⾃⼰封装 login
 login_data = None
 resp = IhrmLoginApi.login(login_data)
 print("⼿机号为空:", resp.json())
 # 断⾔
 self.assertEqual(200, resp.status_code)
 self.assertEqual(False, resp.json().get("success"))
 self.assertEqual(99999, resp.json().get("code"))
 self.assertIn("抱歉,系统繁忙,请稍后重试", resp.json().get("message"))
4、封装断言方法
  1. 创建 ⽂件 assert_util.py

  2. 在 ⽂件内,定义 common_assert() 函数

  3. 直接粘贴 unittest框架中的断⾔代码,修改参数。

  4. 回到 unittest框架 实现的 测试脚本中, 调⽤该函数,实现断⾔,传递 实际参数。

    # 定义 断⾔ 函数
    # def common_assert():
    # self.assertEqual(200, resp.status_code) # self / resp 报错
    # self.assertEqual(True, resp.json().get("success"))
    # self.assertEqual(10000, resp.json().get("code"))
    # self.assertIn("操作成功", resp.json().get("message"))
    def common_assert(self, resp, status_code, success, code, message):
     self.assertEqual(status_code, resp.status_code)
     self.assertEqual(success, resp.json().get("success"))
     self.assertEqual(code, resp.json().get("code"))
     self.assertIn(message, resp.json().get("message"))
     
    # 调⽤演示
     common_assert(self, resp, 200, True, 10000, "操作成功")
     common_assert(self, resp, 200, False, 20001, "⽤户名或密码错误")
     common_assert(self, resp, 200, False, 99999, "抱歉,系统繁忙,请稍后重试")
    

导包注意事项:在这里插入图片描述

22、Tpshopi商城参数化

1、准备工作

  • 分析 tpshop 商城测试⽤例:在这里插入图片描述
  • 提取每个测试⽤例 使⽤的 测试数据 和 断⾔数据。在这里插入图片描述
  • 封装函数,将 数据 转换为 元组列表。在这里插入图片描述

2、参数化步骤

  1. 导包 from parameterized import parameterized
  2. 在 通⽤测试⽅法,上⼀⾏,添加 @parameterized.expand()
  3. 给 expand() 传⼊ [(),(),()](调⽤ 转换 [{},{},{}] --> [(),(),()] 的函数)
  4. 修改 通⽤测试⽅法,添加形参,个数、顺序,与 [{},{},{}] 中 { } 内的所有 key 完全⼀⼀对应。
  5. 在 通⽤测试⽅法内,使⽤形参。

3、代码实现

  • 实现
    from parameterized import parameterized
    class TestTpshopLogin(unittest.TestCase):
     # 添加类属性
     session = None
     @classmethod
     def setUpClass(cls) -> None:
     cls.session = requests.Session()
     def setUp(self) -> None:
     # 调⽤ ⾃⼰封装的接⼝,获取验证码
     TpshopLoginApi.get_verify(self.session)
     # 测试 tpshop 登录
     @parameterized.expand(read_json_data())
     def test_tpshop_login(self, req_body, status_code, status, msg):
     resp = TpshopLoginApi.login(self.session, req_body)
     common_assert(self, resp, status_code, status, msg)
    

------今日学习目标8------

23、接口自动化测试框架

1、目录结构

  • 结构
    7 部分(5个目录、2个文件):
    api/: 存储接口对象层(自己封装的 接口)
    scripts/: 存储测试脚本层 (unittest框架实现的 测试类、测试方法)
    data/: 存储 .json 数据文件
    report/: 存储 生成的 html 测试报告
    common/: 存储 通用的 工具方法
    config.py: 存储项目的配置信息(全局变量)
    run_suite.py: 组装测试用例、生成测试报告的 代码
    
    在这里插入图片描述
    在这里插入图片描述

2、封装iHRM登录

3、=登录接口==

1、普通方式实现
  • 实现方式
    import unittest
    import requests
    class TestIhrmLogin(unittest.TestCase):
    # 测试方法1,登录成功
    def test01_login_success(self):
    # 组织url
    url = "http://ihrm-test.itheima.net/api/sys/login"
    header = {"Content-Type": "application/json"}
    json_data = {"mobile": "13800000002", "password": "123456"}
    resp = requests.post(url=url, headers=header, json=json_data)
    print("登录成功:", resp.json())
    # 断言
    self.assertEqual(200, resp.status_code)
    self.assertEqual(True, resp.json().get("success"))
    self.assertEqual(10000, resp.json().get("code"))
    self.assertIn("操作成功", resp.json().get("message"))
    # 测试方法2,密码错误
    def test02_pwd_err(self):
    # 组织url
    url = "http://ihrm-test.itheima.net/api/sys/login"
    header = {"Content-Type": "application/json"}
    json_data = {"mobile": "13800000002", "password": "123456789"}
    resp = requests.post(url=url, headers=header, json=json_data)
    print("密码错误:", resp.json())
    # 断言
    self.assertEqual(200, resp.status_code)
    self.assertEqual(False, resp.json().get("success"))
    self.assertEqual(20001, resp.json().get("code"))
    self.assertIn("用户名或密码错误", resp.json().get("message"))
    
    
2、登录接口对象层
  • 步骤

    1. 在 api/ 下,创建 ihrm_login_api.py 文件。
    2. 在 文件内,封装 IhrmLoginApi 类,添加 login 类方法。
    3. 安照 普通方式实现,分析。实现 login 类方法。
    
  • 分析:
    在这里插入图片描述
    在这里插入图片描述

3、登录接口测试用例层
  • 步骤

    1. 在 scripts/ 下,创建 test_ihrm_login.py 文件
    2. 在 文件内,创建 测试类 TestIhrmLoginunittest.TestCase 继承
    3. 添加 测试方法, 并实现
    

    在这里插入图片描述在这里插入图片描述

4、封装断言方法
  • 步骤

    1. 在 common/ 下,新建文件 assert_util.py 文件,
    2. 在文件内,添加 函数 assert_util()
    3. 在 函数内,实现通用的断言函数。
    4. 在 测试方法中,使用 直接封装的 通用断言函数, 实现断言
    

    在这里插入图片描述

  • 使用断言方法
    在这里插入图片描述

24、=参数化==

1、回顾UnitTest参数化

1、原始案例
2、参数化实现
3、从json文件读取

2、登录接口参数化

1、组织数据文件
2、读取数据文件
3、==使用parameterized实
4、现参数化==

25、员工管理接口

普通方法实现
=接口对象层==
=接口测试用例层==
数据库工具类封装
解决反复修改手机号
添加员工接口参数化

------今日学习目标9------

获取请求头
提取项目目录
==生成测试报告=

26、日志收集

==日志简介=
日志的级别
日志代码实现分析
代码分析
日志使用
可修改的位置
使用步骤:

27、=全量字段校验==

简介和安装
JSON Schema入门
入门案例
校验方式
JSON Schema语法
type关键字
properties关键字
required关键字
const关键字
pattern关键字
综合案例应用

------今日学习目标10------

28、ihrm剩余

使用全量字段校验
日志的使用
构造员工id

29、持续集成

30、git

简介和安装

31、Gitee

注册网易邮箱
注册Gitee账号
git和gitee管理代码
工作原理

PyCharm配置Gitee插件
PyCharm与Gitee相关操

32、Jenkins

简介、安装、启动
插件安装介绍
=系统设置==
持续集成-Postman
持续集成代码

------今日学习目标11------

33、传智健康项目介绍

项目描述
目标用户群体
项目模块
系统框架

34、Dubbo接口测试

RPC
Dubbo
查阅API文档

35、Telnet工具远程调用

启用telnet
telnet远程连接服务
telnet调用服务接口

36、=python借助dubbo远程调用

安装dubboclient
实现步骤
会员服务(入门)
其他模块
分析bug来源
现有问题
封装目标

------今日学习目标12------

现有问题
封装目标

37、Dubbo接口自动化测试框架

==核心模块=三
基础服务对象封装
==服务对象封装=
会员服务封装
预约设置服务封装
用户服务封装
测试用例对象封装
参数化
接口自动化框架封装
测试报告

1、接口测试

今日目标:能够根据需求文档和接口文档设计出接口测试用例
  • 能够根据需求文档和接口文档设计出接口测试用例
    今日目标
    目标:
  • 能够完成接口API文档的解析
    重点:
  • HTTP协议(URL、HTTP请求、HTTP响应)
  • 接口API文档解析
1、接口测试理论
  • 接口

    • 分类:
      • 硬件接口T
      • 软件接口(软件测试讨论的主体)
    • 慨念:
  • 接口类型:

    • 系统之间的接口(tpshop与支付宝系统的接口)
    • 系统内部的接口(登录与订单之间的交互)
    • 注意:对于测试而言,
      不需要区分系统之间的接口与系统内部的接口
  • 接口测试:

    • 是对系统或组件之间的接口进行测试,主要是校验数据的交换、传递和控制管理过程,以及接口之间的依赖关系。
  • 测试原理

    • 模拟客户端建立连接
    • 发送请求
    • 服务器处理请求并响应
    • 校验响应数据
  • 接口测试的特点

    • 测试可以提前介入,提早发现Bug,符合质量控制前移的理念
    • 可以发现一些页面操作发现不了的问题
    • 低成本,高效益
    • 不同于传统的单元测试,接口测试是从用户的角度对系统进行全面的检测(对整体业务进行测试)
  • 接口测试的实现方式

    • 使用接口测试工具来实现(比如:JMeter、Postman)
    • 通过编写代码来实现(比如:Python + Requests)
  • 接口自动化测试:是让代码、工具代替人工自动的完成对接口进行测试的一种过程

在这里插入图片描述

2、html

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3、接口规范和API文档解析

在这里插入图片描述

  • 接口api文档解析
    • 什么是API文档?
      API文档就是接口文档,它是一个描述接口信息的文档。
    • 为什么要写API文档?
      便于前端开发和后端开发高效的合作
      项目迭代或人员迭代时,能够快速的是熟悉项目
      方便测试提前介入开展接口测试工作
      在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4、接口测试的测试点

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

5、接口用例设计的方法与思路
  • 功能测试:验证接口功能是否按照接口文档实现(输入+处理+输出)

    • 单接口测试
      • 正向功能:(通过性测试)
        • 仅必填参数
        • 全部参数
        • 参数组合
      • 反向测试:(异常测试)
        • 参数异常:无参、少参、多参、错误参数
        • 数据异常:数据为空、长度不符、类型不符、错误数据
        • 业务数据异常:结合业务功能考虑输出的各种异常返回情况
        • 在这里插入图片描述
  • 多接口测试:业务场景功能测试(站在用户角度考虑常用的使用场景)

    • 接口之间数据依赖
6、接口测试流程(复习)
  1. 需求分析
  2. 接口文档解析
  3. 测试用例设计
  4. 执行测试用例
    1. 使用工具:Postman
    2. 使用代码:python + Requests
  5. 缺陷跟踪管理
  6. 生成测试报告
  7. 实现持续集成(可选)
    在这里插入图片描述
7、接口用例模板

在这里插入图片描述

在这里插入图片描述

8、接口测试作用

在这里插入图片描述

在这里插入图片描述

  • post和get 区别
    在这里插入图片描述在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 8、如何判断一个bug为前端bug还是后端Bug?
    在这里插入图片描述
    在这里插入图片描述

2、postman

今日目标
  • 能够使用Postman设置请求方法、URL、请求头、请求体发送接口请求,并且查看响应数据
1、post安装和使用

介绍:一款接口调试工具,开发和测试都在使用

  • 特点
    • 图形化界面
    • 保存历史请求记录
    • 提供数据集管理功能
    • 可以再团队见同步接口数据
  • 安装方式
    • 谷歌浏览器插件(谷歌已停止应用程序支持)
    • 独立安装包安装(推荐安装方式)
      • 下载地址: https://www.getpostman.com/downloads/
      • Windows双击运行安装程序即可
      • 注意:【 Skip signing in and take me straight to the app 】
        在这里插入图片描述
2、post基础用法
  • 1、请求中常见的数据传递格式
  • 在这里插入图片描述
  • 2、用法
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
今日总结
  • 能够说出接口测试用例设计的方法与思路
  • 能够设计单接口接口测试用例(人力资源管理系统登录接口)
  • 能够设计业务场景测试用例(人力资源管理系统员工管理模块)
  • 能够使用postman设置请求方法、url、请求头、请求体发送接口请求,并查看响应数据
今日目标
  • 能够使用postman组织测试用例
  • 能够使用postman对测试结果进行断言(响应状态码和json格式响应数据)
  • 能够使用postman解决多接口的依赖
3、Postman用例管理
  • 作用:规范法管理接口上的大量测试用例
  • 实现步骤:
    1. 创建集合—项目(如IHRM、tpshop)
    2. 创建文件夹—模块(如:登录、员工管理)
    3. 创建请求—测试用例(如:登录成功)
4、Postman断言
1、断言前置基础
  • 断言:通过代码自动判断实际运行的结果是否与测试用例中的预期结果一致
    • 断言结果:
      • 结果一致:测试通过pass
      • 结果不一致:测试不通过fail
    • 复习:UnitTest常用断言方式有哪些?在这里插入图片描述
    • Postman的断言
      • 使用JavaScript语言编写的,写在Postman的【Tests】 标签中
      • 【Tests】中的脚本在发送请求之后执行,它会把断言的结果(PASS/FAIL)最终在【Test
        Results】 标签页中
      • Postman的常用断言
        • 断言响应状态码是否为200(Status code is 200)
        • 断言响应体JSON数据校验(Response body:JSON value check)
        • 断言响应体是否包含指定字符串(Response body: Contains string)
        • 断言响应体是否等于指定字符串(Response body:Is equal to a string)
        • 断言响应头是否包含指定的头信息(Response headers: Content-Type header check)
2、Postm
  • 2.1 断言响应状态码(重点)在这里插入图片描述

  • 2.2 断言JSON数据(重点)在这里插入图片描述

  • 2.3、 断言包含指定的字符串内容(知道)在这里插入图片描述

  • 2.4 断言等于指定的字符串(知道)在这里插入图片描述

  • 2.5 断言响应头标签(了解)在这里插入图片描述

5、环境变量与全局变量
  • 1、概念

    • 全局变量:作用范围是针对postman下面所有测试集均生效
    • 环境变量:
      • 只对选择了对应环境的测试集生效(如:选择了测试环境的测试集IHRM0720)
      • 开发环境、测试环境、生产/线上环境
      • 一套环境中变量不能重复、但是可以定义多个不重复的变量
  • 2、设置变量

    • 全局变量
      • 手动在这里插入图片描述

      • 代码

      • // 设置全局变量 pm.globals.set("g_name", "jack");

    • 环境变量
      • 手动在这里插入图片描述

      • 代码
        // 设置环境变量 pm.environment.set("e_name", "rose");

  • 3、获取变量

    • 全局变量与环境变量
      • 在请求参数中获取:{{变量名}}
      • 通过代码来获取
        pm.environment.get("variable_key");
        pm.globals.get("variable_key");
        // 获取环境变量的值 mobile2和password2
        var mobile = pm.environment.get("mobile2");
        var password = pm.environment.get("password2");
        console.log("测试环境中的mobile是:" + mobile)
        console.log("测试环境中的password是:" + password)
        
        
6、请求前置脚本(了解)
  • 1、请求前置脚本
    在这里插入图片描述
7、Postman关联(重点)
  • 在这里插入图片描述
    在这里插入图片描述
今日总结(3)
  • 能够使用postman的测试集来管理测试用例
  • 能够使用postman断言响应状态码和json格式响应体
  • 能够说出postman全局变量和环境变量的区别和用法
  • 能够使用postman的关联解决多接口的依赖关系(查询天气和百度搜索的依赖
今日目标(4)
  • Postman高级用法
    • 能够使用postman引入外部数据文件实现参数化
    • 能够使用newman生成测试报告
  • IHRM项目
    • 能够创建测试集管理IHRM系统的测试用例
    • 能够按照测试用例在postman中添加请求并录入接口信息
    • 能够对ihrm系统接口响应结果中的响应状态码和核心json字段进行断言
    • 能够使用环境变量处理ihrm系统中登录接口和员工管理接口的依赖关系
    • 能够在postman中导出测试集数据,并使用newman生成测试报告
8、 批量执行测试用例(掌握)
  • 批量执行测试用例(掌握)
    在这里插入图片描述
9、读取外部文件实现参数化(理解)
  • 1、基础在这里插入图片描述
  • 2、案例
    • 1、准备参数在这里插入图片描述

    • 2、设置参数在这里插入图片描述

    • 3、选择数据文件进行批量执行在这里插入图片描述

    • 4、检查结果在这里插入图片描述

10、postman测试报告(掌握)
1、Newman介绍与安装

在这里插入图片描述

2、 Postman导出测试集、环境变量、全局变量
  • 1、在这里插入图片描述
  • 2在这里插入图片描述
  • 3在这里插入图片描述
3、Newman运行及生成报告
newman run 测试脚本文件 -e 环境变量文件 -g 全局变量文件 -d 测试数据文件 -r html --
reporter-html-export report.html
eg: newman run demo.postman_collection.json -r html newman run
demo.postman_collection.json -r html --reporter-html-export report.html

在这里插入图片描述

今日目标(5)
  • 能够使用pymysql库对mysql数据库进行增删改查操作
11、数据库:pymysql库对mysql数据库进行增删改查操作
1、数据库介绍

在这里插入图片描述

2、数据库基本操作
  • 1、安装: pip install PyMySQL在这里插入图片描述

  • 2、操作流程(重点)在这里插入图片描述

  • 3、数据准备

    CREATE DATABASE if not EXISTS books DEFAULT charset utf8;
    use books;
    Drop TABLE if EXISTS `t_book`;
    CREATE TABLE `t_book`(
    `id` int(11) not null auto_increment,
    `title` VARCHAR(20) not NULL COMMENT '图书名称',
    `pub_date` date not NULL COMMENT '发布日期',
    `read` int(11) not null default '0' comment '阅读量',
    `comment` int(11) not null default '0' comment '评论量',
    `is_delete` TINYINT(1) not NULL DEFAULT '0' COMMENT '逻辑删除',
    PRIMARY KEY(`id`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='图书表';
    INSERT into `t_book` VALUES ('1','射雕英雄传','1980-05-01','12','34','0');
    INSERT into `t_book` VALUES ('2','天龙八部','1986-07-24','36','40','0');
    INSERT into `t_book` VALUES ('3','笑傲江湖','1995-12-24','20','80','0');
    Drop TABLE if EXISTS `t_hero`;
    CREATE TABLE `t_hero`(
    `id` int(11) not null auto_increment,
    `name` VARCHAR(20) not NULL COMMENT '姓名',
    `gender` SMALLINT(6) not NULL COMMENT '性别',
    `description` VARCHAR(200) default NULL comment '描述',
    `is_delete` TINYINT(1) not NULL DEFAULT '0' COMMENT '逻辑删除',
    `book_id` int(11) not null comment '所属图书ID',
    PRIMARY KEY(`id`),
    key `t_hero_book_id`(`book_id`)
    )ENGINE=INNODB DEFAULT CHARSET=utf8 COMMENT='英雄人物表';
    INSERT into `t_hero` VALUES ('1','郭靖','1','降龙十八掌','0','1');
    INSERT into `t_hero` VALUES ('2','黄蓉','0','打狗棍法','0','1');
    INSERT into `t_hero` VALUES ('3','乔峰','1','降龙十八掌','0','2');
    INSERT into `t_hero` VALUES ('4','令狐冲','1','独孤九剑','0','3');
    

在这里插入图片描述

  • 4、数据库基本操作
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述在这里插入图片描述

    在这里插入图片描述

3、数据库事务操作
  • 案例在这里插入图片描述

  • 概念、特点、操作、
    在这里插入图片描述在这里插入图片描述
    在这里插入图片描述

4、数据库工具封装
  • 需求

    需求分析:
    1. sql = "select * from t_book"
    2. 调用数据库工具方法
    result = exe_sql(sql)
    print("结果:", result)
    
  • 思路在这里插入图片描述

  • 实现

     导包
    import pymysql
    # 创建工具类
    class DBUtil():
    # 初始化
    __conn = None
    __cursor = None
    # 创建连接
    @classmethod
    def __get_conn(cls):
    if cls.__conn is None:
    cls.__conn = pymysql.connect(host="localhost",
    port=3306,
    user="root",
    password="root",
    database="books")
    return cls.__conn
    # 获取游标
    @classmethod
    def __get_cursor(cls):
    if cls.__cursor is None:
    cls.__cursor = cls.__get_conn().cursor()
    return cls.__cursor
    # 执行sql
    @classmethod
    def exe_sql(cls, sql):
    try:
    # 获取游标对象
    cursor = cls.__get_cursor()
    # 调用游标对象的execute方法,执行sql
    cursor.execute(sql)
    # 如果是查询
    if sql.split()[0].lower() == "select":
    # 返回所有数据
    return cursor.fetchall()
    # 否则:
    else:
    # 提交事务
    cls.__conn.commit()
    # 返回受影响的行数
    return cursor.rowcount
    except Exception as e:
    # 事务回滚
    cls.__conn.rollback()
    # 打印异常信息
    print(e)
    finally:
    # 关闭游标
    cls.__close_cursor()
    # 关闭连接
    cls.__close_conn()
    # 关闭游标
    @classmethod
    验证
    今日总结
    能够说出pymysql操作数据库的基本流程
    能够通过游标对象实现数据库的增删改查操作
    能够结合具体事例(如转账)说出数据库事务的概念
    知道pymysql处理数据库事务的主要方法
    每日作业
    1、请简述安装pymysql的流程
    2、请简述事务的4个特性
    3、请使用pymysql完成以下需求:
    插入一本书,书名为‘python从入门到放弃’,阅读量为50,评论量为0,发布日志为:2020-01-01
    测试工程师人员发现一个bug,这个本书的评论数与实际不符,要求你把评论量修改为修正后的
    值:250
    def __close_cursor(cls):
    if cls.__cursor:
    cls.__cursor.close()
    cls.__cursor = None
    # 关闭连接
    @classmethod
    def __close_conn(cls):
    if cls.__conn:
    cls.__conn.close()
    cls.__conn = None
    
  • 验证

    from test10_dbutil import DBUtil
    # sql = "select * from t_book"
    # sql = "insert into t_book(id, title, pub_date) values(4, '西游记', '1986-
    01-01');"
    # sql = "update t_book set title='东游记' where title = '西游记';"
    sql = "delete from t_book where title = '东游记';"
    result = DBUtil.exe_sql(sql)
    print(result)
    
今日总结(5)
  • 能够说出pymysql操作数据库的基本流程
  • 能够通过游标对象实现数据库的增删改查操作
  • 能够结合具体事例(如转账)说出数据库事务的概念
  • 知道pymysql处理数据库事务的主要方法
今日目标(6)
  • requests
    • 使用requests库传递URL参数、设置请求头与请求体
    • 使用requests库获取响应数据
    • 使用requests库发送不同类型的请求
    • requests库session操作
  • unittest
    • requests库集成unittest

3、request 库

1、request库
1.1、 介绍及安装
  • 安装:pip install requests
  • 验证:pip install requests
    在这里插入图片描述
1.2、 发送get请求

在这里插入图片描述

1.3、发送post请求

在这里插入图片描述

  • 3.1 提交form表单在这里插入图片描述

  • 3.2 提交json数据在这里插入图片描述

1.4、其他请求方式(了解)

在这里插入图片描述

1.5、传递URL参数

在这里插入图片描述

1.6、响应内容解析
  • 用途:断言

  • 实现:

    • response.status_code :响应状态码
    • response.url :url地址信息
    • response.encoding :查看响应数据编码格式
    • response.headers :查看头部信息
    • response.cookies : 查看cookies信息
    • response.text :文本形式查看响应数据
    • response.content :字节码形式查看响应数据
    • response.json() :json形式查看响应数据
  • 案例1
    在这里插入图片描述

  • 案例2
    在这里插入图片描述

1.7、设置请求头

在这里插入图片描述

1.8、 设置cookie(了解)

在这里插入图片描述
在这里插入图片描述

1.9 、 设置session(掌握)

在这里插入图片描述

2、集成UnitTest
  • UnitTest优势
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

在这里插入图片描述

4、接口测试框架开发

今日目标(7)

- 接口测试框架
- 能够按照接口测试框架的封装思想,实现TPshop登录接口的接口对象封装
- 能够按照接口测试框架的封装思想,使用UnitTest编写测试用例实现接口的测试
- 能够实现接口测试框架项目目录结构的定义
- 能够提取测试脚本中的测试数据,实现测试数据参数化
- 能够使用HTMLTestRunner生成接口测试报告

1、接口测试框架开发

1.1、 框架结构

在这里插入图片描述
在这里插入图片描述

1.2、 框架目录结构

在这里插入图片描述

1.3、 封装被测试系统 接口

在这里插入图片描述

1.4、 定义接口测试用例

在这里插入图片描述

1.5、 集成测试报告

在这里插入图片描述

1.5、 测试数据参数化
  • 1、基于json文件实现参数化
    在这里插入图片描述

  • 2、基于数据库实现参数化在这里插入图片描述

2、IHRM项目实战任务

在这里插入图片描述

今日总结(7)

在这里插入图片描述

今日目标(8)

在这里插入图片描述

3、IHRM项目实战

3.1、搭建接口测试框架

在这里插入图片描述

3.2、封装被测试系统接口
1、登陆

在这里插入图片描述

2、员工管理

在这里插入图片描述

3.3、定义接口测试用例
1、 登陆

在这里插入图片描述

1.1、实现登陆成功

在这里插入图片描述在这里插入图片描述

1.2、 实现其他测试用

在这里插入图片描述

1.3、 生成测试报告

在这里插入图片描述

1.4、 参数化

在这里插入图片描述在这里插入图片描述

在这里插入图片描述

2、 员工管理

在这里插入图片描述

2.1、 添加员工

在这里插入图片描述

在这里插入图片描述

2.2、 修改员工

在这里插入图片描述

在这里插入图片描述

2.3、 查询员工

在这里插入图片描述

在这里插入图片描述

2.4、 删除员工

在这里插入图片描述
在这里插入图片描述

2.5、 封装公共断言方法

在这里插入图片描述

在这里插入图片描述

2.6、 生成测试报告

在这里插入图片描述

2.7、 参数化

5、持续集成

今日目标(9)

在这里插入图片描述

1、持续集成相关知识

在这里插入图片描述

2、git

在这里插入图片描述
在这里插入图片描述

  • 有时候我们在本地开发了一个项目,想推送到gitee仓库管理,有两种方式
    • git remote add origin https://gitee.com/用户个性地址/HelloGitee.git在这里插入图片描述

3、gitee

在这里插入图片描述

4、Jenkins

4.1、介绍与安装

在这里插入图片描述

  • jenkins下载地址:
    • https://mirrors.tuna.tsinghua.edu.cn/jenkins/war/latest/
      在这里插入图片描述
  • java –jar jenkins.war --httpPort=8888
    在这里插入图片描述
4.2、Jenkins插件——HTML Publisher
  • 进入首页,选择’Jenkins’后面的小图标->‘系统管理’->‘管理插件’
    在这里插入图片描述
4.3、Jenkins邮箱配置
4.3.1 qq邮箱

在这里插入图片描述

4.3.2 Jenkins配置qq邮箱

在这里插入图片描述

5、基于Postman实现持续集成

5.1、操作步骤

在这里插入图片描述

5.2. 操作详细说明
5.3、常见问题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

6、基于代码实现持续集成

6.1、操作步骤

在这里插入图片描述

今日总结(9)

在这里插入图片描述

6、接口测试扩展

今日目标(10)

在这里插入图片描述

1、Mock

1.1、Mock测试

在这里插入图片描述

1.2、Python + Flask实现mock平台搭建

在这里插入图片描述
在这里插入图片描述

1.3、Moco框架

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

2、Fiddler

在这里插入图片描述

3、webservice

在这里插入图片描述

今日总结

在这里插入图片描述

六、ego实战项目

七、性能测试

注:性能测试课程总体目标:jmeter使用,项目接口压测、分析调优

在这里插入图片描述

今日目标(1) 性能测试定义、目的、测试策略、性能指标、测试流程、loadrunner和jmeter优缺点

在这里插入图片描述在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

今日目标(2)jmeter 环境搭建、主要元件及作用域、线程组、http请求配置、jmeter参数化应用

在这里插入图片描述

  • Jmeter三个重要组件:
    在这里插入图片描述
1、jmeter和loadrunner区别

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

今日目标(3)jmeter断言、关联、自动录制脚本

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

今日目标(4)直连数据库、逻辑控制器、常用定时器、分布式配置和使用

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

4.1、Jmeter直连数据库

在这里插入图片描述

在这里插入图片描述

4.2、逻辑控制器:

在这里插入图片描述

4.3、循环控制器:

在这里插入图片描述
在这里插入图片描述

4.4、定时器:

在这里插入图片描述

4.5、jmeter分布式:

在这里插入图片描述
在这里插入图片描述

4.6、jmeter报告:

在这里插入图片描述

今日目标(5)安装jmeter及相关组件、获取有效的性能需求、编写性能测试用例、用jmeter编写接口测试脚本

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

5.1、并发数及Jmeter性能测试常用图表
1、插件安装:

在这里插入图片描述

2、性能测试常用图表:

在这里插入图片描述

  • 1、 Concurrency Thread Group(右键点线程):

    • 说明:阶梯线程组

    在这里插入图片描述

  • 2、TPS:运行过程中的TPS统计(右键点监听器)

    • 每秒完成事务数 场景:统计业务成功率在这里插入图片描述
  • 3、 Bytes Through Over Time:运行过程中的传输速率(右键点监听器)

    • 查看服务器吞吐流量 单位/字节
      在这里插入图片描述
  • 4、基于jmeter客户端监控服务器 硬件资源:

    • 用来监控服务端的性能的工具,包括cpu、内存、磁盘、网络等性能数据
    • 注:使用之前需要在服务器端安装监听服务程序并启动在这里插入图片描述
3、并发数计算:

在这里插入图片描述

5.2、项目介绍和部署
性能测试项目阶段的整体安排

在这里插入图片描述

1、项目介绍与部署
1、微商城功能介绍:

在这里插入图片描述

2、微商城项目的技术介绍:

在这里插入图片描述

3、微商城项目技术架构

在这里插入图片描述

4、熟悉数据库设计:

在这里插入图片描述

5、微商城项目的部署过程:

在这里插入图片描述

2、性能测试需求分析

在这里插入图片描述

1、性能需求的获取:

在这里插入图片描述

2、性能测试点的提取规则:

在这里插入图片描述

3、轻商城性能测试点的提取:

在这里插入图片描述

4、确定性能测试目标

在这里插入图片描述

3、性能测试计划

在这里插入图片描述
在这里插入图片描述

4、测试用例设计

在这里插入图片描述

5、测试脚本开发

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1、常用的Jmeter元件:

在这里插入图片描述

2、编写脚本:

在这里插入图片描述

6、建立测试环境
1、特点:

在这里插入图片描述

2、如何达成性能测试环境与生产环境一致:

在这里插入图片描述

3、测试数据的准备(插入10万条数据):

在这里插入图片描述在这里插入图片描述

7、执行测试脚本
1、执行测试脚本的测试机:

在这里插入图片描述
在这里插入图片描述

2、性能测试脚本执行:
2.1、 登陆脚本

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

2.X 、linux重启后检查项:

在这里插入图片描述

2.2、 进入首页脚本:

在这里插入图片描述

2.3、 加入购物车脚本:

在这里插入图片描述在这里插入图片描述

2.4、 结算并下订单脚本

在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.5、 稳定性测试执行:

在这里插入图片描述

8、性能测试监控
1、性能测试监控关键指标

在这里插入图片描述

1.1、 系统指标

在这里插入图片描述

1.2、 硬件服务器资源指标

在这里插入图片描述
在这里插入图片描述

1.3、 java应用

在这里插入图片描述
在这里插入图片描述

1.4、 数据库监控

在这里插入图片描述
在这里插入图片描述

1.5、 压测机资源:

在这里插入图片描述

2、性能监控工具

在这里插入图片描述
在这里插入图片描述

3、服务器资源

在这里插入图片描述

4、数据库资源监控——慢查询:

在这里插入图片描述

5、JVM监控—Jvisualvm.exe

在这里插入图片描述在这里插入图片描述

9、性能分析和调优
1、性能调优的步骤:

在这里插入图片描述

2、性能调优案例:
  • 案例1在这里插入图片描述在这里插入图片描述

  • 案例2在这里插入图片描述

  • 案例3在这里插入图片描述

  • 案例4在这里插入图片描述

10、编写测试报告

在这里插入图片描述

今日目标(6)性能测试脚本、准备测试环境和数据、运行性能脚本、监控数据指标

在这里插入图片描述

在这里插入图片描述

今日目标(7)对性能测试监控指标了解

在这里插入图片描述

在这里插入图片描述

今日目标(8)Locust测试脚本定义任务、任务集、locust用户、查看监控指标

在这里插入图片描述

8.1、特点:

在这里插入图片描述

8.2、安装:

在这里插入图片描述

8.3、编写测试脚本的步骤:

在这里插入图片描述

1、定义任务:

在这里插入图片描述

2、定义任务集(用户行为):

在这里插入图片描述

3、定义locust类:

在这里插入图片描述

8.4、运行Locust:

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

8.5、启动压测执行:

在这里插入图片描述

  • 正则
    在这里插入图片描述

八、金融项目实战

九、ui自动化测试 及 实战

今日目标(1):UI自动化、web自动化测试、元素定位

在这里插入图片描述

一、UI自动化测试介绍

1、什么是自动化测试

概念:由程序代替人工进行系统校验的过程

1.1自动化测试能解决的问题?
  • 回归测试 (冒烟测试)
    • 针对之前老的功能进行测试 通过自动化的代码来实现。
    • 针对上一个版本的问题的回归
  • 兼容性测试 web实例化不同的浏览器驱动相当于对不同的浏览器进行操作,从而解决浏览器的兼容性测试问题
  • 性能测试 通过一些工具来模拟多个用户实现并发操作
  • 提高工作效率,保障产品质量
1.2自动化测试的优点
  • 自动化测试能在较少的时间内执行更多的测试用例
  • 自动化测试能够减少人为的错误
  • 自动化测试能够克服手工的局限性
  • 自动化测试可以重复执行( 注册用户 --已注册)
1.3自动化则试的误区
  • 自动化测试可以完全代替手工测试 针针某些功能(图片、页面架构)也是没有办法通过自动化来实现

  • 自动化测试一定比手工测试厉害 金融行业更看重业务的积累

  • 自动化测试可以发现更多的BUG 是因为自动化测试主要用来做回归测试

  • 自动化测试适用于所有的功能 页面的架构、图片、文字,用户体验

1.4自动化测试分类
  • web自动化测试(本阶段学习内容) web系统
  • 移动app自动化(本阶段学习内容) app应用
  • 接口自动化 接口:用来给web或者app前端传输数据用的
  • 单元测试-自动化测试 针对开发人员的代码进行测试。 是由开发自己来做的
  • 安全测试(渗透测试) 针对系统、数据、应用等安全方面进行测试
  • 桌面应用自动化测试 针对windows的桌面应用程序进行自动化测试
  • 嵌入式设备自动化测试 针对嵌入式设备的应用程序进行自动化测试

2、什么是UI自动化测试

概念:UI(user interface)通过对web应用以及app应用进行自动化测试的过程。

2.1 什么项目适合做ui自动化测试?
  • 需求变动不频繁 前端代码变更维护不方便
  • 项目周期长 项目短,上线之后不需要再去测试
  • 项目需要回归测试 不用回归测试的也不需要写自动化
2.2 UI自动化测试在什么阶段开始?
  • 手工测试完成之后才做自动化测试,相当于是编写自动化测试代码(通过手工测试能够清楚的知道自动化测试的步骤以及结果)
2.3 UI自动化测试所属分类
  • 黑盒测试(功能测试) UI自动化测试 模拟人工对web以及app页面进行操作的过程
  • 白盒测试(单元测试)
  • 灰盒测试(接口测试)

1、V1 通过手工测试完成之后,有十个功能。

2、 针对V1版本的十个功能,进行自动化的代码编写

3、V2 增加了十个功能(总共有20个功能), v2版本的测试过程当,新增的10个功能手工测试。针对老的10个功能就可以通过自动化来进行回归测试。


二、web自动化测试基础

1、web自动化框架
1.1 主流的web自动化工具
  • QTP 由惠普公司开发的一款自动化工具,支持web、桌面的自动化测试。 收费的商用工具。
  • selenium 主要用来做web自动化测试的,开源的免费的工具。
  • root framework 自动化测试平台。通过它可以实现web自动化测试、接口自动化测试、桌面的自动化测试。
1.2 selenium特点

selenium中文名是硒,就是用来做web自动化测试的

  • 开源软件: 源代码开放,但是不一定免费

  • 跨平台: 平台指操作系统。 linux、windows、 mac操作系统

  • 支持多种浏览器:firefox、chrome、 ie、edge、opera、safari

  • 支持多语言:python\java\C#\js\Ruby\PHP

  • 成熟稳定功能强大:被大公司使用。google、华为、百度、腾讯

    后续大家在选择自动化工具的时,这几个特点就是选择工具的依据。

1.3selenium发展史
  • selenium 1.0

    • selenium IDE

      • 是firefox的一款插件,通过它可以记录用户的操作并生成对应的自动化脚本。
    • selenium grid 通过grid可以将脚本下发到不同的电脑在不同的浏览器上面执行。

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h76R7HKL-1685171571261)(D:/img/image-20200621105146357.png)]

    • selenium RC

      由JS封装的一个工具,用来对浏览器进行操作的。

  • selenium 2.0

    • selenium 1.0 + webdriver
    • 针对浏览器的操作都是通过webdriver来实现的。
    • 支持的语言更多
  • selenium 3.0

    • 删除了selenium RC
    • 全面支持java8
    • 支持macOS,支持safari浏览器
    • 支持微软最新的EDGE浏览器,支持更多的浏览器
2、环境搭建
2.1 selenium工作原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IV3O5OiO-1685171759407)(\img\image-20200621111601100.png)]

2.2 selenium环境安装
2.1 python开发工具安装(不需要安装,python阶段已经安装过了)
2.2 浏览器安装(浏览器电脑已安装)

需要注意浏览器与浏览器驱动的版本, 不同的浏览器有不同的浏览器驱动,而且不同的版本也有不同的浏览器驱动

2.3selenium工具包安装
  • 在线安装方式: 在dos命令行中输入: pip install selenium

  • 离线安装方式:

    • 需要获取selenium离线安装包并解压
    • 在DOS命令行进入到解压的目录,然后执行python setup.py install
  • pycharm进行安装

    • 在file菜单中选择setting, 然后选择"project- interpreter"

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z2lSy1te-1685171759408)(D:/img/image-20200621112636954.png)]

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m2N8LnII-1685171759408)(D:/img/image-20200621112852206.png)]

  • 如何确认selenium安装完成:可以通过pip show selenium进行查看

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cHkjUTfO-1685171759409)(D:/img/image-20200621113223428.png)]

2.4 浏览器驱动安装
  • 安装浏览器驱动之前,一定要知道自己浏览器的版本。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ol6vUycw-1685171759409)(D:/img/image-20200621113433417.png)]

  • 通过https://npm.taobao.org/mirrors/chromedriver/ 获取对应的浏览器驱动

  • 解压浏览器驱动文件,并将驱动文件复制到python的根目录就行了。

    查看python安装根目录:通过where python命令

2.4 入门示例
  • 项目创建

    • 项目名称不要 与第三方的模块名同名

    • 文件名称也不要与第三方的模块名或者是类名同名

    • 项目创建时不要使用虚拟环境.

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B0ypN0j6-1685171759409)(D:/img/image-20200621114601500.png)]

# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("http://www.baidu.com")
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()

FAQ:

搭建环境问题总结:

1、安装过程中没有urllib3这个模块

  • 如果没有对应的模块,可以通过在线或者离线的方式,安装一下urllib3这个模块

2、chrome浏览器的版本与chrome浏览器驱动的版本不一致

  • 先确定浏览器的版本,再下载对应的浏览器驱动版本

3、chrome浏览器安装有问题,移动了chrome浏览器的应用程序目录 从C盘移到E盘

  • 不要随便去移动安装程序的位置,因为在注册表中会记录程序安装目录信息。

4、chrome浏览器驱动没有复制到python安装的根目录下

  • python安装的根目录不是python安装文件的目录。

5、大家在创建项目时,用的是虚拟环境(包含venv目录),虚拟环境下找不到selenium模块

  • 切换虚拟环境到正常的环境

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YV8eMSe2-1685171759410)(img/image-20200621143100635.png)]


[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eevUTEsP-1685171759410)(ui自动化测试day01/image-20200621143416928.png)]


3、元素定位
3.1 如何进行元素定位?

元素: 由标签头+标签尾+标签头和标签尾包括的文本内容

元素的信息就是指元素的标签名以及元素的属性

元素的层级结构就是指元素之间相互嵌套的层级结构

元素定位最终就是通过元素的信息或者元素的层级结构来进行元素定位。

3.2 浏览器开发者工具介绍
  • 浏览器开发者工作主要用来查看元素的信息, 同时也可以查看接口的相关信息。
  • 浏览器开发者工作不需要安装,浏览器自带.
  • 浏览器开发者工具的启动:
    • 直接按F12 不区分浏览器
    • 通过右键的方式来启动浏览器开发者工具 (谷歌浏览器右键选择“检查”, 火狐浏览器右键选择“检查元素”
  • 浏览器开发者工具使用
    • 点击 浏览器开发者工具左上角的 元素查看器按钮
    • 再点击想要查看的元素
3.3 元素定位
  • id定位
  • name定位
  • class_name定位
  • tag_name定位
  • link_text定位
  • partail_link_text定位
  • xpath定位
  • css定位
3.3.1 ID定位
  • 通过元素的ID属性值来进行元素定位 ,在html标准规范中 ID值是唯一的

    说明: 元素要有ID属性

  • 定位方法: find_element_by_id(id) # id参数表示的是id的属性值

# 导包selenium
import time

from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 通过ID定位到用户名输入框并在用户名输入框中输入admin
driver.find_element_by_id("userA").send_keys("admin")
# 通过ID定位到密码输入框并在密码输入框中输入123456
driver.find_element_by_id("passwordA").send_keys("123456")
# 等待3s
time.sleep(3)
# 退出浏览器
driver.quit()
3.3.2 name定位
  • 通过元素的name属性值为进行元素定位 name属性值 在HTML页面中,是可以重复的。

    说明:元素要有name属性

  • 定位方法: find_element_by_name(name) # name 参数表示的是name的属性值

# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 通过name定位用户名,输入admin
driver.find_element_by_name("userA").send_keys("admin")
# 通过name定位密码, 输入123456
driver.find_element_by_name("passwordA").send_keys("123456")
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()
3.3.3 class_name定位
  • 通过元素的class属性值进行元素定位 class属性值是可重复的

    说明:元素必须要有class属性

  • 定位方法: find_element_by_class_name(class_name) # class_name参数表示的是class的其中一个属性值

# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 1).通过class_name定位电话号码A,并输入:18611111111
driver.find_element_by_class_name("telA").send_keys("18611111111")
# 2).通过class_name定位电子邮箱A,并输入:123@qq.com
driver.find_element_by_class_name("dzyxA").send_keys("123@qq.com")
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()
3.3.4 tag_name定位
  • 通过元素的标签名称进行定位, 在同一个html页面当中,相同标签元素会有很多。

    这种定位元素的方式不建议大家在工作当中使用。

  • 定位方法: find_element_by_tag_name(tag_name) # tag_name表示的是元素的标签名称。

    如果有重复的元素,定位到的元素默认都是第一个元素

# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 1).使用tag_name定位用户名输入框,并输入:admin
driver.find_element_by_tag_name("input").send_keys("admin")
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()
3.3.5 link_text定位
  • 通过超链接的全部文本信息进行元素定位 ,主要用来定位a标签
  • 定位方法: find_element_by_link_text(link_text) # link_text参数代表的是a标签的全部文本内容。
# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 通过linu_text定位到新浪网站并点击
# driver.find_element_by_link_text("新浪").click()
driver.find_element_by_link_text("访问 新浪 网站").click()
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()
3.3.6 partial_link_text定位
  • 通过超链接的局部文本信息进行元素定位,主要用来定位a标签
  • 定位方法:find_element_by_partial_link_text(partial_link_text) # partial_link_text表示的是a标签 的局部文本内容
# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 通过partial_link_text定位到新浪网站并点击
driver.find_element_by_partial_link_text("访问 新浪 网站").click()
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()
3.3.7 定位一组元素
  • 定位一组元素的方法:

    find_elements_by_id(id)

    find_elements_by_tag_name(tag_name)

  • 定位一组元素返回的值是一个列表

  • 可以通过下标来使用列表中的元素

  • 下标是从0开始。

# 导入selenium
import time

from selenium import webdriver
# 实例化浏览器驱动对象(创建浏览器驱动对象)
driver = webdriver.Chrome()  # 创建的是谷歌浏览器驱动对象   chrome后面有括号,而且第一个字母要大写
# driver = webdriver.Firefox() # 创建火狐浏览器驱动对象
# 打开百度网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 使用tag_name定位密码输入框(第二个input标签),并输入:123456
elements = driver.find_elements_by_tag_name("input")
elements[2].send_keys("123456")
# 等待3s(代表业务操作)
time.sleep(3)     # 通过快捷导包的方式导入time模块,  光标要在time后面再按alt+enter
# 退出浏览器驱动(释放系统资源)
driver.quit()

今日目标(2):元素定位_余、元素及浏览器操作

在这里插入图片描述

一、元素定位Xpath、CSS

?为什么要使用Xpath或者CSS

因为在页面当中,有一些元素无法通过元素的信息精准的定位到,所以需要借助于Xpath和CSS

1 xpath元素定位
1.1 什么是xpath

总结:xpath是用来在xml文件中进行元素定位的标记语言,html是一种特殊的xml,所以xpath也可以用在html中

1.2 Xpath定位策略
  • 路径定位
  • 属性定位
  • 属性与逻辑结合
  • 属性与层级结合

定位方法: find_element_by_xpath(xpath) # xpath表达式

按Ctrl+F 可以在搜索框对xpath和css表达式进行校验

1.2.1 路径定位
  • 绝对路径 表达式是以 /html开头,元素的层级之间是以 / 分隔

    相同层级的元素可以使用下标,下标是从1开始.

    需要列出元素所经过的所有层级元素 , 工作当中, 一般不使用绝对路径

    例:/html/body/div/fieldset/form/p[1]/input

  • 相对路径 匹配任意层级的元素, 是以 //tag_name或者//* 开头

    也可以使用下标,下标是从1开始。

    例子://p[5]/button

# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 通过xpath的绝对路径定位用户名输入框并输入admin
driver.find_element_by_xpath("/html/body/div/fieldset/form/p/input").send_keys("admin")
# 等待3S
time.sleep(3)
# 通过xapth的相对路径定位密码输入框并输入123
driver.find_element_by_xpath("//form/p[2]/input").send_keys("123")
# 等待3S
time.sleep(3)
# 退出
driver.quit()
1.2.2 元素属性定位
  • //*或者//tag_name //*[@attribute=‘value’] # attribute表示的是元素的属性名,value表示的是元素对应属性值

如果使用class的属性进行元素定位,需要用到class里面所有的值

# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 利用元素的属性信息精确定位用户名输入框,并输入:admin
driver.find_element_by_xpath("//*[@placeholder='请输入用户名']").send_keys("admin")
# 等待3S
time.sleep(3)
# 退出
driver.quit()

1.2.3 属性与逻辑结合定位
  • //* 或者//tag_name 开头 //*[@attribute1=‘value1’ and @attribute2=‘value2’]
# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 使用属性与逻辑结合定位策略,在test1对应的输入框里输入:admin
driver.find_element_by_xpath("//input[@name='user' and @class='login']").send_keys("admin")
# 等待3S
time.sleep(3)
# 退出
driver.quit()
1.2.4 属性与层级结合定位
  • 是以//*或者//tag_name开头 //p[@id=‘pa’]/input

    在任意层给当中,都可以结合属性来使用

    # 导包
    import time
    from selenium import webdriver
    # 创建浏览器驱动对象
    driver = webdriver.Chrome()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    
    # 使用层级与属性结合定位策略,在test1对应的输入框里输入:admin
    driver.find_element_by_xpath("//p[@id='p1']/input").send_keys("admin")
    # 等待3S
    time.sleep(3)
    # 退出
    driver.quit()
    
1.2.5 XPATH扩展
  • //*[text() = ‘value’] value表示的是要定位的元素的全部文本内容.

  • //*[contains(@attribute,‘value’)] attribute表示的属性名称, value表示的是字符串

    要定位的元素中,attribute属性的属性值包含了value的内容。

  • //*[starts-with(@attribute,‘value’)] attribute表示的属性名称, value表示的是字符串

    要定位的元素,attribute属性的属性值是以value开头


2、CSS定位
2.1 什么是CSS

总结:css是可以用来在selenium中定位元素的

CSS定位元素的方法: find_element_by_css_selector(css_selector) # css_selector表示的是CSS选择器表达式

2.2 CSS定位策略
  • id选择器
  • class选择器
  • 元素选择器
  • 属性选择器
  • 层级选择器
2.2.1 id选择器
  • 表达式: #id # 表示通过元素的ID属性进行元素选择 id 表示的的id属性的属性值
2.2.2 class选择器
  • 表达式: .class # .表示通过元素的class属性进行元素选择, class表示的class属性的其中一个属性值
# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 通过css的id选择器定位用户名输入框,输入admin
driver.find_element_by_css_selector("#userA").send_keys("admin")
# 通过css的class选择器定位电子邮箱输入框,输入123@qq.com
driver.find_element_by_css_selector(".emailA").send_keys("123@qq.com")
# 等待3S
time.sleep(3)
# 退出
driver.quit()
2.2.3 元素选择器
  • 就是通过元素标签名称来选择元素 。表达式: tag_name 不推荐使用
2.2.4 属性选择器
  • 就是通过元素的属性来选择元素。 表达式:[attribute=‘value’] #attribute 表示的是属性名称,value表示的是属性值

    如果使用的是class属性,需要带上class的全部属性值

# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 通过css的元素选择器定位用户名输入框,输入admin
driver.find_element_by_css_selector("input").send_keys("admin")
# 通过css的属性选择器定位电子邮箱输入框,输入123@qq.com
driver.find_element_by_css_selector("[class='emailA dzyxA']").send_keys("123@qq.com")
# 等待3S
time.sleep(3)
# 退出
driver.quit()
2.2.5层级选择器
  • 父子层级关系选择 器
    • 表达式: element1>element2 通过element1来找element2,并且element2是element1的直接子元素
  • 隔代层级关系选择器
    • 表达式: element1 element2 通过element1来找element2, 并且element2是element1的后代元素
# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 通过css的层级选择器定位用户名输入框输入admin
driver.find_element_by_css_selector(".zc #userA").send_keys("admin")
# 等待3S
time.sleep(3)
# 退出
driver.quit()
2.2.6CSS扩展
  • input[type^=‘value’] input表示标签名称,type表示属性名称, value表示的文本内容

    查找元素type属性值是以value开头的元素

  • input[type$=‘value’] input表示标签名称,type表示属性名称, value表示的文本内容

    查找元素type属性值以value结尾的元素

  • input[type*=‘value’] input表示标签名称,type表示属性名称, value表示的文本内容

    查找元素type属性值包含value的元素

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5wU0B9W1-1685173214554)(img/image-20200622150415134.png)]

3、元素定位总结
4、定位元素的另外一种写法
  • find_element(By.ID, id) 需要导入By类。

二、元素操作及浏览器操作方法

1、元素操作
  • 点击操作 element.click() element表示的是元素对象
  • 输入操作 element.send_keys(“value”) element表示的是元素对象, value表示的是要输入的内容
  • 清除操作 element.clear() element表示的是元素对象. 将输入框里面的内容全部清除。
# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 1).通过脚本执行输入用户名:admin;密码:123456;电话号码:18611111111;电子邮件:123@qq.com
driver.find_element(By.ID, "userA").send_keys("admin")
driver.find_element(By.ID, "passwordA").send_keys("123456")
driver.find_element(By.CSS_SELECTOR, ".telA").send_keys("18611111111")
driver.find_element(By.XPATH, "//*[@class='emailA dzyxA']").send_keys("123@qq.com")
# 2).间隔3秒,修改电话号码为:18600000000
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, ".telA").clear()
time.sleep(3)
driver.find_element(By.CSS_SELECTOR, ".telA").send_keys("18600000000")

# 等待3S
time.sleep(3)
# 退出
driver.quit()

2、浏览器操作
  • 浏览器常用操作方法
  1. maximize_window() 最大化浏览器窗口 --> 模拟浏览器最大化按钮 实例化浏览器驱动之后,就可以调用窗口最大化的方法

  2. set_window_size(width, height) 设置浏览器窗口大小 --> 设置浏览器宽、高(像素点)

  3. set_window_position(x, y) 设置浏览器窗口位置 --> 设置浏览器位置

    x,y是一个坐标点,通过此坐标点确定浏览器最左上角的位置,以此确定浏览器在屏幕上的位置。

    x, y不能超过屏幕的分辨率大小

# 导包
import time
from selenium import webdriver
# 创建浏览器驱动对象
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
# 窗口最大化
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
time.sleep(3)
# 设置窗口大小
driver.set_window_size(500, 500)
time.sleep(3)
# 设置窗口位置
driver.set_window_position(300, 300)

# 等待3S
time.sleep(3)
# 退出
driver.quit()
  1. back() 后退 --> 模拟浏览器后退按钮
  2. forward() 前进 --> 模拟浏览器前进按钮
  3. refresh() 刷新 --> 模拟浏览器F5刷新
  4. close() 关闭当前窗口 --> 模拟点击浏览器关闭按钮
  5. quit() 关闭浏览器驱动对象 --> 关闭所有程序启动的窗口
import time

from selenium import webdriver
# 创建浏览器驱动对象
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
# 窗口最大化
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 在注册A页面中点击 新浪网站
driver.find_element(By.CSS_SELECTOR, "#linkto>a").click()
# 调用浏览器的后退
time.sleep(3)
driver.back()
# 再调用浏览器的前进
time.sleep(3)
driver.forward()
# 再调用浏览器的后退
time.sleep(3)
driver.back()
# 点击击访问新浪网站
driver.find_element(By.XPATH, "//*[text()='访问 新浪 网站']").click()
time.sleep(3)
# 再调用关闭按钮
driver.close()
time.sleep(3)
# 等待3S
time.sleep(3)
# 退出
driver.quit()
  1. title 获取页面title
  2. current_url 获取当前页面URL
import time

from selenium import webdriver
# 创建浏览器驱动对象
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
# 窗口最大化
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 获取页面标题
print(driver.title)

# 获取页面的URL地址
print(driver.current_url)

# 等待3S
time.sleep(3)
# 退出
driver.quit()
3、获取元素信息

今日目标(3)selenium提供鼠标键盘、元素等待、下拉框、弹出框、滚动条操作

  • selenium提供一下操作
    • 鼠标键盘、
    • 元素等待、
    • 下拉框、
    • 弹出框、
    • 滚动条操作
3、获取元素信息(接day02)
  • 为什么要学习获取元素信息的方法

    主要为了获取相关的信息进行断言,判断自动化用例最终的执行结果。

  • 获取元素常用的方法:

    • size 获取元素的大小 返回的是一个字典,里面包含 元素高度和宽度的值
    • text 获取元素的文本内容
    • get_attribute(“attribute”) 获取元素对应属性名称的属性值 , attribute表示的是属性名
    # 导包
    import time
    
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    # 1).获取用户名输入框的大小
    print(driver.find_element(By.ID, "userA").size)
    # 2).获取页面上第一个超链接的文本内容
    print(driver.find_element(By.LINK_TEXT, "新浪").text)
    # 3).获取页面上第一个超链接的地址
    print(driver.find_element(By.LINK_TEXT, "新浪").get_attribute("href"))
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    
    • is_displayed() 判断元素是否可见 返回值为true或者false
    • is_enabled() 判断元素是否可用,返回值为true或者false
    • is_selected() 判断复选框或者单选框是否被选中,返回值为true或者false
    # 导包
    import time
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    # 4).判断页面中的span标签是否可见
    print("判断元素是否可见,默认应该是False:", driver.find_element(By.NAME, "sp1").is_displayed())
    # 5).判断页面中取消按钮是否可用
    print("判断取消按钮是否可用,默认应该是False:", driver.find_element(By.ID, "cancelA").is_enabled())
    # 6).判断页面中'旅游'对应的复选框是否为选中的状态
    print("判断旅游复选框是否选中,默认应该是True:", driver.find_element(By.ID, "lyA").is_selected())
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    

一、鼠标和键盘操作

1、鼠标操作
1.1 鼠标操作实现方式
  • selenium提供鼠标操作的方法及步骤

    需要导入ActionChains类

    • 通过ActionChains实例化鼠标对象 action = ActionChains(driver) # driver表示的是浏览器驱动对象
    • 调用鼠标的事件方法
    • 调用鼠标的执行方法 action.perform()
1.2 鼠标右击操作
  • 右击操作的实现步骤:

    针对由html自定义的右键菜单。可以使用右击的方式来进行操作。

    • 创建鼠标对象 action = ActionChains(driver)
    • 调用右击事件方法 action.context_click(element) # element表示的是一个元素对象
    • 调用鼠标执行方法 action.perform()
    # 导包
    import time
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    
    # 在用户名文本框上点击鼠标右键
    # 创建鼠标对象
    action = ActionChains(driver)
    # 调用鼠标右击的方法
    action.context_click(driver.find_element(By.ID, "userA"))
    # 调用鼠标执行的方法
    action.perform()
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    
1.3 鼠标双击操作
  • 鼠标双击的实现步骤

    • 创建鼠标对象 action=ActionChains(driver)
    • 调用鼠标双击事件方法 action.double_click(element) # element表示是元素对象
    • 调用鼠标的执行方法 action.perform()
    # 导包
    import time
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    
    # 输入用户名admin,暂停3秒钟后,双击鼠标左键,选中admin
    element = driver.find_element(By.ID, "userA")
    element.send_keys("admin")
    time.sleep(3)
    # 创建鼠标对象
    action = ActionChains(driver)
    # 调用鼠标双击事件方法
    action.double_click(element)
    # 调用鼠标执行方法
    action.perform()
    
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    
1.4 鼠标拖动操作
  • 鼠标拖动的实现步骤:
    • 创建鼠标对象 action = ActionChains(driver)
    • 调用鼠标拖动事件方法 action.drag_and_drop(source, target) # source表示的是源元素,被拖动的元素, target表示是目标源,也就是要拖动到哪个元素上。
    • 调用鼠标执行方法 action.perform()
# 导包
import time
from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/drag.html")

# 把红色方框拖拽到蓝色方框上
source = driver.find_element(By.ID, "div1")
target = driver.find_element(By.ID, "div2")
# 实例化鼠标对象
action = ActionChains(driver)
# 调用鼠标拖动事件方法
action.drag_and_drop(source, target)
# 调用鼠标执行方法
action.perform()

# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()
1.5 鼠标悬停操作
  • 鼠标悬停实现步骤:
    • 实例化鼠标对象 action = ActionChains(driver)
    • 调用鼠标悬停事件方法 action.move_to_element(element) # element表示的是元素对象
    • 调用鼠标执行方法 action.perform()
# 导包
import time
from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 模拟鼠标悬停在‘注册’按钮上
element = driver.find_element(By.CSS_SELECTOR, "button")

# 创建鼠标对象
action = ActionChains(driver)
# 调用鼠标悬停事件方法
action.move_to_element(element)
# 调用鼠标执行方法
action.perform()

# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()
1.6 鼠标单元素拖动操作
  • 鼠标单元素拖动实现步骤
    • 创建鼠标对象 action=ActionChains(driver)
    • 调用鼠标单元素拖动事件方法 action.drag_and_drop_by_offset(element, x, y) x, y 表示的元素拖动时横向和纵向移动的距离,单位为像素, element表示的是元素对象 移动的像素最终要比在web页面中看到的移动像素值要大,最好大于5个像素或者10像素
    • 调用鼠标执行方法 action.perform()
# 导包
import time

from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E9%AA%8C%E8%AF%81%E7%A0%81/index.html")

# 模拟鼠标实现滑块验证码的操作
element = driver.find_element(By.CSS_SELECTOR, '.handler_bg')
# 创建鼠标对象
action = ActionChains(driver)
# 调用鼠标单元素拖动事件方法
action.drag_and_drop_by_offset(element, 265, 0)
# 调用鼠标执行方法
action.perform()

# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()

2、键盘操作
  • 模拟键盘上面的快捷键的操作

  • 调用键盘操作的快捷键的方法 element.send_keys(快捷键的键值)

    需要导入Keys类, 第一个字母是大写

    单键值: 直接传入对应的键值

    组合键: 键值之间由逗号分隔

    send_keys(Keys.CONTROL, Keys.SHIFT, ‘i’)

    常用的快捷键

    1. send_keys(Keys.BACK_SPACE) 删除键(BackSpace)
    2. send_keys(Keys.SPACE) 空格键(Space)
    3. send_keys(Keys.TAB) 制表键(Tab)
    4. send_keys(Keys.ESCAPE) 回退键(Esc)
    5. send_keys(Keys.ENTER) 回车键(Enter)
    6. send_keys(Keys.CONTROL,‘a’) 全选(Ctrl+A)
    7. send_keys(Keys.CONTROL,‘c’) 复制(Ctrl+C)
    8. send_keys(Keys.CONTROL, ‘v’) 粘贴
    # 导包
    import time
    
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver import ActionChains
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.keys import Keys
    
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    # 1). 输入用户名:admin1,暂停2秒,删除1
    element = driver.find_element(By.ID, 'userA')
    element.send_keys("admin1")
    time.sleep(2)
    element.send_keys(Keys.BACK_SPACE)  # 删除最后一个字符串 clear()
    # 2). 全选用户名:admin,暂停2秒
    element.send_keys(Keys.CONTROL, 'a')
    time.sleep(2)
    # 3). 复制用户名:admin,暂停2秒
    element.send_keys(Keys.CONTROL, 'c')
    time.sleep(2)
    # 4). 粘贴到密码框
    driver.find_element(By.ID, 'passwordA').send_keys(Keys.CONTROL, 'V')
    
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    
    

二、元素等待

HTML加载需要时间,影响HTML加载的因素:

  • 服务器性能
  • 网络速度
  • 本身电脑的配置
1、隐式等待

概念:首先要等待整个页面加载完成,再去进行元素定位,如果在定位过程中找到了元素,直接返回该元素,继续后面的操作,如果在指定的时间内没有找到该元素,那么每隔0.5秒再去找,如果超过了指定时间,就会抛出NoSuchElementException的异常错误。

隐式等待实现方式:

driver.implicitlty_wait(timeout) # timeout表示的是最长的等待时间 单位为S

隐式等待只需要设置一次,对所有的元素定位的方法都是有效的。

# 导包
import time

from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver.common.by import By
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(5)  # 隐式等待的时间,设置为5S
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 针对第一个延时框输入admin
print("开始时间:", time.strftime("%H:%M:%S"))
driver.find_element(By.XPATH, "//div[@id='wait']/input[1]").send_keys("admin")
print("找到第一个元素的时间:", time.strftime("%H:%M:%S"))
# 针对第二个延时框输入admin2
driver.find_element(By.XPATH, "//div[@id='wait']/input[2]").send_keys("admin2")
print("找到第二个元素的时间:", time.strftime("%H:%M:%S"))

# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()
2、显示等待

概念:定位指定元素时,如果能找到该元素,那么就直接返回该 元素,如果找不到,那么每隔指定的时间再去定位该 元素,如果超出最长等待时间,那么就抛出TimeOutException。

显示等待的实现:

WebDriverWait(driver, timeout, poll_frequency=0.5).until(lambda x:x.find_element(By.ID, “userA”))

WebDriverWait等待类需要导入

driver指的是浏览器驱动对象

timeout表示的是最长等待时间

poll_frequency表示的是检测的间隔时间,默认是0.5和

后面跟上until方法,在until方法跟上匿名函数来实现元素定位。

显示等待与隐式等待的区别:

1、抛出的异常不一样 , 隐式等待超时,报的NoSuchElementException ,显示等待超时,报的是 TimeOutException

2、作用域不一样, 隐式等待对所有元素定位的方法都有效,只需要定义一次, 显示等待只针对单个元素

3、显示等待不需要等待整个页面的HTML的DOM树加载完成,显式等待的效率更高,工作当中一般使用显示等待。而隐式等待需整个HTML DOM树加载完成。

# 导包
import time

from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.maximize_window()
# driver.implicitly_wait(5)  # 隐式等待的时间,设置为5S
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")

# 通过显示等待的方式定位延时输入框输入admin
element = WebDriverWait(driver, 9, 1).until(lambda x: x.find_element(By.XPATH, "//*[@id='wait']/input[1]"))
element.send_keys("admin")
# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()

3、强制等待
  • 强制等待就是让代码休眠,不做任何的操作

    time.sleep(time) 单位为time

  • 常用的场景:

    • 当要获取元素的文本内容时,而元素的文本内容是需要通过后台接口请求并渲染的,此时,如果使用隐式等待或显示等待是没有办法获取到文本内容,所以需要使用强制等待
    • 当要操作的元素已经存在,但是有其他的元素需要等待且与该操作的元素有业务关联,如果使用隐式等待或显示等待对该元素进行操作的话,是没有办法进行的,也需要使用强制等待。
# 导包
import time

from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(5)
driver.get("http://tpshop-test.itheima.net/")

# 先登录
driver.find_element(By.CSS_SELECTOR, '.red').click()
# 输入用户名密码等信息
driver.find_element(By.CSS_SELECTOR, "#username").send_keys("13012345678")
driver.find_element(By.CSS_SELECTOR, "#password").send_keys("12345678")
driver.find_element(By.CSS_SELECTOR, "#verify_code").send_keys("8888")
driver.find_element(By.CSS_SELECTOR, ".J-login-submit").click()

# 获取购物车中的商品数量
time.sleep(2)
print("购物车商品数量:", driver.find_element(By.CSS_SELECTOR, "#cart_quantity").text)

# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()


三、下拉选择框、弹出框、滚动条操作

1、下拉选择框操作
  • 下拉选 择实现步骤:

    1、导入Select类

    2、实例化select对象 select=Select(element) # element对象表示的是select元素对象

    3、通过select的相关方法选择option选项

    • select.select_by_index(index) 参数index表示的option索引
    • select.select_by_value(value) 参数value表示的是option元属中value的属性值
    • select.select_by_visible_text(visible_text ) 参数visible_text表示的是option的文本内容。
    # 导包
    import time
    
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.select import Select
    
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    element = driver.find_element(By.CSS_SELECTOR, "#selectA")
    select = Select(element)
    # 通过select对象的index来选择广州
    time.sleep(2)
    select.select_by_index(2)
    # 通过select对象的value来选择上海
    time.sleep(2)
    select.select_by_value("sh")
    # 通过select对象的visible来选择深圳
    time.sleep(2)
    select.select_by_visible_text("深圳")
    
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    
2、弹出框操作
  • 弹出框处理步骤:
    • driver.switch_to.alert 获取弹出框对象
    • 处理弹出框
      • alert.text 获取弹出框提示信息
      • alert.accept() 确定弹出框
      • alert.dismiss() 取消弹出框
# 导包
import time

from selenium import  webdriver
# 实例化浏览器驱动
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.maximize_window()
# 打开测试网站
driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
# 点击alert按钮
driver.find_element(By.ID, "alerta").click()
time.sleep(3)
# 处理弹出框
# 获取弹出框
alert = driver.switch_to.alert
# 打印信息,然后取消
print(alert.text)
alert.dismiss()
# 在用户名输入框中输入admin
driver.find_element(By.ID, 'userA').send_keys("admin")

# 等待3S
time.sleep(3)
# 退出浏览器驱动
driver.quit()
3、滚动条操作
  • 滚动实现步骤:

    • 控制滚动条到最下方

    • 1、定义js

    ​ js = “window.scrollTo(0, 2000)” # 如果想要移动到最下方,y值给最大值就可以了。

    • 2、执行JS

    ​ driver.execute_script(js)

    # 导包
    import time
    
    from selenium import  webdriver
    # 实例化浏览器驱动
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    driver.maximize_window()
    # 打开测试网站
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
    time.sleep(3)
    # 控制滚动条到最下方
    # 1、定义js
    js = "window.scrollTo(0, 2000)"
    # 2、执行JS
    driver.execute_script(js)
    
    # 等待3S
    time.sleep(3)
    # 退出浏览器驱动
    driver.quit()
    

四、frame切换、多窗口切换

1、frame切换
2、多窗口切换

今日目标(4)selenium提供frame切换、多窗口切换、窗口截图、验证码处理

  • selenium提供一下操作
    • frame切换、
    • 多窗口切换、
    • 窗口截图、
    • 验证码处理

一、frame切换、多窗口切换

1、frame切换
  • frame切换实现方法:
    • driver.switch_to.frame(frame_reference) --> 切换到指定frame的方法
      frame_reference:可以为frame框架的name、id或者定位到的frame元素
    • . driver.switch_to.default_content() --> 恢复默认页面方法

frame切换原理总结:

  • 针对同一层级的frame,如果要进行切换的话,需要切回到默认首页
  • 针对所要进入的frame, 有多少个层级,就需要切换几次
  • 不管当前在哪个层级,如果要回到默认首页,只需要调用一次回到默认首页的方法(driver.switch_to.default_content())

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbfDvZKA-1685181221110)(img/image-20200626101031448.png)]

import time

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)

driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8C%E5%AE%9E%E4%BE%8B.html")
# 针对主页的用户名输入admin
driver.find_element(By.ID, "userA").send_keys("admin")

# 针对注册用户a输入用户名adminA
driver.switch_to.frame(driver.find_element(By.ID, "idframe1"))
driver.find_element(By.ID, "AuserA").send_keys("adminA")

# 回到默认首页面
driver.switch_to.default_content()

# 针对注册用户B输入用户名adminB
ele_frame = driver.find_element(By.ID, "idframe2")
driver.switch_to.frame(ele_frame)
driver.find_element(By.ID, "BuserA").send_keys("adminB")

time.sleep(3)


driver.quit()
2、多窗口切换
  • 窗口操作的三种方法

    获取当前窗口句柄: driver.current_window_handle

    获取所有窗口句柄: driver.window_handles 返回的是一个列表

    切换窗口句柄: driver.switch_to.window(window_handle) window_handle表示的是要切换到哪个窗口句柄

    窗口句柄:由操作系统生成的一串唯 一识别码,是一串字符。

    import time
    
    from selenium import webdriver
    from selenium.webdriver.common.by import By
    
    driver = webdriver.Chrome()
    driver.maximize_window()
    driver.implicitly_wait(10)
    
    driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/page/%E6%B3%A8%E5%86%8C%E5%AE%9E%E4%BE%8B.html")
    
    # 在注册实例页面中点击  注册A页面
    driver.find_element(By.ID, "ZCA").click()
    time.sleep(1)
    # 获取当前窗口句柄信息
    print(driver.current_window_handle)
    
    # 获取所有窗口句柄
    windows = driver.window_handles
    
    # 切换窗口句柄
    driver.switch_to.window(windows[-1])
    
    # 在注册A页中输入用户名和密码
    driver.find_element(By.ID, "userA").send_keys("admin")
    
    
    time.sleep(3)
    
    driver.quit()
    

窗口切换与frame切换的区别: 窗口切换是指针对浏览器窗口, frame切换针对的是同一个窗口中的html代码。

窗口相当于是同一栋楼的一套房子,frame相当于一套房子中的某一间房子


二、窗口截图、验证码处理

1、窗口截图

  • 目的:当程序运行出错时,通过截图文件能够更直观的知道具体是哪个操作步骤出错

  • 窗口截图就是指把出错的图片保存到指定位置。

    载图方法: driver.get_screenshot_as_file(filename)

    • 截图的文件名必须是以PNG结尾
    • filename中的文件目录必须手动创建
import time

from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)

driver.get("file:///D:/software/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%B7%A5%E5%85%B7/web%E8%87%AA%E5%8A%A8%E5%8C%96%E5%B7%A5%E5%85%B7%E9%9B%86%E5%90%88/pagetest/%E6%B3%A8%E5%86%8CA.html")
try:
    # 输入用户名
    driver.find_element(By.ID, "userA").send_keys("admin")

# 输入密码
    driver.find_element(By.ID, "padd").send_keys("1234")
except Exception as e:
    driver.get_screenshot_as_file("img/error.png")
    raise e

time.sleep(3)
driver.quit()


2、验证码处理
2.1 什么是验证码?

验证码就是指一种随机生成的信息(数字、字母、汉字、图片、算术题)等为了防止恶意的请求行为,增加应用的
安全性。

自动化过程中也是需要进行注册或者登陆的操作,所以需要处理验证码。

2.2 验证码处理方式
  • 去掉验证码 由开发操作 , 用在测试环境
  • 设置万能验证码 由开发 操作, 一般也只使用在测试环境,
  • 验证码识别技术 由于技术难度高,识别率很难达到100%, 一般不建议使用
  • 记录COOKIE 通过记录cookie来跳过登陆的操作。
2.3 Cookie原理
  • 原理:
  1. Cookie是由Web服务器生成的,并且保存在用户浏览器上的小文本文件,它可以包含用户相关的信息。
  2. Cookie数据格式:键值对组成(python中的字典)
  3. Cookie产生:客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie
    数据
  4. Cookie使用:当浏览器再次请求该网站时,浏览器把请求的数据和Cookie数据一同提交给服务器,服务
    器检
    查该Cookie,以此来辨认用户状态。
2.4 selenium操作cookie
  • driver.get_cookie(name) 获取指名称的cookie信息 返回的是一个字典
  • driver.get_cookies() 获取的是所有cookie的信息, 返回的是一个列表
  • driver.add_cookie(dict_cookie) 往浏览器驱动增加cookie, dict_cookie是一字典

注意事项:如何确认哪个cookie是用来控制用户权限的

  • 可以问开发同学
  • 针对登陆的前后的cookie进行对比,比登陆之前多的cookie都可以用来使用控制用户权限。
  • 手动登陆之后不能退出,退出之后就相当于cookie无效了。

扩展知识点

1、解决注册用例可重复执行的问题?
  • 通过python代码编写一个生成手机号码的函数 (会生成比较多的垃圾数据)
  • 在注册之前,备份一处数据库(备份只需要做一次),执行注册的用例,每次执先完用例之后,再去恢复数据库(如果数据库数据量大,那么恢复的时间会比较久,效率比较低)
  • 通过python脚本直接在数据库删除新注的用户(要熟悉底层的数据库业务,要知道注册用户是存在哪些表中)
import random
import time

from selenium import webdriver
from selenium.webdriver.common.by import By


# 定义获取手机号码的函数名
def get_mobile():
    mobiles = ['130', '131', '134', '135']  # 确定手机号码所需要格式
    number = str(int(time.time()))[2:]  # 通过时间戳获取手机号码的后8位数(一定不会重复)
    mobile = random.choice(mobiles)+number  # 把手机号码格式的三位数与后8位数相加
    return mobile


driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)

driver.get("http://tpshop-test.itheima.net/Home/user/reg.html")

driver.find_element(By.ID,  "username").send_keys(get_mobile())
driver.find_element(By.NAME,  "verify_code").send_keys("8888")
driver.find_element(By.ID, "password").send_keys("123456")
driver.find_element(By.ID, "password2").send_keys("123456")
driver.find_element(By.CSS_SELECTOR, ".J_btn_agree").click()
time.sleep(10)
driver.quit()
2、文件上传
  • 安装()这个工具。autoit V3工具是用来查看windows窗口信息及控件信息的在这里插入图片描述

  • 安装pyautoit模块。在这里插入图片描述

    • 解压pyautoit-master.zip文件
    • 在windows窗口进入到解压目录之后,再在地址栏输入cmd
    • 执行以下命令 python setup.py install
import time

import autoit
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
driver.get("http://www.baidu.com")
# 点击百度上面的照相机按钮
driver.find_element(By.CSS_SELECTOR, ".soutu-btn").click()
# 点击选择文件
ele = driver.find_element(By.CSS_SELECTOR, ".upload-pic")
# 定义鼠标对象
action = ActionChains(driver)
# 调用鼠标事件
action.click(ele)
# 执行鼠标事件方法
action.perform()
time.sleep(2)
#  针对windows操作
# 通过autoit来获取弹出的窗口
autoit.win_wait_active("打开", 3)  # 3表示的是时间,秒为单位

# 在文件选择输入框中输入文件的地址及文件名称
autoit.control_send("打开", "Edit1", r"C:\Users\LiaoFei\Pictures\Saved Pictures\333.jpg")

# 在弹出窗口中点击打开按钮
autoit.control_click("打开", "Button1")

time.sleep(10)
driver.quit()

今日目标(5)app基础理论

在这里插入图片描述

一、app测试基础理论

1、app的应用架构
  • app属于CS架构,是通过HTTP协义来传输数据的。 通过json的格式来传送数据的。

2、app项目环境及发布平台
2.1 app项目环境介绍(后端服务器环境)
  • 开发环境 是给开发人员进行代码联调的。给开发进行自测的。
  • 测试环境 用来给测试人员进行测试用的。测试环境也可能分为手工测试环境和自动化测试环境的。
  • 预发布环境 当项目要上线时,做最后一轮的验收测试时,预发布环境的数据跟生产环境的数据是一致的。
  • 镜像环境 当生产环境出现问题时,把生产环镜的相关数据以及代码全部拉到镜像环境,复现生产上的问题,然后由测试人员协助开发人员复现问题,然后由开发人员去进行问题的定位和分析。
  • 生产环境 给用户或者是客户使用的环境 (生产环境测试人员不能随便操作,由运维人员管理的)
2.2 灰度发布介绍

所谓灰度发布,就是指在发布生产环境过程当,先发布其中几台服务器,如果这几台服务器功能运行一段时间后能够正常,那么再把其他未升级或者未发布的服务器进行生产环境发布,那如果说先发布的几台服务器运行有问题,那么就需要回滚到原来的版本。

2.3app项目发布平台
  • android 安卓app文件后缀名是 apk

  • IOS 苹果app文件后缀名是ipa

  • 获取app安装包文件的方式一:

    • anroid 可以直接找开发给对应apk安装包
    • IOS 直接将手机给开发人员,让开发人员安装对应的ipa包
  • 获取app安装包文件的方式二:

    • 可以借助内测试平台

      国内用的内测平台是蒲公英, 国外用的是fir.im

    • 测试包生成之后会上传到蒲公英平台,然后生成一个链接地址(二维码),可以直接通过二维码或者链接地址下载对应的测试包

  • 生产app安装包的获取

    anroid app安装包 豌豆荚、应用宝、360手机助手、各类手机品牌商城(上传app安装包需要审核 2-3 )

    ios app安装包 appstore itools(IOS时间更长,一周左右)


3、敏捷开发模型
3.1 敏捷开发模型介绍
  • 瀑布模型(传统行业)

    • 需求分析
    • 设计
    • 编码
    • 测试
    • 运行维护

    优点:

    1、为项目提供了按阶段划分检查点(文档)

    2、当前一阶段完成后,只需要关注后续阶段。

    缺点:

    1、在项目各介段之间极少有反馈,出现问题没法及时处理,灵活性差

    2、只有在项目结束交付上线时才能看到最终的结果

    3、需要太多的文档来驱动项目进行。影响项目的效率。

    结论:采用传统的瀑布模型最大的问题是开发的周期长,迭代的速度慢。

互联网行业特点:追求创新、以快吃慢、需求高度不确定性

互联网产品开发的特点:新需求、新方向

降低项目风险,确保正确的方向:快速的反馈机制、快速试错的流程 (针对需求不确定性)

敏捷开发:

概念:以用户的需求为核 心,采用迭代、循序渐近的方法进行软件开发

在敏捷开发过程当,软件项目在构建初期会被切分成不同的子系统以及不同的失代,各个子项目的成果经过测度,具备可视,可集成和可运行的特征。

3.2 Scrum介绍

概念:Scrum是一个敏捷开发框架,是一个增量的,迭代的开发过程。在这个框架中,整个开发周期包括若干个小的迭代
周期,每个小的迭代周期成为一个Sprint(sprint:项目开发过程中最小迭代周期),每个Sprint的周期建议为2~4
周。在Scrum中,将产品Backlog(产品待办列表)按商业价值排出需求列表。在每个迭代中开发团队从产品
Backlog挑选最有价值的需求进行开发,实现完成后产品推出市场,进入下一个迭代

需要熟悉的三个角色:

  • 产品负责人:收集产品需求,确定产品上线时间,排产品需求的优先级
  • 项目经理:带领团实现SCRUM敏捷过程,确保组内成员不被外界干扰,确保组内成员按时完成任务
  • 开发团队:程序员,测试员,设计(程序员分前端、后端、android开发、ios开发)
  • 每日立会: 需要知道每天干 了什么,明天计划干什么,以及遇到的问题。 一般早上开会,15分钟左右。 同时需要知道项目的进度是否正常

4、app应用测试流程
  • 参与需求评审 评审前一定要看需求文档
  • 制定测试计划 一般由测试负责人或测试主管制定
  • 设计编写测试用例 有一些小公司由人力时间紧张,可以不写用例,需要写测试点。用例评审
  • 执行用例,跟踪缺陷 搭建环境,冒烟测试(有可能做,也有可能不做)
  • 编写提交版本测试报告

二、学车不app测试

1、模拟器安装及使用介绍

在这里插入图片描述

  • 点击打开使用

2、app测试要点
  • 功能测试
  • 兼容性测试
  • 安装、卸载、升级测试
  • 交叉事件测试
  • PUSH测试
  • 性能测试
    • CPU
    • 内存
    • 流量
    • 电量
    • 流畅度
    • 启动速度
  • 用户体验测试
  • 稳定性测试
2、业务功能测试

根据测试功能去拆分功能点,再根据功能点去分析测试点。

一、专项测试

1、兼容性测试(专项)
  • 系统 1、android 2、IOS

  • 手机系统的版本 覆盖主流 https://tongji.baidu.com/research/app

    • android 对应的主流版本 9.0 \ 8.1 \10.0的版本
    • IOS 对应的主流版本 13.3.1 \ 13.4.1\ 13.3
  • 品牌-机型 覆盖主流 https://tongji.baidu.com/research/app

    • android 华为、小米、vivo
    • IOS 苹果
  • 屏幕分辨率 覆盖主流 https://tongji.baidu.com/research/app

  • 软硬件兼容性
    与手机硬件兼容
    home键、电源键、音量调节等
    与外部硬件设备兼容
    耳机、蓝牙等
    与操作系统软件兼容
    wlan设置、系统时间调节、LBS定位等
    与其他APP兼容
    后台在播放音乐时,进入动态页面点击动态视频的播放,系统如何处理

  • 网络兼容性 2G\3G\4G\5G\WIFI

    不可能去做全兼容的测试。

    可以去做深度兼容测试。需要借助于第三方云测试平台。testin云测,云测平台有很多手机。

    在云测平台注册账号,上传APP,给钱,拿 报告 。

2、安装卸载升级测试(专项)

app是一个客户端程序,客户端在使用前是需要安装的,因此需要测试安装、卸载、升级的操作

安装测试点:(只要大家能想到的点,都可以去进行测试,没有对错)

  • 正常场景:

1、在不同的操作系统、不同的手机品版和版本上安装

2、从不同的渠道下载app进行测试

3、不同的安装路径,安装在手机的内存卡或者是SD卡(非必要)

异常场景:

4、安装时出现异常(关机、断网),恢复后能否继续安装

5、安装时存储空间不够或者内存不足

6、安装时点出取消再安装

7、安装之后再次覆盖安装

8、低版本覆盖安装高版本

  • 卸载

    正常卸载:长按app正常删除卸载、通过第三方工具进行卸载

    异常卸载:app正在运行卸载、取消卸载、卸载关机、卸载之后数据是否保留

  • 升级

    正常升级: 从低版本升级到高版本,从app内部升级, 从app应用商城升级

    异常升级:跨版本升级, 关机,内存不足,电量不足

    升级提示

    升级之后数据的检查


3、交叉测试

概念:交叉测试又称为冲突测试,或者干 扰测试

交叉事件的关注点:

1、app运行时接打电话

2、app运行时收发短信

3、app运行时收到推送通知

4、app运行时接到视频通话

5、app运行连接蓝牙

6、app运行时切换网络、切换应用

7、app运行时旋转屏幕


4、push消息测试
  • 消息推送的场景:
    • 新闻资讯类通知, 让用户实时获取到自己感兴趣的新闻,从而增加用户的粘性
    • 商城类通知, 让用户获取到商城的促销活动,提高用户的成交率
    • 流程类的通知, 让用户及时获取处理工作的内容。
  • 推送原理: 是由服务器通过推送的服务将对应的消息推送到app端。 是一个长连接的状态。
  • 推送服务器: 使用的是第三方的推送服务器。(极光或者信鸽)
  • 手机厂商会自己的推送服务器。
  • 中小企业不会自己搭建推送服务器,一般使用的都是第三方的推送服务器
  • push消息推送的关注点
    • PUSH消息推送是否按指业务规则发送.
    • 当PUSH推送时,检查是否按特定用户去进行推送.
    • 设置不接收推送消息时,确认是否正常
    • 推送通知的跳转是否正常
    • 推送消息的打开及展示
    • 包括app是否运行,都需要去关注推送消息能否收到。

3、性能测试

1、打开USB调式, 点击“系统应用”–“设置”, 在设置 的最下方选择“关于平板电脑”,在关于平板电脑中点击“版本号”,直接提示开发者选项已打开。

2、返回到设置 菜单页面时,可以 看到 “开发者选项”这个菜单。点击进入到开发者选项, 需要打开 USB调试 以及指针位置 这两个选项。

3、开启超级管理员访问权限

  • 点击“系统应用”–“文件管理器”, 在文件管理器的左上方有三横杆的按钮,在弹出的页面中点击左下方的 齿轮 按钮,进入到设置页面之后,选择 “常规设置”—“访问模式”,将访问模式更改为超级管理员访问模式。
3.1 性能工具介绍及安装 GT工具

GT随身调 android版是由腾讯公司开发的性能测试平台。直接运行在手机上面的。

可以通过GT工具进行基础的性能测试:内存、CPU、电量、网络流量、流畅度,可以以绘制图表的形式显示出指标的相关数据

GT工具提供了查看日志的功能。可以通过查看相关日志来分析和定位app功能异常以及crash等问题

  • 安装
    • 拖动到模拟器中在这里插入图片描述
3.2 性能工具使用
  • 打开GT工具,在AUT界面选择被测试的app以及对应的性能指标

  • 设置参数,进入到参数页面,点击右上角的"编辑"按钮,拖动想要测试的参数到已关注区域,而且要勾选。

    勾选之后,点击上方的红色 录制按钮。

  • 执行测试之前,进入到日志界面,开启logcat的日志记录功能。

  • 如果要进行电量或流量的性能测试需要进入到插件页面进行设置。

  • 返回到AUT界面,在上面点击“启动”或者“running” 来启动被测试的app

  • 针对app进行相关的业务操作

  • 操作完成之后,再进入到GT工具,查看性能参数的数据。

3.3 CPU测试

GT工具提供了两个CPU的监控指标:CPU和jiffes

CPU指标就是指当前手机中cpu的整体使用率

用户态:cpu处于应用程序执行的时间

系统态:表示的是系统内核执行的时间

空闲态:表示空闲系统进程执行的时间

cpu使用率 = cpu空闲态/cpu的总的执行时间

jiffief:

表示的是开机以来,程序消耗的CPU时间片的总数

CPU问题的影响:

1、CPU使用长时间处于90%以上 (70 80 )

2、手机发热、耗电量增加

3、反应变慢,引起ANR(假死状态)

操作步骤:

1、打开GT工具,进入到AUT页面,选择测试的app,勾选CPU性能指标

2、进入到参数界面,配置CPU参数选项,然后进行勾先,点击录制

3、进入到日志界面,打开logcat记录日志

4、返回到AUT界面,启动app

5、针对app进行相关的业务操作(实际工作当中,操作时间会比较长)

6、返回到GT工具界面,查看相关的参数数据。

3.4 内存测试

PSS和private dirty

private dirty(私有内存):

进程独占的内存,也就是进程销毁时可以回收的内存容量.

PSS(实际使用内存):

将跨进程的共享内存也加入进来,进行按比列计算PSS。就能够准确的表示进程占用的实际物理内存。

常见问题:

1、内存泄漏

内存泄漏(memory leak):当程序运行时申请了对应的内存空间,而当程序销毁时并没有释放对应的内存空间。

2、内存溢出

内存溢出 (out of memory):是指程序在申请内存空间时,没有足够的内存空间供其使用。

  • 内存问题产生的影响

    1、程序实际使用的内存PSS会不停的增长

    2、程序会出现闪退(crash)

内存的指标根据不同的手机配置、以及不同的公司,指标值是不一样的。

  • 内存操作步骤:
    • 打开GT工具,选择对应的被测app, 勾选内存指标(PSS和private dirty)
    • 进入到参数界面,编辑参数,勾选对应参数,并点击录制按钮
    • 进入到日志界面,开启logcat,记录日志信息
    • 回到AUT界面,点击 启动按钮,启动被测试的app
    • 针对启动的app进行相关的业务功能操作(时间一般也会在几个小时左右。)
    • 操作完成,回到GT工具的参数界面,查看获取到的参数数据。

今日目标(6)app自动化测试介绍、自动化环境搭建、adb工具、adb命令

3.5 流畅度测试

GT工具提供了流畅度的监控指标:FPS

FPS是指人的肉眼能够看到的画面每一秒帧数

效果:想要达到流畅的效果,至少每秒的帧数要达到24帧

每秒和帧数越高流畅度就越好

如果想要达到最佳的流畅度需要达到每秒60帧

当页面静止不动时,FPS的值显示的是0

测试时间:15-30分钟

操作步骤:

1、打开GT工具,进入到AUT界面,选择被测试的app

2、进入到参数界面,点击编辑拖动FPS参数到已关注参数中,勾选之后,点击录制

3、进入到日志界面,开启logcat记录日志信息

4、返回到AUT界面,点击启动,打开被测试的app

5、针对被测app进行相关的业务操作

6、返回到参数界面查看参数数据

3.6 流量测试

GT工具里面提供了一个监控流量的指标:NET

流量:手机在访问网络过程当所产生的上传和下载的数据(报文)就称为流量

  • 常用流量测试方法

    • 抓包测试法

      通过抓包工具将所有的网络应用数据包,全部抓取到并保存到某个文件中,进行分析的过程 。

      wireshark所有协议的报文,sniffer也可以抓所有的报文,tcpdump命令可以抓所有的报文

    • 统计测试法

      获取的是某一个应用程序获取的数据报文,统计出对应的流量。

  • GT工具测试步骤:

    • 打开GT进入到AUT界面,选择被测试的app,勾选NET指标
    • 进入到参数界面,点击编辑,拖选 NET参数,勾选并点击录制
    • 进入到日志界面,开启Logcat记录日志信息
    • 进入到插件界面,选择“抓包”,再点击“开始”
    • 返回到AUT界面,点击“启动”,启动测试app
    • 针对启动的app进行相关业务操作
    • 返回到参数界面,停止录制,再返回到插件界面,点击“抓包”,再点“停止”

流量的优化:

  • 数据压缩 在HTTP协议中可以通过此字段将数据进行压缩,减少数据容量。content-encoding: gzip
  • 不同的数据格式的采用 json lxml 数据格式
  • 控制访问的频次 通过异步加载的方式来加载数据。
  • 只获取必要的数据
  • 缓存机制
  • 懒加载 将多个图片放在同一张图片里面,一起加载。
3.7 电量测试

GT工具当中提供了电量的监控指标:电流、电压,电量跟温度

就是指移动设备电量消耗快慢的一种测试方法。一般用平均电流来衡量电量的消耗速度。

常见的耗电场景:

定位,GPS

网络传输

蓝牙

屏幕的亮度

GT工具只能特定类型的机型进行电量的测试。

可换其他性能测试工具进测试,也可以使用对比方式进行测试(拿 同类型的产品,在同样的手同样的场景下进行对比测试。)

3.8 用户体验测试

用户体验主要是跟app的界面有关。

  • UI界面测试 包括界面的设计、界面元素框架、结构、颜色、布局、图片、按钮选中的一些效、文字的内容。
  • 易用性测试 菜单的层次、完成业务操作的步骤是否过多, 点击按钮的范围 是不是合适,包括返回键的操作
  • 横竖屏测试 横屏之后,页在的表格是不是能正常的显示。
  • 关注手机上的其他辅助功能 放大字体

二、app测试总结

如何测试app?

首先了解需求。

测试的过程 :

  • 测试功能
  • 兼容性测试
  • 安装、卸载、升级测试
  • 交叉事件测试
  • 用户体验测试
  • PUSH测试
  • 性能测试(CPU、内存、电量、流量、流畅度、启动时间)
  • 稳定性测试

当对app进行了充分

的测试之后,主可以编写测试报告 ,发布app到线上了。

app的发布,打包上传到各大应用商城。

测试人员也需要关注,关注的是app线上的BUG。

运维需要关注的app的线上环境


一、app自动化框架介绍

1、常用自动化框架介绍
  • Robtium

    基于anroid的一款开源自动化测试框 架

    支持java语言

    不支持跨平台

  • macaca

    由阿里巴巴公开开发的一套开源自动化解决方案

    适用平台:PC端、android、IOS

    支持的语言:java、python、nodejs

  • Appium

    是一款国外开源的自动化测试框架

    适用平台:android、IOS

    支持的语言:java\js\php\python\C#\ruby

    社区活跃、资料丰富

  • appium的特点:

    • 开源

    • 支持Native App(全部android sdk的java代码生成) 原生的app如果页面有变更,就得发一版本,提交到应用商城去审核

      Web App(都是由HTML5生成的) 访问速度慢。H5的代码以及元素信息

      Hybird APP(既有native app也有H5的页面)混合app 是当前工作中用得最多的

    • 支持andorid 、IOS

    • 支持跨平台、支持windows、linux、macos

    • 支持多语言 java js python C# ruby

2、appium介绍
2.1 appium自动化框架特点
2.2 appium自动化原理

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1YUbx4gG-1685203165249)(ui自动化测试day06/image-20200628120246352.png)]

通过此图可以知道app的自动化环境需要以下工具:

  • appium服务器
  • 基于python的appium客户端(appium-client-python)
  • adb(adb集成在android-sdk中)
  • JDK

一、自动化测试环境搭建

1、java安装

双击可执行文件,安装过程中建议不要将安装目录设置在含有中文的目录。建议不要发装在系统盘中。

验证: 在DOS命令行中输入 java -version 如果能看下图所显示的信息就是正确的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-G2b4TyPe-1685203165250)(ui自动化测试day06/image-20200628140337684.png)]

2、android SDK安装
2.1 androidSDK安装

下载链接: https://android-sdk.en.softonic.com/?ex=MOB-593.7

  • 安装步骤:

    • 解压android-sdk的压缩包文件
    • 将解压的目录复制到某一个文件夹下,文件夹的路径也不要包含 中文
    • 添加相应的环境变量(以下三个目录)
      • D:\Program Files\android-sdk\tools uiautomatorviewer.bat工具可以用来查看app的元素信息
      • D:\Program Files\android-sdk\platform-tools adb.exe 此工具用来连接手机
      • D:\Program Files\android-sdk\build-tools\25.0.0 aapt.exe 可以获取app的包名和启动名
  • 验证:

    1、在DOS命令行中输入 uiautomatorviewer 如果能显示以下图片,就说明是正常的。

    在这里插入图片描述

    2、在DOS命令行中输入: adb ,如果 能出现以下图片,就说明是正常.

在这里插入图片描述

3、在DOS命令行中输入: aapt , 如果能出现发下图片,就说明是正常的

在这里插入图片描述

3、模拟器安装(略过)
4、appium服务器安装
4.1 appium安装
  • 双击appium服务器的可执行文件,默认安装在C盘。
4.2 appium验证
  • 启动服务之前,需要先配置jdk以及android-sdk的目录。

在这里插入图片描述

  • 启动服务,如果能看到以下图片信息,说明安装正常

5、appium-client-python安装
  • 安装方式
    • 离线 解压对应的安装包文件,进到解压目录下执行 python setup.py install
    • 在线 pip install Appium-Python-Client
    • pycharm
  • 验证是否安装
    • pip show Appium-Python-Client
    • pycharm

二、adb工具

1、adb工具构成及原理
  • adb 包含 了三个部分
    • adb 客户端 用来下发adb的指令工具
    • Server 服务端 adb.exe执行之后的进程,表示adb的服务端,通过服务端与手机上的adb守护进程进行 通信
    • adb守护进程 随着android系统的启动而启动,当android系统关闭之后它才会关闭。

2、adb常用命令
2.1 adb常用命令(常看设备、启动关闭adb服务)

如果是真机,不要 使用一带多接头的数据线,否则找不到手机设备

  • adb devices 常看手机的设备ID名称以及状态

    emulator-5554 device emulator-5554表示的是手机设备的ID名称, device表示设备处于在线状态,

    如果不在线显示的是offline 如果adb服务没有启动,下发该命令时,会自动的去启动adb的服务

  • adb start-server 启动adb服务

  • adb kill-server 关闭adb 服务

2.2 获取包名和界面名
  • 包名: app包名 ,通过app的包名来区分不同的app,app包名是唯 一的
  • 界面名(启动名): 相当于web页面当中的链接地址,在app当中,每个界面都有一个名字

原因:自动化过程当,需要通过app的包名和界面名来启动app。

  • 操作步骤: adb命令

    • 在手机或者模拟器上面打开app

    • windows命令一:adb shell dumpsys window windows | findstr mFocusedApp

    • windows命令二: adb shell dumpsys window |findstr “usedApp”

      com.android.settings/.Settings com.android.settings是包名, .Settings是界面名 通过 / 分隔包名和界面名

      LINUX/MacOS命令一: adb shell dumpsys window windows | grep mFocusedApp

      LINUX/MacOS命令二: adb shell dumpsys window |grep “usedApp”

  • 通过aapt获取app的包名和界面名

    • aapt dump badging D:\BaiduNetdiskDownload\apptools\apk\xuechebu.apk 后面表示的是app安装包的路径及名称

      包名: package: name=‘com.bjcsxq.chat.carfriend’ # package:name 后面的字符串表示的是app的包名

      界面名: launchable-activity: name=‘com.bjcsxq.chat.carfriend.module_main.activity.SplashActivity’ launchable-activity: name后面的字符串是界面

2.3 安装卸载app
  • app安装 adb install 路径/app安装包名称

  • app卸载 adb uninstall 包名

2.4 上传下载文件
  • 上传 将电脑上的文件上传到手机

    adb push 电脑上的文件路径 手机的路径

    例子:adb push ./monkey.txt /sdcard

  • 下载文件 从手机上下载文件到本地

    adb pull 手机的文件路径 电脑的文件夹路径

    例子:adb pull /sdcard/monkey.txt D:\opt

2.5 查看日志信息

为什么要获取日志信息:用来给开发定位问题。

adb logcat 来查看相关的日志信息

2.6 测试app的启动速度(性能测试)
  • 测试app启动速度的命令:

    adb shell am start -W 包名/界面名

    Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.baidu.homework/.activity.user.passport.ChoiceLoginModeActivity }
    Status: ok
    Activity: com.baidu.homework/.activity.user.passport.ChoiceLoginModeActivity
    ThisTime: 3345
    TotalTime: 3345
    WaitTime: 3378

  • 需要大家关注的是TotalTImie的时间值,那么在实际的测试过程当,会进行多次测试,然后取平均值。


3、稳定性测试 (8小时)
  • monkey 集成在adb工具当中,主要用来做稳定性测试用的, monkey是通过java语言编写的一种稳定性测试工具。

    主要用来测试app会不会出现crash(崩溃)的情况。

    相当于让一只猴子来随机操作app,所有的操作都有可能出现,长时间的操作来测试app会不会出现问题。

  • monkey常用的参数

    • -p 参数 对指定的app进行随机操作

    adb shell monkey -p com.baidu.homework 100 (100次随机事件)

    • -v 参数 表示的是记录信息的级别

      level 0:adb shell monkey -p com.baidu.homework -v 100 默认级别

      level 1: adb shell monkey -p com.baidu.homework -v -v 100 打印出来的信息会比较详细,只打印跟本程序相关的日志信息

      level 2: adb shell monkey -p com.baidu.homework -v -v -v 100 打印出来的信息会更多,会显示出其他程序运行的信息

    • -s 用于指定伪随机数。如果两次的伪随机数相同,那么两次的操作步骤、流程、操作事件完全一样。

      主要的作用,就是用来复现上次的问题

      adb shell monkey -p com.baidu.homework -v -v -s 10 100

    • –throttle 用于指定随机事件的间隔时间, 单位是毫秒

      adb shell monkey -p com.baidu.homework -v -v --throttle 3000 -s 10 100

    组合使用:

    adb shell monkey -p com.baidu.homework --throttle 500 --pct–touch 10 --pct-motion 50 -v -v -s 100 300> log.log

    –pct–touch 10 触模(10表示的是整个随机同件中的百分比)

    –pct-motion 50 滑屏(50表示的是整个随机同件中的百分比)

  • 日志分析

    如果在日志里面出现了 ANR(application not responsing)

    如果日志中出现了Exception,可能程序崩溃。

    在这里插入图片描述

adb 操作命令
  • 手势操作命令

    • 模拟点击事件

      adb shell input tap x y # x y表示的是坐标点 参数之间用空格隔开

    • 模拟滑屏事件(参数之间用空格隔开)

      adb shell input swipe startx starty endx endy # startx, starty 表示的是起始点坐标,endx,endy表示的是终点坐标

    • 模拟键盘操作

      adb shell input keyevent 键值 (3 表示的HOME键 4 表示的返回键 66表示的回车键)

    • 模拟输入操作

      adb shell input text 内容 内容表示要输入的内容,另外输入的内容不能是中文

    • 在这里插入图片描述

      如果出现上图中 offline的设备,记得重启一下adb服务

    • 如果电脑上面连接了多个模拟器或者是手机。那么需要加上一个参数 -s device_name

      adb -s emulator-5554 shell input keyevent 4

1、弱网测试
  • 弱网测试步骤:

    • 打开fiddler,设置相应的代理端口(当端口被占用时需要手动更改代理端口)

    • 在fiddler中设置网络的上传和下载的速度

      • 点击 “rules”–“customize rules”
    • 在这里插入图片描述

      在这里插入图片描述

    • 在手机中设置网络的代理

      • 手机的IP地址必须与fiddler电脑的IP地址,是同一个局域 网。也就是在同一网段。

        查看电脑的IP地址命令: ipconfig

今日目标(7)uiautometorview工具使用、appium基础操作、元素定位、元素操作

  • uiautometorview工具使用、
  • appium基础操作、
  • 元素定位、
  • 元素操作

一、入门示例

在这里插入图片描述

# 导入webdriver
import time

from appium import webdriver
# 初始化app的配置信息
des_cap = dict()  # 定义字典参数

des_cap["platformName"] = "android"   # 表示的是android 或者IOS系统
des_cap["platformVersion"] = "5.1.1"  # 表示的是平台系统的版本号
des_cap["deviceName"] = "****"  # 表示的是设备的ID名称(如果只有一个设备可以用****来替代)
des_cap["appPackage"] = "com.android.settings"  # 表示的是app的包名
des_cap["appActivity"] = ".Settings"  # 表示的是app的界面名

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

time.sleep(6)

driver.quit()

二、uiautometorview工具使用

  • 通过uiautomatorviewer工具可以查看app的元素信息。

    查看元素信息:

    在这里插入图片描述

  • 如果出现如下错误:

在这里插入图片描述

需要重启adb服务。获取app页面信息时不能正在运行代码,会占用adb服务。

为了提高效率,在android sdk的 tools目录下,将uiautomatorviewer.bat复制一份出来,并修改为ui.bat就OK了。

后续直接在dos中输入ui就可以打开了

三、appium基础操作

1、通过appium启动app
  • driver.start_activity(“包名”,”界面名“)

    driver.start_activity("com.baidu.homework", ".activity.user.passport.ChoiceLoginModeActivity")
    
    
2、获取包名和界面名

​ driver.current_package 获取当前脚本运行中的app的包名

​ driver.current_activity 获取当前脚本运行中的app的界面名

3、关闭app及关才驱动
  • 关闭app driver.close_app() 不需要跟参数
  • 关闭驱动 driver.quit()

区别:

关闭app之后,可以再使用其他代码启动新的app

关闭驱动,那么代码与appium服务器之间的连接已经断,开不能再做任何的操作。

4、安装卸载app以及判断是否安装app
  • 安装app driver.install _app(apk路径)
  • 卸载app driver.remove_app(app包名)
# 导入webdriver
import time

from appium import webdriver
# 初始化app的配置信息
des_cap = dict()  # 定义字典参数

des_cap["platformName"] = "android"   # 表示的是android 或者IOS系统
des_cap["platformVersion"] = "5.1.1"  # 表示的是平台系统的版本号
des_cap["deviceName"] = "****"  # 表示的是设备的ID名称(如果只有一个设备可以用****来替代)
des_cap["appPackage"] = "com.android.settings"  # 表示的是app的包名
des_cap["appActivity"] = ".Settings"  # 表示的是app的界面名

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)
driver.close_app()
time.sleep(2)
# 安装263app
# driver.install_app(r"D:\BaiduNetdiskDownload\apptools\apk\263.apk")

# 卸载263app
driver.remove_app("com.em.mobile")
time.sleep(6)
driver.quit()

  • 判断手机是否安装app driver.is_app_installed(“包名”)

    返回值:True 有安装app 或者False 没有安装app

5、将应用置于后台运行

driver.background_app(seconds) # seconds 表示的是将app置于后台运行多少秒的时间

四、元素定位

1、定位单个元素
1.1 通过ID定位元素

​ 通过元素的resource-id来进行元素定位

​ driver.find_element_by_id(resource_id的值)

1.2 通过class_name定位元素

​ 通过元素的class属性值来进行元素定位

​ app中,class的值始终都只有一个。

​ driver.find_element_by_class_name(class)

1.3 通过xpath定位元素

​ 通过xpath的元素属性来进行元素定位

driver.find_element_by_xpath(“//*[@text=‘value’]”)

单个元素定位不到会报错。

# 导入webdriver
import time

from appium import webdriver
# 初始化app的配置信息
from selenium.webdriver.common.by import By

des_cap = dict()  # 定义字典参数

des_cap["platformName"] = "android"   # 表示的是android 或者IOS系统
des_cap["platformVersion"] = "5.1.1"  # 表示的是平台系统的版本号
des_cap["deviceName"] = "****"  # 表示的是设备的ID名称(如果只有一个设备可以用****来替代)
des_cap["appPackage"] = "com.android.settings"  # 表示的是app的包名
des_cap["appActivity"] = ".Settings"  # 表示的是app的界面名

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)
# 找到“更多”按钮并点击(XPATH)
element = driver.find_element(By.XPATH, "//*[@text='更多']")
element.click()
time.sleep(2)
# 找到 飞行模式的 开关,并点击(ID)
air_element = driver.find_element(By.ID, "android:id/switchWidget")
air_element.click()
time.sleep(2)
# 找到返回按钮并点击(class)
return_element = driver.find_element(By.CLASS_NAME, "android.widget.ImageButton")
return_element.click()
time.sleep(3)
driver.quit()

通过显示等待定位元素

from selenium.webdriver.support.wait import WebDriverWait
# 定义一个获取元素的方法


# def get_element(driver, find_type, value):
#     wait = WebDriverWait(driver, 10, 1)
#     element = wait.until(lambda x: x.find_element(find_type, value))
#     return element

def get_element(driver, element):
    wait = WebDriverWait(driver, 10, 1)
    element = wait.until(lambda x: x.find_element(element[0], element[1]))
    return element
2、定位一组元素

driver.find_elements_by_id(resource_id)

​ driver.find_elements_by_class_name(class_name)

​ driver.find_elements_by_xpath(xpath)

​ driver.find_elements(By.ID, value)

返回的值是一个列表,如果没有找到,说明列表是空值,可以通过下标来使用其中的元素对象,下标是从0开始。

五、元素操作

1、点击操作
element.click()    针对元素进行点击操作
2、清空和输入操作

​ element.clear() 针对元素进行清空操作

​ element.send_keys(“value”) 针对元素进行输入操作

3、输入的封装
#  为了保证代码的健壮性,确定输入的内容一定不会出错,所以在输入前做了一次清除。
def input_text(element, text):
    """
    :param element:  表示的是元素对象
    :param text: 表示的是要输入的内容
    :return:
    """
    # 清除元素中的文本内容
    element.clear()
    # 输入文本内容
    element.send_keys(text)
4、获取元素的信息
  • 获取元素的文本内容(获取的是元素text属性的内容)

    element.text

  • 获取元素的位置

    element.location 返回的值是一个字典,字典中包含x和y , x和y表示的是元素在手机屏幕左上角的点的坐标

  • 获取取元素的大小

    element.size 返回值是一个字典,字典中会包含 width和height, width表示的宽度,height表示的高度

  • 获取元素的属性值

    element.get_attribute(“attribute”) # attribute表示的是属性名称

    获取ID值时, attribute= “resourceId”

    获取的是class的值 , attribute=“className”

    如果attribute = "name"时,获取的是text或者content-desc(text优先,找不到text值,再去找content-desc的值)

# 导入webdriver
import time

from appium import webdriver
# 初始化app的配置信息
from selenium.webdriver.common.by import By

from utils import get_element

des_cap = dict()  # 定义字典参数

des_cap["platformName"] = "android"   # 表示的是android 或者IOS系统
des_cap["platformVersion"] = "5.1.1"  # 表示的是平台系统的版本号
des_cap["deviceName"] = "****"  # 表示的是设备的ID名称(如果只有一个设备可以用****来替代)
des_cap["appPackage"] = "com.android.settings"  # 表示的是app的包名
des_cap["appActivity"] = ".Settings"  # 表示的是app的界面名

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)
# 找到wlan 元素
wlan_btn = By.ID, "com.android.settings:id/title"
element = get_element(driver, wlan_btn)
# 获取wlan菜单的文本内容
print(element.text)

# 获取wlan的位置信息
print(element.location)

# 获取wlan元素的大小
print(element.size)

# 获取wlan元素
print(element.get_attribute("className"))

time.sleep(6)

driver.quit()

今日目标(8) 元素操作:获取手机操作、滑动和拖拽事件、高级手势操作

  • 元素操作:
    • 获取手机操作、
    • 滑动和拖拽事件、
    • 高级手势操作
初始化:输入中文的处理

在初始化配置中增加两个参数:

"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
from selenium.webdriver.support.wait import WebDriverWait
# 定义一个获取元素的方法


# def get_element(driver, find_type, value):
#     wait = WebDriverWait(driver, 10, 1)
#     element = wait.until(lambda x: x.find_element(find_type, value))
#     return element
# 减少代码量,不必要在每个元素定位的代码中都使用显示等待来定位。
def get_element(driver, element):   # element 表示的元素定位的值
    wait = WebDriverWait(driver, 10, 1)
    element = wait.until(lambda x: x.find_element(element[0], element[1]))
    return element


# 判断元素是否存
def element_is_exsit(driver, element):   # element 表示的元素定位的值
    try:  # 捕获异常信息
        get_element(driver, element)    # 能够正常找元素,就返回True
        return True
    except Exception as e:   # 如果捕获到了异常,返回False
        return False


#  为了保证代码的健壮性,确定输入的内容一定不会出错,所以在输入前做了一次清除。
def input_text(element, text):
    """
    :param element:  表示的是元素对象
    :param text: 表示的是要输入的内容
    :return:
    """
    # 清除元素中的文本内容
    element.clear()
    # 输入文本内容
    element.send_keys(text)
初始化:区分首次打开还是非首次打开
"noReset": True  # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
# 导入webdriver
import time
from appium import webdriver
# 初始化app的配置信息
from selenium.webdriver.common.by import By

from utils import get_element, input_text, element_is_exsit

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.bjcsxq.chat.carfriend",   #表示app的包名
"appActivity" :  ".module_main.activity.SplashActivity",      #表示的是app的界面名
"noReset": True  # 用来记住app的session,如果有登陆或做过初始化的操作,为True时,后面不需要再操作
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub",des_cap)

agree_btn = By.XPATH, "//*[@text='同意并继续使用APP']"

# 通过同意协议来判断app是否是首次打开
if element_is_exsit(driver, agree_btn):
    get_element(driver, agree_btn).click()
else:
    print("非首次打开")

# 点击“我的”
me_element = By.ID,"com.bjcsxq.chat.carfriend:id/mine_layout"
get_element(driver, me_element).click()
# 登录
login_element = By.ID, "com.bjcsxq.chat.carfriend:id/mine_username_tv"
get_element(driver, login_element).click()
# 输入手机号
tel_element = By.ID, "com.bjcsxq.chat.carfriend:id/login_phone_et"
input_text(get_element(driver, tel_element), "13751113926")
# 输入密码
password_element = By.ID, "com.bjcsxq.chat.carfriend:id/login_pwd_et"
input_text(get_element(driver, password_element), "a123456b")
# 点击登录
insert_element = By.ID, "com.bjcsxq.chat.carfriend:id/login_btn"
get_element(driver, insert_element).click()
# 点击确定
accept_element = By.CLASS_NAME, "android.widget.Button"
get_element(driver, accept_element).click()
# 点击“驾照圈”
licence_btn = By.ID, "com.bjcsxq.chat.carfriend:id/apply_layout"
get_element(driver, licence_btn).click()
# 选择第一条评论
pl_element = By.ID, "com.bjcsxq.chat.carfriend:id/tv_post_replay"
get_element(driver, pl_element).click()
# 填写评论内容
nr_element = By.XPATH, "//*[@text='发布评论']"
input_text(get_element(driver, nr_element), "test")
# 进行发布
fb_element = By.CLASS_NAME, "android.widget.TextView"
get_element(driver, fb_element)
time.sleep(3)
driver.quit()

一、获取手机操作

1、获取手机分辨率

保证脚本在不同机型上都能实现滑屏的操作。

driver.get_window_size() 返回的值是字典类型, 包含 height 和 width 高度和宽度的值

2、获取手机截图

driver.get_screenshot_as_file(filename)

注意事项:1、路径必须手动创建 2、文件名称必须是以PNG结尾

import time

from appium import webdriver
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub",des_cap)

# 获取手机屏幕分辨率
print(driver.get_window_size())

# 截图
driver.get_screenshot_as_file("img/error.png")

time.sleep(2)
driver.quit()
3、获取设置手机网络

主要是为了实现视频类的app中,视频播放过程中网络切换时会有提示信息的操作。

3.1 获取手机网络

driver.network_connection

appium定义的网络类型
在这里插入图片描述

3.2 设置手机网络

driver.set_network_connection(connectionType) # connectionType 网络类型的值

import time

from appium import webdriver
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub",des_cap)

# 获取网络类型
print(driver.network_connection)

# 设置网络类型
driver.set_network_connection(4)

print(driver.network_connection)
time.sleep(2)
driver.quit()
4、模拟键盘操作

常用的三个键值: 3 HOME键, 4 返回键 , 66 回车键

driver.press_keycode(键值)

5、手机通知栏操作

driver.open_notifications()

import time

from appium import webdriver
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub",des_cap)

#  打开通知栏
driver.open_notifications()

# 模拟返回键
driver.press_keycode(4)

time.sleep(2)
driver.quit()


二、滑动和拖拽事件

1、swipe滑动事件

driver.swipe(startx, starty, endx, endy, duration=None)

  • duration用来降低滑屏的速度及惯性, 单位是ms
2、swipe滑动事件封装
# 封装滑屏操作方法
def execute_swipe(driver, fx, count=1):
    w = driver.get_window_size()["width"]  # 获取手机屏幕的宽度
    h = driver.get_window_size()["height"] # 获取手机屏幕的高度
    # w=1080  h=1920
    if fx == "top":  # 往上滑
        zb = (w/2, h*0.9, w/2, h*0.1)
    elif fx == "down":  # 往下滑
        zb = (w/2, h*0.1, w/2, h*0.9)
    elif fx == 'left':  # 往左滑
        zb = (w*0.9, h/2, w*0.1, h/2)
    else:  # 往右滑
        zb = (w*0.1, h/2, w*0.9, h/2)
    for i in range(count):
        driver.swipe(*zb, duration=1200)
        time.sleep(1)
3、swipe边滑动边查找封装

针对频道类的元素进行滑动选择对应的频道。

# 封装一个边滑动边查找的方法
def swipe_find(driver, element, element_info):
    ele_size = element.size  # 获取元素大小
    width = ele_size["width"]  # 获取元素的宽度
    height = ele_size["height"]  # 获取元素的高度
    # 获了element元素左上角点的坐标
    ele_position = element.location
    x = ele_position["x"]  # 获取左上角点的x坐标值
    y = ele_position["y"]  # 获取左上角点的y坐标值

    start_x = x + width*0.9  # 获取的是起始点X的值
    y = y + height*0.5  # 获取的是起始及终止点的Y的值
    end_x = x + width*0.1   # 获取的是终止点X的值
    while True:
        page = driver.page_source  # 记录查找前的页面资源,通过对比页面资源来退出死循环
        try:
            driver.find_element(*element_info).click()  # 如果有找到对应的元素那么点击并返回
            return True
        except Exception as e:
            print("没有找到该元素!")
        driver.swipe(start_x, y, end_x, y, duration=1000)  # 没有找到元素,那么滑屏后再对比并重新查找
        time.sleep(1)
        if page == driver.page_source:
            print("滑屏操作完成且没有找到元素信息")
            return False
4、scroll滑动事件

scroll是通过元素来进行滑动的

driver.scroll(source_element, target_element)

scroll无法设置滑动的持续时间,带有一定惯性。 主要用于IOS中,android高版本系统可以使用。

import time

from appium import webdriver
from selenium.webdriver.common.by import By

from utils import get_element, input_text, execute_swipe

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)
# 存储 按钮
save_btn = By.XPATH, "//*[@text='存储']"
save_element = get_element(driver, save_btn)

# 蓝牙 按钮
lanya_btn = By.XPATH, "//*[@text='蓝牙']"
lanya_element = get_element(driver, lanya_btn)

# 通过scroll来进行滑动操作
driver.scroll(save_element, lanya_element)

time.sleep(3)

driver.quit()
5、drag_and_drop拖拽事件

从一个元素滑动到另外一个元素的位置, 同时也能实现将一个元素拖动另一个元素当。

driver.drag_and_drop(source_element, target_element)

source_element 表示的是被拖动的元素对象

target_element 表示的是目标元素对象

import time

from appium import webdriver
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)
# 存储
save_btn = By.XPATH, "//*[@text='存储']"
# 更多
more_btn = By.XPATH, "//*[@text='更多']"

# 通过拖动来实现滑屏操作
driver.drag_and_drop(get_element(driver, save_btn),  get_element(driver, more_btn))

time.sleep(3)

driver.quit()

三、高级手势操作

实现步骤:

1、创建TouchAction对象

2、调用手势方法

3、调用perform() 执行操作

1、轻敲操作

实现步骤:

  • action = TouchAction(driver) # 创建建手势对象

  • action.tap(element=None, x=None, y=None, count=1) # 调用轻敲手势方法,传入的是一个元素对象或者是一个坐标点

    count表示的是轻敲的次数, 默认值为1.

  • action.perform() # 调用perform()执行轻敲操作

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

wlan_btn = By.XPATH, "//*[@text='WLAN']"
wlan_element = get_element(driver, wlan_btn)

# 调用轻敲手势操作
TouchAction(driver).tap(x=457, y=487).perform()
# action = TouchAction(driver)  # 创建手势对象
# # 调用手势方法
# action.tap(wlan_element)
# # 调用perform()执行
# action.perform()
time.sleep(3)
driver.quit()
2、按下和抬起操作

按下:

press(element, x, y)

抬起:

​ release()

TouchAction(driver).press(x=477, y=489).release().perform()

按下和抬起可以结合起来使用,达到点击的效果

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

# 调用按钮手势操作
TouchAction(driver).press(x=477, y=489).perform()
# 等待2S
time.sleep(2)
TouchAction(driver).press(x=477, y=489).release().perform()

time.sleep(3)
driver.quit()
3 、等待操作【掌握】

模拟手指等待。 wait(ms=0) ms表示的是毫秒数

TouchAction(driver).press(x=650, y=650).wait(5000).release().perform()

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

# 找到wlan元素
wlan_btn = By.XPATH, "//*[@text='WLAN']"
get_element(driver, wlan_btn).click()
time.sleep(2)
# 通过等待及按下和抬起实现长按的操作
TouchAction(driver).press(x=467, y=569).wait(3000).release().perform()

time.sleep(3)

driver.quit()
4、长按操作

long_press(element, x=None, y=None, duration=1000)

element表示的是元素对象

x, y表示的是坐标点

duration表示的是长按的时长,单位是毫秒

TouchAction(driver).long_press(x=650, y=650, duration=2000).perform()

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True        # 采用unicode编码输入
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

# 找到wlan元素
wlan_btn = By.XPATH, "//*[@text='WLAN']"
get_element(driver, wlan_btn).click()
time.sleep(2)
# 通过等待及按下和抬起实现长按的操作
# TouchAction(driver).press(x=467, y=569).wait(3000).release().perform()
TouchAction(driver).long_press(x=467, y=569, duration=3000).perform()
time.sleep(3)

driver.quit()




## 今日目标(9)高级手势操作_余、toas操作、webview操作、pytest测试框架、pytest插件 - 高级手势操作_余、 - toas操作、 - webview操作、 - pytest测试框架、 - pytest插件

一、高级手势操作

5、移动操作

模拟手指在手机屏幕上移动的过程

move_to(element, x=x, y=y) ele表示的是元素对象, x和y表示的是坐标点。二选其一。

移动的操作是需要结合press和release一起使用。

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.lufax.android",   #表示app的包名
"appActivity" :  ".activity.HomeActivity",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True,        # 采用unicode编码输入
"noReset": True
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

me_btn = By.XPATH, "//*[@text='我的']"
get_element(driver, me_btn).click()

TouchAction(driver).press(x=260, y=720).wait(500).move_to(x=540, y=720)\
    .wait(500).move_to(x=820,y=720).wait(500).move_to(x=540, y=1000).wait(500).move_to(x=260, y=1270)\
    .wait(500).move_to(x=540, y=1270).wait(500).move_to(x=820, y=1270).release().perform()
time.sleep(5)
driver.quit()

今日目标(9)toast操作、webview操作(H5)、pytest测试框架、Pytest插件

二、toast操作:获取一个设置重点信息

1、获取toast消息,在初始化配置中需要增加一个配置项。否则定位不到。

“automationName”: “Uiautomator2”

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text, execute_swipe, element_is_exsit

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.settings",   #表示app的包名
"appActivity" :  ".Settings",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True,        # 采用unicode编码输入
"noReset": True,
"automationName": 'Uiautomator2'
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)
# 往上滑三次
execute_swipe(driver, 'top', count=3)

# 点击关于平板电脑
about_btn = By.XPATH, "//*[@text='关于平板电脑']"
get_element(driver, about_btn).click()

# 往上滑一次
execute_swipe(driver, 'top')

# 点击版本号
version_btn = By.XPATH, "//*[@text='版本号']"
get_element(driver, version_btn).click()
time.sleep(1)
# toast元素信息
toast_btn = By.XPATH, "//*[contains(@text, '开发者模式')]"
# driver.find_element(*toast_btn).click()
if element_is_exsit(driver, toast_btn):
    print("能够定位到toast消息")
else:
    print("不能定位到toast消息")
# 定义获取toast消息的方法
def get_toast(driver, message, timeout=3):
    # xpath = "//*[contains(@text, '" + message + "')]"   #.format(message)   # 通过{} 符号将message当参数传到xpath表达式中去
    xpath = F"//*[contains(@text, '{message}')]"
    wait = WebDriverWait(driver, timeout, 1)
    element = wait.until(lambda x:x.find_element(By.XPATH, xpath))
    return element.text

三、webview操作(H5):移动端的网页

  • 环境安装:

    1、需要查看手机或者模拟器上webView的版本 (webView的版本必须要与chromedriver的版本配套)

    在这里插入图片描述

    2、在手机或者模拟器上面安装chrome浏览器(手机或者模拟器中chrome版本要低于电脑上chrome的版本)

    3、设置PC电脑上面的appium中chromedriver的版本,chrome版本要与webView的版本配套。

    替找appium中的chrome版本:

    C:\Users\LiaoFei\node_modules\appium\node_modules\appium-chromedriver\chromedriver\win

  • 查看H5页面的元素信息

    1、在手机或者模拟器当中打开H5的页面

    2、在PC的chrome浏览器当中,打开对应的地址: chrome://inspect/#devices

在这里插入图片描述

3、通过devtools来查看对应的元素信息。

代码实现步骤:

1、首先要获取context的信息, 如果是原生的app,context的信息显示为Native App, 如果页面为webView的页面,context的信息显示为webView的名称。如果需要在app当中查看对应的webView的名,需要在app的代码当中加上以下的代码:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.KITKAT) {
    WebView.setWebContentsDebuggingEnabled(true);
}

2、切换到web页面

driver.switch_to.context(context)

import time

from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.by import By

from utils import get_element, input_text, execute_swipe, element_is_exsit, get_toast

des_cap = {
"platformName" : "android" ,   #表示的是android  或者ios
"platformVersion" : "5.1.1",   #表示的是平台系统的版本号
"deviceName" : "****",    #表示的是设备的ID名称(如果只有一个设备可以用****来代替)
"appPackage" : "com.android.browser",   #表示app的包名
"appActivity" :  ".BrowserActivity",      #表示的是app的界面名
"resetKeyboard": True,        # 重置设备的输入键盘
"unicodeKeyboard": True,        # 采用unicode编码输入
"noReset": True,
"automationName": 'Uiautomator2',
"chromedriverExecutableDir": r"D:\BaiduNetdiskDownload\apptools\apk\chromedriver_win32_2.22"  # 用来指定chrome驱动的目录
####"".module_main.activity.MainActivity""
}  #定义字典参数

driver = webdriver.Remote("http://localhost:4723/wd/hub", des_cap)

print(driver.contexts)
driver.get("http://m.baidu.com")
time.sleep(2)
driver.switch_to.context("WEBVIEW_com.android.browser")

driver.find_element(By.ID, "index-kw").send_keys("python")
time.sleep(3)
driver.find_element(By.ID, "index-bn").click()
time.sleep(5)
driver.quit()

四、pytest测试框架:测试框架

特点:

1、非常容易上手,入门简单,文档丰富,文档中有很多参考实例

2、支持简单的单元测试和复杂的功能测试

3、支持参数化

4、执行测试用例过程中,支持跳过操作

5、支持重复执行失败的case

6、支持运行由Nose,unittest编写的测试case

7、pytest支持很多第三方插件

8、方便的和持续集成工具集成

1、pytest介绍及安装
  • pytest安装
    • 在线安装 pip install pytest
    • 离线安装方式 下载pytest离线安装包,并解压,然后在DOS下进入到解压的目录,然后执行 python setup.py install
    • pycharm
  • 判断是否安装成功:
    • pip show pytest
    • pycharm
2、pytest类定义及方法定义及运行
  • pytest测试类的定义:类名必须是以Test开头
  • pytest测试方法的定义:方法名必须是以test开头
  • 执行:
    • 在pycharm中右击方法名或者类名可以直接执行对应测试类或者测试方法

在这里插入图片描述

​ 第二种运行方式: 通过pytest -s -v 测试文件名称 (-s 输出的用例输出的信息, -v输出的是执行的用例的类名以及方法名)

import pytest


def add(x, y):
    return x+y


class TestADD:  # 定义的类名必须是以Test开头
    def test_add_01(self):  # 定义的测试方法必须是以test开头
        result = add(1, 2)
        print(result)

    def test_add_02(self):
        result = add(2, 2)
        print(result)


3、pytest 断言
  • pytest里面的断言方法就只有一个

    assert 表达式

    class TestADD:  # 定义的类名必须是以Test开头
        def test_add_01(self):  # 定义的测试方法必须是以test开头
            result = add(1, 2)
            print(result)
            # assert result == 3    判断相等
            # assert result != 4    判断不相等
            # assert result    # 判断为True
            #assert False        # 判断为False
            # assert "a" in "abc" # 判断包含
            # assert "a" not in "abc"  # 判断不包含
            # assert result is None
            assert result is not None
    
4、pytest 方法级别的fixture
  • pytest方法级别的fixture是针对每个测试方法,在执行测试方法前会执行fixture初始化的操作,在执行完测试方法后,执行fixture销毁的操作。

    初始化的操作方法: def setup(self): 方法来实现。

    销毁的操作方法: def teardown(self): 方法来实现。

    import time
    
    
    def add(x, y):
        return x+y
    
    
    class TestAdd:
    
        def setup(self):
            print("测试用例开始执行时间:", time.strftime("%Y-%m-%D %H:%M:%S"))
    
        def test_add_01(self):
            result = add(1, 2)
            assert result == 3
    
        def test_add_02(self):
            result = add(2, 2)
            assert result == 4
    
        def teardown(self):
            print("测试用例结束时间:", time.strftime("
    
5、pytest类级别的fixture
  • pytest 类级别的fixture针对每个测试类的初始化和销毁的操作,可以放在以下两个方法中

    • 类级别初始化的方法: def setup_class(self):

    • 类级别销毁的方法: def teardown_class(slef):

      方法名称固定,不能修改。

fixture的方法必须写在测试类当中,不能写在测试类外面。

6、pytest配置文件

pytest的配置文件有固定的三个名称: pytest.ini tox.ini setup.cfg 这三个配置文件是放在项目的根目录下。

[pytest]   #  标识当前配置文件是pytest的配置文件
addopts = -s -v  # 标识pytest执行时增加的参数
testpaths = ./scripts  # 匹配搜索的目录
python_files = test_*.py # 匹配测试文件
python_classes = Test*  # 匹配测试类
python_functions = test_* # 匹配测试方法

五、Pytest插件

pytest测试报告
  • 安装pytest测试报告插件

    • 在线安装
    • 离线安装
    • pycharm
  • 使用方法

    addopts = -s -v --html=report/report.html
    

今日目标(10)pytest常用插件、pytest高级用法、PO模式

  • pytest常用插件、
  • pytest高级用法、
  • PO模式

一、pytest常用插件

2、控制用例执行顺序
  • unittest测试用例执行顺序是根据测试方法名称的assicc码值的大小来的,值越小排在前面(a-z)

  • pytest 正常情况下是根据测试方法的从上到下的顺序来执行

    可以通过 pytest-ordering 插件来控制pytest测试方法执行的顺序。

  • 安装:

    • 在线安装: pip install pytest-ordering
    • 离线安装: 下载对应的离线安装包,解压后,并进入到对应的目录,执行 python setup.py install
    • pycharm
  • 使用

    @pytest.mark.run(order=x) # x 表示的是整数,(既可以是负数也可以是正数)

    • 全为负数或者正数时,值越小,优先级越高

    • 既有正数,又有负数,那么正数优先级高

    • 没有确定执行顺序的用例优先于负数

    • @pytest.mark.last    # 设置用例最后执行
      
3、失败重试
  • pytest-rerunfailures 安装

    • 在线安装
    • 离线安装
    • pycharm
  • 使用

    在addopts参数行中增加对应的参数项: --reruns 3

    当重复执行成功时,就不会再重复执行。


二、 pytest高级用法

1、跳过

@pytest.mark.skipif(condition, reason=None)

condition 表示是跳过的条件

这里面reason参数名称必填。

@pytest.mark.skip(reason=None)

reason表示的是跳过的原因

可以在测试类和测试方法上使用

import pytest


def add(x, y):
    return x+y

version = 21

class TestAdd:
    # @pytest.mark.last    # 设置用例最后执行
    def test_add_01(self):
        result = add(1, 2)
        assert 3 == result

    @pytest.mark.skipif(version > 20, reason="大于2.0的版本不需要再执行此用例")
    # @pytest.mark.skip("版本已更新,不需要再进行测试")
    @pytest.mark.run(order=0)
    def test_add_02(self):
        result = add(2, 2)
        assert 4 == result

    @pytest.mark.run(order=-2)
    def test_add_03(self):
        result = add(3, 2)
        assert 5 == result

2、数据的参数化
  • pytest参数化实现: @pytest.mark.parameterize(argnames, argvalues)

    • argnames 表示是 参数名字,是一串字符, 多个参数之间由逗号隔开 “username, password”

    • argvalues 表示的是参数化的数据 [(“13700001111”,“123124”),(“13800011111”,“123456”)]

      argname的参数个数要与argvalues里面的测试数据的个数要相同,否则会报错。

import pytest


def add(x, y):
    return x+y


class TestAdd:
    @pytest.mark.parametrize("x,y,expect", [(1, 2, 3), (2, 2, 4), (3, 2, 5)])
    def test_add_01(self, x, y, expect):
        result = add(x, y)
        assert expect == result

三、 PO模式

1、V1版本介绍
  • 不使用任何模式和单元测试框架

V1版本缺点: 一条用例一个脚本,维护和管理非常的不方便

2、V2版本实现(通过pytest管理用例)
  • 通过pytest实现用例的管理和执行

V2版本缺点:存在代码冗余

今日目标(11)PO模式、数据驱动

一、PO模式:通过对界面元素的封装减少冗余代码

3、V3版本
3.1 方法封装
3.2 V3版本代码实现

缺点:1、 如果前端页面的元素信息发生了变更,那么自动化代码就需要去更新元素,而且是只要用到了这个元素就都要去更新。维护不方便

2、针对登录的代码,存大大量的冗余。

4、V4版本实现
4.1 PO模式介绍

PO是page object的简称,核心思想是通过对界面元素的封装减少冗余代码,同时在后期维护中,若元素定位发生变化, 只
需要调整页面元素封装的代码,提高测试用例的可维护性、可读性。

PO模式可以把一个页面分为三层,对象库层、操作层、业务层。
对象库层:封装定位元素的方法。
操作层:封装对元素的操作。
业务层:将一个或多个操作组合起来完成一个业务功能。比如登录:需要输入帐号、密码、点
击登录三个操作。

注意点:

1、确认需要操作的页面

2、每个页面所需要用到的元素对象

4.2 PO模式优点

减少冗余代码
业务代码和测试代码被分开,降低耦合性
维护成本低

4.3 PO模式实现

V4版本缺点:

1、元素定位的信息,如果页面元素过多,不方便维护

2、如果输入前没有做清除操作,代码的健壮性不够好。

5、V5版本(PO模式优化)

缺点:

1、元素定位,针对元素定位,没有使用显示等待。

2、代码的健壮性不够。

6、V6版本(PO模式的深入封装)

1、针对元素定位封装到操作的基类当中,且是通过显示等待来进行元素定位

2、针对元素输入之前做了清除的操作。封装在操作层的基类当中。

二、数据驱动:通过测试数据来驱动测试用例的执行。

1、数据驱动介绍

概念:通过测试数据来驱动测试用例的执行。

1.1 数据驱动特点
  • 数据驱动本身不是一个工业级标准的概念,因此在不同的公司都会有不同的解释。
  • 可以把数据驱动理解为一种模式或者一种思想。
  • 数据驱动技术可以将用户把关注点放在对测试数据的构建和维护上,而不是直接维护脚本,可
    以利用同样的过程对不同的数据输入进行测试。
  • 数据驱动的实现要依赖参数化的技术。
1.2 数据驱动方式
  • 直接定义在测试脚本中(简单直观,但代码和数据未实现真正的分离,不方便后期维护)
  • 从文件读取数据,如JSON、excel、xml、txt等格式文件
  • 从数据库中读取数据
  • 直接调用接口获取数据源
  • 本地封装一些生成数据的方法
1.3 json读取文件回顾
2、数据驱动实战一
3、数据驱动实战二

今日目标(12)日志收集

一、日志收集

1、日志相关概念

日志的概念:日志就是用于记录系统运行时的信息,对一个事件的记录

1.1 日志的作用
  • 调试程序
  • 可以用来判断程序是否运行正常
  • 可以用来分析和定位问题
  • 可以用来做用户行为分析和数据统计
1.2 日志的级别
  • 调试级别 DEBUG 记录的一些代码的调试信息
  • 信息级别 INFO 记录一些正常的操作信息
  • 警告级别 Warring 记录的是一些警告日志信息,但不会影响系统的功能及正常运行
  • 错误级别 Error 记录的是系统运行时的错误信息,说明系统的某些功能不能正常运行
  • 严重错误级别 critical 记录的系统运行时的严重错误信息,有可能导致整个系统都不能运行。

2、logging模块

logging是python自带的日志收集模块

2.1 logging的基本用法
  • 通过logging模块来输出日志信息.

    使用前需要导入logging模块

    使用方法: logging.debug(“这是一条调试级别的日志”)

    ​ logging.info(“这是一条信息级别的日志”)

    注意点:logging模块默认的级别是warring级别,默认的输出格式:" 级别: root : 日志信息"

    如果设置了对应级别,那么会输出大于或等于对应级别的日志信息

    #  导包
    import logging
    
    # 调用logging输出日志
    logging.debug("这是一条调试级别的日志")
    logging.info("这是一条信息级别的日志")
    logging.warning("这是一条警告级别的日志")
    logging.error("这是一条错误级别的日志")
    logging.critical("这是一条严重级别的日志")
    
2.2 logging的日志级别设置
  • 日志级别的设置: logging.basicConfig(level=logging.DEBUG)

    日志级别的选择:

    开发环境和测试环境:可以使用DEBUG或者INFO级别都可以

    生产环境:建议使用WARRING或者EEROR

2.3 logging的日志格式设置
  • 日志格式设置: logging.basciConfig(format=fmt) # fmt表示的日志格式字符串

    #  导包
    import logging
    # 定义一个格式化的字符串
    fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
    

设置日志的级别

logging.basicConfig(level=logging.DEBUG, format=fmt)

调用logging输出日志

logging.debug(“这是一条调试级别的日志”)
logging.info(“这是一条信息级别的日志”)
logging.warning(“这是一条警告级别的日志”)
logging.error(“这是一条错误级别的日志”)
logging.critical(“这是一条严重级别的日志”)

  
  
  
  
  
  

#### 2.4 将日志输出到文件

* 将日志输出到文件:

  logging.basicConfig(filename = 'log/a.log')    # 日志文件保存的目录必须手动创建

如果将日志输出到文件当中,就不会在控制台打印出对应的日志信息了。

​```python
#  导包
import logging
# 定义一个格式化的字符串
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
# 设置日志的级别
logging.basicConfig(level=logging.DEBUG, format=fmt, filename='log/a.log')
# 调用logging输出日志
logging.debug("这是一条调试级别的日志")
logging.info("这是一条信息级别的日志")
logging.warning("这是一条警告级别的日志")
logging.error("这是一条错误级别的日志")
logging.critical("这是一条严重级别的日志")
3、logging的高级用法
3.1 logging的四大组件介绍
  • 四大组件

    • 日志器 logger : 是程序的入口,主要用来记录日志的信息
    • 处理器 handler : 决定了日志的输出目的地
    • 格式器 formatter :决定了日志的输出格式
    • 过滤器 filter: 决定哪些日志信息被输出,哪些被丢弃

    总结: 日志器是程序的入口,最终通过处理器来决定日志器该往哪里输出对应的日志信息

3.2 logger类
  • 创建日志器: logger = logging.getLogger() 或者 logger = logging.getLogger(“myLogger”)

    如果创建的日志器不带参数,默认的日志名称是root

    如果创建的日志器带了参数,日志名称为对应的参数名

    如果创建的日志器名称相同,实际上,这两个日志器使用的是同一个日志名称。

    日志器常用方法:

    • 输出日志信息: logger.debug(msg)

      ​ logger.info(msg)

      ​ logger.warring(msg)

    • 设置日志的级别: logger.setLever(logging.INFO)

    • 添加处理器: logger.addHandler(handler)

3.3 handler类
  • 处理器的作用:决定日志输出到目的地
  • 常用处理器类:
    • logging.StreamHandler 将日志信息输出到控制台
    • logging.hanlders.TimedRotatingFileHandler 将日志信息输出到文件,并支持按时间来切割
  • 处理器类常用的方法
    • 设置日志的级别 handler.setLevel()
    • 在处理器当中添加格式器 handler.setFormatter()
import logging
import logging.handlers
import time

logger = logging.getLogger("myLogger")  # 创建logger日志器
logger.setLevel(logging.DEBUG)  # 设置日志器的级别

# 创建 输出日志到文件的处理器, 文件按时间来切割的
handler = logging.handlers.TimedRotatingFileHandler("log/test.log", when='S', interval=30, backupCount=3)
handler.setLevel(logging.INFO)

# 将处理器添加到日志器
logger.addHandler(handler)
while True:
    #  输出日志信息
    time.sleep(2)
    logger.info("这是一条信息级别的日志!")

3.4 formatter类
  • 格式器: 用来格式化日志信息的格式

    创建格式: formatter = logging.formatter(fmt=fmt) # fmt参数表示的是格式化的字符串

    可以将格式器添加到处理器就可以了。

3.5 将日志输出到控制台和文件中
import logging
import logging.handlers

# 1、创建日志器
import time

logger = logging.getLogger()

# 2、设置日志器级别
logger.setLevel(logging.DEBUG)

# 3、创建两个处理器(输出到控制台以及输出到文件)
#     3.1 创建输出到控制台的处理器
sf = logging.StreamHandler()
#     3.2 创建输出到文件的处理器
hf = logging.handlers.TimedRotatingFileHandler("log/log.log", when='M', interval=1, backupCount=3)

# 4、设置级别
sf.setLevel(logging.INFO)
hf.setLevel(logging.INFO)

# 5、创建格式器
fmt = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
formatter = logging.Formatter(fmt=fmt)

# 6、添加格式器到处理器当中
sf.setFormatter(formatter)
hf.setFormatter(formatter)

# 7、将处理器添加到日志器
logger.addHandler(sf)
logger.addHandler(hf)

# 8、输出日志信息
while True:
    time.sleep(3)
    logger.info("这是一条信息级别的日志")
    logging.warning("这是一条警告级别的日志")

今日目标(13)持续集成、GIT工具介绍及使用、Jenkins工具介绍及使用

  • 持续集成、
  • GIT工具介绍及使用、
  • Jenkins工具介绍及使用

持续集成

持续集成概念:

  • 持续集成的好处:

    • 提前发现错误
    • 防止分支与主干偏离
    • 更快速的发布更新
  • 持续集成的流程及原理:

在这里插入图片描述

一、GIT工具介绍及使用

  • git工具安装:

    直接运行exe文件进行安装,按默认的操作点击下一步就行了。

  • 校验:

    在DOS命令行中输入: git --version

    如果能正常显示出对应的版本就是OK的

  • 做初始化的配置: 为了提交代码时能够识别身份

    git config --global user.email “email@example.com”
    git config --global user.name “Your Name”

  • 常见的代码托管平台:

    • github 全球最大的代码托管平台
    • gitee 码云,国内的代码托管平台
    • gitlab 私有的git代码托管平台,一般是由公司自己搭建。
git基本使用命令
  • 创建git仓库

    1、创建一个目录

    2、在DOS命令行中,进入到创建的目录下,然后输入 git init方法进行创建 。

    注意事项:

    通过git init创建项目后会在对应的目录下自动创建.git目录,.git目录主要用来存放git的相关操作信息。

    如果已经通过git init创建git仓库,不要再次使用git init去创建

  • 查看状态:git status 用来查看git仓库的状态

  • 添加文件到缓存区 git add 文件名 或者git add . (.号代表的是所有文件)

  • 添加到仓库 git commit -m “msg”

    注意:-m ”msg“ 参数一定不能少。

git 版本创建及切换
  • 查看版本信息: git branch
  • 创建版本分支: git branch dev_branch git branch test_branch
  • 切换片本分支: git checkout dev_branch git checkout test_branch
git恢复特定的版本
  • git log 查看提交的历史版本 git reflog 来查看是全部的提交版本信息
  • git reset hash值前6位
上传本地仓库到远端仓库

操作步骤:

​ 1、在本地新建一个仓库

​ 2、在远端新建一个仓库

在这里插入图片描述

在这里插入图片描述

3、执行以下两条命令,可以将本地仓库上传到远端仓库

git remote add origin https://gitee.com/liaohui3389/ui_test.git
git push -u origin master    #  需要指定特定的分支版本, master表示的是主干分支
将远端的仓库下载的本地
  • 命令行方式:

    git clone 远端仓库地址 第一次执行时,会要求你输入远端仓库平台的用户名和密码

  • 通过pycharm下载远端仓库

    • 在file-setting菜单中,搜索git

    • 在搜索之后的窗口中,设置git的执行文件的地址.

    在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 通过pycharm上传 和 下载新代码

    • 上传

      • 更新或者修改文件

      • 要通过pycharm 将对应的文件添加到缓存区

      • 通过pycharm将对应的文件添加到本地仓库

      • 通过pycharm上传本地仓库到远端

        在这里插入图片描述

    • 下载远端仓库到本地

      直接右击 选择 git–pull就可以下载远端仓库

二、Jenkins工具介绍及使用

jenkins安装

1、JDK

  • 直接运行exe文件进行安装即可。如果有自动添加环境变量,不用手动添加,如果没有自动添加环境变量,需要添加以下两个环境变量: JAVA_HOME=C:\Program Files\Java\jdk1.8.0_151
    在Path中添加:%JAVA_HOME%\bin;

  • 校验:在DOS中输入 : java -version 如果有显示正确的版本信息就是OK的

在这里插入图片描述

2、jenkins.war

  • 在线安装: 获取jenkins.war

    1、通过java -jar jenkins.war 来启动jenkins

    2、需要获取到首次启动的密码,并将密码填入到 localhost:8080首次打开的页面中。

在这里插入图片描述

3、进入到jenkins首次打开页面后,选择安装对应的插件。默认选择第一个就可以了。

在这里插入图片描述

4、安装完插件之后,会提示设置并要求输入用户名和密码。确定用户名和密码之后就可以登录了。

  • 离线安装方式:

    1、通过 java -jar jenkins.war来启动 jenkins(启动之后,在复制数据文件目录之前可以停止掉)

    2、将离线的数据文件包.jenkins复制到对应的 C:\users\用户名 目录下即可。

    3、重启jenkins即可。

jenkins插件安装
  • 在线安装方式:

    1. 进入 jenkins
    2. 点击 系统管理
    3. 点击 管理插件
    4. 点击 可选插件
    5. 搜索框中输入 allure
    6. 第一条选中点击 直接安装 即可
  • 离线安装方式:

    1、从网上下载对应的插件文件,hpi结尾。

    2、进入 jenkins

    3、点击 系统管理

    4、点击 管理插件

    5、点击 高级

    6、在高级页签 中,点击上传插件中上传文件,选择下载的插件文件,点击打开就OK

jenkins 系统配置
  • 配置jenkins访问的地址及系统管理员邮箱地址

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4QtjLswp-1685210457568)(ui自动化测试day13/image-20200709145114925.png)]

  • 配置jenkins的扩展邮箱通知

在这里插入图片描述

  • 邮件通知配置

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QyYSQNn5-1685210457568)(D:/ce/02-%E9%85%8D%E5%A5%97%E8%B5%84%E6%96%99%EF%BC%88%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85%E5%8C%85+%E8%AF%BE%E4%BB%B6+%E8%AF%95%E5%8D%B7%EF%BC%89/09%E3%80%81UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95%E5%8F%8A%E9%BB%91%E9%A9%AC%E5%A4%B4%E6%9D%A1%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98/UI%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95/day13/02%E7%AC%94%E8%AE%B0%E6%80%BB%E7%BB%93/ui%E8%87%AA%E5%8A%A8%E5%8C%96%E6%B5%8B%E8%AF%95day13/image-20200709145503099.png)]

在jenkins上面配置job
  • 在jenkins页面当中,点击 ”新建item“

  • 在新建的job页面,输入 job名称,选择 ”Fresstyle Project“,并点击确定

在这里插入图片描述

  • 源码管理设置

在这里插入图片描述

  • 触发器构建 设置

在这里插入图片描述

  • 构建 设置

在这里插入图片描述

  • 构建后的操作 设置

在这里插入图片描述

今日目标(day14-day15)

1、自动化测试流程

  • 需求分析
  • 挑选合适的功能做自动化测试
  • 设计测试用例----可从手工用例挑选
  • 搭建测试环境(可选)
  • 设计自动化测试项目的架构(可选)
  • 编写代码
  • 执行测试用例
  • 生成测试报告并分析结果

2、项目介绍

2.1 负载均衡器

负载均衡器:负载均衡(Load Balance)可以将工作任务分摊到多个处理单元,从而提高并发处理能力。
负载均衡建立在现有网络结构之上,使用它可以实现扩展网络设备的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

负载均衡器在工作当中,要么使用nignx(软件的负载均衡), 要么使用F5(硬件负载均衡设备),如果使用的阿里云或者是腾讯云,SLB负载均衡。

2.2 消息队列

消息队列(Message Queue 简称MQ):是在消息传输过程中保存消息的容器。
消息队列中间件是分布式系统中重要的组件,主要解决应用解耦、异步消息、流量削峰等问题,实现高性能、高可用、可伸缩和最终一致性架构。

  • 异步处理
    将业务逻辑处理由串行方式变成并行方式(好友推荐、新闻推荐)
  • 应用解耦
    订单系统–>库存系统
    发送短信验证码
  • 流量削峰
    秒杀、抢购活动(一般会因为用户访问量过大,导致流量暴增、应用挂掉)
  • 日志处理
    将消息队列用在日志处理中,解决大量日志传输的问题

3、项目搭建

uiAutoTestHmtt # 项目名称
├── base # 封装PO基类
├── page # 封装PO页面对象
├── script # 定义测试用例脚本
├── data # 存放测试数据
├── report # 存放生成的测试报告
├── log # 存放日志文件
├── img # 存放截图
├── config.py # 定义项目的配置信息
├── utils.py # 定义工具类
└── pytest.ini # pytest配置文件

4、allure测试报告

4.1 allure安装
  • 在线安装 pip install allure-pytest
  • 离线安装
  • pycharm安装
4.2 allure配置运行脚本生成结果文件
  • allure使用步骤:

    • 要在pytest.ini配置文件的addopts项中,增加一项: --alluredir report # report表示的是生成报告数据存放的目录
    • 在终端执行pytest 的命令,运行测试脚本
    • 通过allure在对应的目录下生成 测试报告的数据。 json或者xml开式存放的。
  • 将allure测试报告数据生成HTML测试报告

    allure转换工具安装

    • 解压allure-2.7.0工具包
    • 将解压的目录放到不经常移动的路径下面
    • 找到解压目录的bin目录,并将bin目录的路径添加到环境变量当中
    • 在命令行当中输入 allure,如果有以下提示信息,就说明是成功的。
      -在这里插入图片描述
4.3 通过allure命令将结果文件转换成html报告

allure生成HTML测试报告

  • 使用的命令: allure generate report -o report/html --clean

    allure generate 表示的是生成测试报告

    report 表示的是测试报告的数据目录

    -o report/html 表示输出html测试报告的目录为 report/html

    –clean 表示的是清除之前 report/html里面的报告文件

5、allure与pytest结合

5.1 添加测试步骤
  • 使用的方法:

    @allure.step(title=“步骤名称”)

    title名称必须要带上。

# 定义操作层
class LoginHandle(BaseHandle):
    def __init__(self):
        self.login_page = LoginPage()

    # 输入手机号码
    @allure.step(title="输入手机号码")
    def input_mobile(self, mobile):
        self.input_text(self.login_page.find_mobile(), mobile)

    # 输入验证码
    @allure.step(title="输入验证码")
    def input_code(self, code):
        self.input_text(self.login_page.find_code(), code)

    # 点击登录按钮
    @allure.step(title="点击登录按钮")
    def click_login_btn(self):
        self.login_page.find_login_btn().click()
5.2 添加图片文件
  • 通过allure添加截图实现

    allure.attach(driver.get_screenshot_as_png, “截图描述”, allure.attachment_type.PNG)

 @pytest.mark.parametrize("username, code, expect", case_data)
    def test_login(self, username, code, expect):
        logging.info("用例的数据如下:用户名:{}, 验证码:{}, 预期结果:{}".format(username,
                                                              code, expect))
        print(username, code)
        self.login_proxy.login(username, code)   # 登录
        allure.attach(UtilsDriver.get_mp_driver().get_screenshot_as_png(), "登录截图", allure.attachment_type.PNG)
        username = self.home_proxy.get_username_msg()  # 获取登录后的用户名信息
        assert expect == username   # 根据获取到的用户名进行断言
5.3 添加用例的严重级别
  • allure添加用例的严重级别实现方法:

    @allure.severity(allure.severity_level.NORMAL)

    参数有五个,也对应不同的优先级,只需要将最后一个词替换即可。

    1. BLOCKER 最严重
    2. CRITICAL 严重
    3. NORMAL 普通
    4. MINOR 不严重
    5. TRIVIAL 最不严重

6、jenkins集成

  • 安装allure插件

  • 配置allure插件

在这里插入图片描述

  • 将自动化的代码上传到git服务器

    • 本地创建仓库 在当前项目的根目录下,执行 git init 为创建本地仓库

      • 初始化仓库之后,需要将本地的代码提交到本地仓库

        git add .   # 将本地的代码提交到缓存区
        git commit -m “提交信息”  # 将本地的代码提交到本地仓库
        
    • 创建远端仓库

    • 将本地仓库代码上传到远端仓库

      git remote add origin https://gitee.com/liaohui3389/ui_auto_test.git
      git push -u origin master
      
  • jenkins结合allure测试报告的 job创建

    • 在 jenkins页面当中,点击 “新建item”

在这里插入图片描述

在这里插入图片描述

  • 输入描述信息

在这里插入图片描述

  • 在源码管中选择 git, 输入对应的远端仓库地址。

在这里插入图片描述

  • 构建触发器设置

在这里插入图片描述

  • 构建的设置

在这里插入图片描述

在这里插入图片描述

  • 点击 构建后操作步骤中,选择 Allure Report

    在这里插入图片描述

  • 配置allure测试报告

  • 配置邮件通知

在这里插入图片描述

在这里插入图片描述

  • 最后点击应用并保存

  • 1、技能、测试工具总结写下

  • 2、测试项目,学一下,写下测试内容,和其他测试的内容,如用例,报告,性能,接口,自动化(车载,金融)

  • 3、然后面试经历记录总结下,融合到项目中

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mingji811920

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值