八、Python
1.python简介
python是一种高级编程语言,与C,C++,C#,java,php等一样。python可以用来做web开发,软件开发,人工智能,云计算,自动化运维,网络爬虫等。
2.python环境搭建
(1)python编译器===python-3.7.1-amd64.exe 编译器:将开发工程师编写英文代码翻译成计算机能够执行的二进制文件。 python中目前有两个大版本,python2和python3,语法有部分区别。
安装注意:
环境变量作用:记录一些命令的可执行文件的路径,当在命令行(cmd)中输入相关的命令时,可以通过环境变量找到对应的路径,打开相应的可执行文件,去执行相应的命令。
(2)python开发环境====pycharm-community-2017.2.4.exe (方便编写python代码的工具。)
优点:
(1)代码方便保存和管理
(2)界面比较美观,有高亮和不同颜色区分;
(3)有语法错误提示
(4)有语法提示
3.python代码注释
单行注释:# 快捷键:ctrl+/
对于已注释的代码,再次按ctrl+/ 取消注释
多行注释:''' 注释内容 ''' 三个单引号或者三个双引号
4.Python命名规则
(1)只能包含数字,字母下划线
(2)不能以数字开头
(3)区分大小写
(4)不能使用关键字:例if,for,else等
5.Python基本语法
(1)变量
变量是一种存储数据的容器,在不同的时刻可以存储不同的数据。
变量定义:直接定义并且复制。例:a=10
赋值符:= 将
变量要先定义再使用
变量的数据类型由它的赋值来决定
(2)数据类型
1)整型
整型:int
a1=10
type() 该方法为Python的内置方法,可以获取变量类型
例:print (type(a1))
2)浮点型
浮点型:float
a2=100.88
同样,获取变量类型:
print (type(a2))
3)字符串型
字符串型:str
字符串型必须用引号引起来,单引号,双引号(单引号和双引号没有区别),三引号都可以
a3='我是字符串'或a3=''我是字符串''
说明:在单引号或者双引号的字符串中不能定义换行等特殊符号,但三引号可以
1.字符串的拼接
a4='hello'+a3
在拼接时只能字符串型与字符串型拼接,如果想要将数值型拼接,可以进行转型。
例:'110'强制转成整型:int('110')
110 强制转成字符串型:str(110)
'9.99'强制转成浮点型:float('9.99')
2.字符串转义型
在Python对于键盘上的一些特殊键,定义了一些特殊的字符去表达
常用的转义符:\n:换行
\t:tab制表符
\\:表示一个\
\”:表示一个”
\':表示一个'
定义路径字符串,在字符串前面加r,作用是将后面的字符串中的\当成普通字符,不要进行转义
例:a5='D:\\pythoncode\\test38.txt'
a5=r'D:\pythoncode\test38.txt'
3.3.字符串格式化
占位符:%s 字符串类型
%d 整型
%f 浮点型
%.2f 表示保留两位小数
例:b11='张三'
b22=100
b33=5
a10='学生姓名为:%s,学生成绩为:%.2f,课程总数为:%d'%(b11,b22,b33)
print(a10)
4)布尔型 bool
一般是用于做逻辑判断,只有两个值:True和False
5)列表 list
一个列表型变量可以存储多个数据,有序存储。
1.定义:使用中括号[]来定义。
例:a12=[1,'123',True,99.9,10]
2.取值:使用下标来取值,下标从0开始计算,下标也可以用负数表示,从后开始计算下标,倒数最后一个-1,倒数第二个-2
单个取值:变量名[下标]
例:print(a12[3])--取99.9的值
print(a12[-2])--取99.9的值
3. 多个取值:变量名[开始下标:结束下标:步长]
步长就是每一次增值,下标的增量
例:
a12=('11',23,78,50,66,'aaa',True,'999',10,20)
print(a12[2:8:2])--[78,66,True]
print(a12[1:9:3])--[23,66,'999']
print(a12[2:8])--步长可以为空,为空时默认为1
print(a12[2:])--结束下标为空,表示取值到列表的最后一个数据
print(a12[:8])--开始下标为空,表示从列表的第一个数据开始取值
print(a12)--直接写变量名表示取整个列表
4.列表修改
a12[3]=False--直接给对应下标的位置重新赋值
5.列表追加
在列表的最后加入新的数据。
例:a12.append(999)
在列表的指定下标位置插入数据
例:a12.insert(3,'hello')--将hello的字符串插入到下标为3的位置
6.列表长度
列表中数据的个数
len(变量名)--获取列表变量数据的个数
6)元组 tuple
一个元组变量可以存储多个数据,有序存储
与列表的区别:
1.定义不同,列表用[]来定义,元组用()来定义。
2.列表可以修改,但是元组是只读的,不能修改。
例:a13(1,'123',23,78,50,66,True,99.9,10)
3.元组的取值用法与列表取值用法一致
例:print(a13[3])--取78的值
7)字典 dict
一个字典变量可以存储多个数据,每一个数据都是以键值对形式定义,键代表数据的含义,值代表数据具体的值。
每个数据定义的格式:键:值
1.定义:使用大括号{}来定义,每一个数据都是键值对形式
例:a14={'name':'张','age':18,'sno':'s001','score':95}
说明:1.字典中的键唯一,不能重复
2.字典中的键不可修改,一般用数字,字符串,元组,不能是列表
3.字典是无序的。
2.取值:通过键来取值
格式:变量名[键]
8)输入和输出
1.输出--print()
将程序运行过程中的数据输出到控制台,给开发查看
可以输出一个内容,也可以输出多个内容,用逗号隔开。
例:print(a12[3],a14['name'])
2.输入--input()
在程序运行的过程中,接收用户输入的数据用于程序运算
注意:input()方法接收到用户输入的数据当做字符串类型处理。
例:
a1=int(input('请输入一个数'))
s2=int(input('请输入第二个数'))
s=a1+a2
print(s)
9.运算符
1.算术运算符
+ - * /
//:整数除法,除法后取整数
%:取余数 例:10%3==1 10除以3的余数为1
思考:给你一个三位数478,计算百位,十位,个位数字
n=478
a=n//100 百位
b=n//10%10 十位
c=n%10 个位
2.关系运算符
==:相等
!=:不等于
>< >= <=
3.赋值运算符
= 比如a=10 将10赋值给变量a
+= -= *= /=
比如: a+=10 表示a=a+10
4.逻辑运算符
and 与 a and b同时为真,结果为真,否则结果为假
or 或 a or b 只要有一个为真,结果为真,否则结果为假
not 非 not a 当a为真,结果为假,当a为假,结果为真
in 包含 a in b 当b包含a,结果为真,否则为假,一般用于字符串或者列表或者元组
not in 不包含
3.Python三大语句
(1)if语句
if语句实现代码的分支结构,实现根据条件一部分代码执行,一部分代码不执行。
(1)单分支结构:if 条件:
条件为真,执行的代码
注意:if中语句与if关键字有一个缩进(indent),也就是按一个tab键,Python中通过缩进关系来表示代码间的从属关系。
执行逻辑:执行到if这一句时,判断if后的条件,如果为真,执行if中代码,否则不执行,继续顺序往下执行if后面的语句
例:输入成绩,判断成绩大于90,输出优秀
sore=int(input('请输入成绩'))
if sore>90:
print('优秀')
(2)双分支结构:
if 条件:
条件为真,执行的代码
else:
条件为假,执行的代码
执行逻辑:执行到if语句时,判断if后的条件,如果为真,执行if中的代码块,如果为假,执行else中的代码块。
注意:
(1)if 和else中的代码块与if,else关键字有一个缩进关系
(2)else后不能加条件
(3)if和else分支只能有一个会被执行而且只有一个会被执行
(3)多分支结构:
if 条件1:
条件1为真,执行的代码块
elif 条件2:
条件2为真,执行的代码块
elif 条件3:
条件3为真,执行的代码块
...
else:
上面的条件都不为真,执行的代码块
执行逻辑:先判断条件1,如果为真,执行if中的代码块1;条件1为假,再判断条件2,如果为真,执行代码块2;条件2为假,再判断条件3,如果为真,就执行代码块3,...如果前面所有的条件都不为真,就执行else中的代码。
注意:
1)if,elif和else中的代码块与if,elif,else关键字有一个缩进关系;
2)else后不能加条件,elif后面可以加条件;
3)if,elif和else分支只能有一个会被执行,而且只有一个会被执行。
4)else可以没有。
例:输入成绩,大于等于90,优秀;大于等于80,小于90,良好;大于等于60,小于80,及格;小于60,努力搬砖
score=float(input('请输入成绩'))
if 90<=score<=100:
print('优秀')
elif 80<=score<90:
print('良好')
elif 60<=score<80:
print('及格')
elif 0<=score<60:
print('努力搬砖')
else:
print('请输入正确的成绩')
(4)嵌套分支:
if 外层条件:
if 内层条件:
满足内层if执行的代码块
执行逻辑:先判断外层的if条件,如果为真,再判断内层if的条件,如果也为真,就执行内层的if条件
例:20.去火车站乘车,首先检查是否有票,如果有票,进去安检,安检如果健康码是红码,不允许进站上车,否则可以上车。
f=(input('请输入是否有票(有/无)'))
if f=='有':
print('请进安检')
m=(input('请出示健康码(红/黄/绿'))
if m=='绿':
print('请入站')
elif m=='黄':
print('请做核酸')
elif m=='红':
print('请做隔离')
else:
print('健康码信息错误')
elif f=='无':
print('请先购票')
else:
print('票据信息有误')
(2)while 语句
while语句时实现循环结构,实现根据条件让一部分代码重复执行多次。
语法:
while 条件:
条件为真,执行的代码块
执行逻辑:
执行到while语句时,首先判断while后的条件,如果条件为真,执行一次while中的代码块,第一次循环执行结束后,判断while后的条件,如果还为真,第二次执行while中的语句.....直到while条件为假,循环结束,继续顺序往下执行。
例:1.打印100以内的奇数
i=0
while i<=100:
if i%2==1:
print(i)
else:
pass
i+=1
例:2.打印100以内的奇数
i=0
while i<=100:
if i%2==1:
print(i)
else:
pass
i+=1
例:3.输入一个数n,计算1+2+3+……+n的结果
n=int(input('请输入一个正整数'))
i=1
s=0 #存放计算的结果
while i<=n:
s=s+i #每一次循环将变量i加到结果s中
i+=1
print('结果为:',s)
例:4.输入一个数n,计算1+3+5+7+……+n的结果
n=int(input('请输入一个正整数'))
i=1
s=0
while i<=n:
if i%2==1:
s=s+i
i+=1
print('结果为:',s)
例:5.计算1~100之间奇数和,偶数和。输出格式:100内的奇数和为:***,偶数和为:***
i=1
s1=0 #存奇数和
s2=0 #存偶数和
while i<=100:
if i%2==1:
s1=s1+i
elif i%2==0:
s2=s2+i
i+=1
print('100内的奇数和为:%d,偶数和为:%d'%(s1,s2))
(3)for语句
for语句也是实现循环结构,for语句时在确定的范围内循环,但while语句只是根据条件来进行循环。
(1)在字符串中循环
语法:for i in 字符串:
循环执行的代码块
执行逻辑:循环变量i一次取字符串中每一个字符,循环的次数就是字符串的个数。
例:
for i in 'hello world':
print(i)
(2)在列表/元素/字典中循环:
语法:for i in 列表:
循环执行的代码块
执行逻辑:循环变量i依次取列表中每一个数据,循环的次数就是列表数据的个数。
例:
for i in [1,'45',True,10,89]:
print(i)
(3)在一个序列范围内循环
语法:for i in range(开始范围,结束范围,步长):
循环执行的代码块
执行逻辑:循环变量i取值范围:开始范<=i<结束范围
步长:每一次循环,变量i的增量
说明:开始范围可以为空,如果为空,就从0 开始
步长可以不写,默认为1
例:
循环变量i从1开始,到9结束,每次变量i+1(步长默认为1)
for i in range(1,10):
print(i)
循环变量i从0开始(开始范围为空,默认从0开始),到9结束,每次变量i+1(步长默认为1)
for i in range(10):
print(i)
循环变量i从1开始,到9结束,每次变量i+2(步长为2)
for i in range(1,10,2):
print(i)
例:1.输入一个数n,计算1+2+3+……+n的结果
n=int(input('请输入一个正整数'))
s=0 #存放计算的结果
for i in range(1,n+1,1):
s=s+i #每一次循环将变量i加到结果s中
print('结果:',s)
2.输入一个数n,计算1+3+5+7+……+n的结果
n=int(input('请输入一个正整数'))
s=0 #存放结果
for i in range(1,n+1,2):
s+=i
print('结果:',s)
另一种写法
for i in range(1,n+1,1):
if i%2==1:
s+=i
3.计算1~100之间奇数和,偶数和。输出格式:100内的奇数和为:***,偶数和为:***
s1=0
s2=0
for i in range(1,101,1):
if i%2==1:
s1=s1+i
else:
s2=s2+i
print('1-100的奇数和为%d,偶数和为%d'%(s1,s2))
(4)循环中断
一般与if结合使用,当满足什么条件时,循环中断。
1)break
一般在循环中遇到break,循环中止,结束整个循环
例:
for i in 'hello world':
if i=='o':
break
print(i)
2)continue
一般在循环中遇到continue,本次循环结束,后面的循环继续
for i in 'hello world':
if i=='o':
continue
print(i)
4.python函数
函数的意义:提高代码复用率,提高编程效率
函数的定义:一段具有特定功能的代码块,可以被反复使用多次
函数的分类:
(1)内置函数,就是Python已经定义好的,可以直接使用,例print(),input(),int(),str(),float(),list(),len(),type()等
(2)用户自定义函数,需要先定义,再使用。
(1)有参有返
1.函数定义:
def 函数名(参数1,参数2.....)
函数功能实现代码块
return 返回值
说明:
1.参数的作用:将函数外的数据传到函数内
2.返回值作用:将函数内的数据返回到函数外
2.函数调用:
变量=函数名(参数值1,参数值2.....)
例:
定义一个加法函数
def add(a,b):
c=a+b
return c
调用函数
num1=int(input('输入第一个数'))
num2=int(input('输入第二个数'))
s=add(num1,num2) #调用函数add,将计算的数据num1和num2传入函数内,将计算的返回值结果赋值给变
量s
print('结果:',s)
(2)有参无返
1.函数定义
def 函数名(参数1,参数2……):
函数功能实现代码块
2.函数调用
函数名(参数值1,参数值2……)
例:函数定义
def add2(a,b):
c=a+b
print('结果:',c) #计算的结果再函数内打印出来,不返回到函数外
函数调用
num1=int(input('输入第一个数'))
num2=int(input('输入第二个数'))
add2(num1,num2) #调用函数add2,将计算的数据num1和num2传入函数内,没有返回值
(3)无参有返
1.函数定义
语法:
def 函数名():
函数功能实现代码块
return 返回值
2.函数调用
格式:
变量=函数名()
例:
定义一个加法函数
def add3():
a=int(input('输入第一个数'))
b=int(input('输入第二个数'))
c=a+b
return c
调用函数
s=add3() #调用函数add3,将计算的返回值结果赋值给变量s
print('结果:',s)
(4)无参无返
1.函数定义
def 函数名():
函数功能实现代码块
2.函数调用
函数名()
例:函数定义
def add4(a,b):
a=int(input('输入第一个数'))
b=int(input('输入第二个数'))
c=a+b
print('结果:',c) #计算的结果再函数内打印出来,不返回到函数外
函数调用
add4() #调用函数add4,没有返回值
标准代码组织结构
在其他文件中调用函数时,需要先导入再调用。
导入:from 文件名 import 函数名
导入快捷键:alt+enter
from 文件1 import 函数1
from 文件2 import 函数2
def 函数3():
代码
def 函数4():
代码
需求:文件(模块)1 的函数被文件(模块)2调用,不希望执行文件1中测试代码
解决:在文件1的测试代码上增加:if __name__ == '__main__':
作用:如果在执行自己文件时候(会执行该if结构下的代码)
如果文件(文件1)被别人(文件2)使用,运行文件2时,文件1中
if __name__==”__main__”: 此结构下的代码不会被执行。
(5)练习
1.定义一个乘法函数,实现两个数的乘法 ,计算的数据有用户自己输入 两种方式:有返/无返
有返回值
def mul(a,b):
return a*b
num1=int(input('输入第一个数'))
num2=int(input('输入第二个数'))
ss=mul(num1,num2)
print(ss)
无返回值
def mul2(a,b):
c=a*b
print('结果为:',c)
num1=int(input('输入第一个数'))
num2=int(input('输入第二个数'))
mul2(num1,num2)
无参无返
2.定义一个函数判断一个数是正数还是负数,要求动态输入一个数据,打印出结果。
def compare():
num = int(input('请输入一个数'))
if num > 0:
print('正数')
elif num < 0:
print('负数')
else:
print('非正非负')
compare()
有参有返
3.定义一个函数判断两个数的大小,要求动态输入两个数,调用函数判断大小,打印出大的数。
def f1(a,b):
c=0 #c放返回的结果,也就是放两个数中的较大的数
if a>b:
c=a
elif a<b:
c=b
else:
c=a
return c
num1=int(input('输入第一个数'))
num2=int(input('输入第二个数'))
ss=f1(num1,num2)
print("大的数为:",ss)
5.面向对象
面向对象是一种编程思想,可以应用于所有高级编程语言,比如java,Python,c++,c#等,主要是使用大型复杂的系统实现。
面向对象思想核心:将事物进行抽象化提取公共特征(包括静态的数据以及动态的功能/动作),形成一个类(面向对象的专业名词,就是指提取出来的公共特征);创建具体的事物,具体的事物在面向对象思想被称做对象/实例;让具体的对象去完成相应的功能
(1)面向对象基本用法
1)事物抽象化,提取公共特征,创建类
需求:(1)创建一个人类,公共特征:姓名,年龄,性别,身份证号,可以吃饭,可以睡觉,可以打豆豆
(2)创建一个人张三,李四,让张三吃饭,让李四打豆豆
在类中的公共特征分为两类:
1)属性:静态的数据,本身就是一个变量
2)方法:动态的动作/功能,本质就是一个函数
创建类的语法格式:
class 类名:
#1.定义属性
#2.定义方法
说明:
1.类中属性通过一个特殊的函数(构造函数)来定义属性和属性赋值
2.构造函数:函数名固定为:__init__(),作用就是定义属性,给属性赋值
3.self参数:
(1)self参数代表对象自己
(2)在类中,对象的属性都需要加上self.前缀
(3)在类中,所有的方法都需要有self参数,并且是第一个
例:1.抽象化,创建类
class person:
# 1.定义属性 姓名,年龄,性别,身份证号
# 定义属性时,通过构造函数来定义
def __init__(self,a,b,c,d):
self.name=a
self.age=b
self.gender=c
self.id=d
# 2.定义方法 可以吃饭,可以睡觉,可以打豆豆
def eat(self):
print(self.name,'在吃饭')
def sleeping(self):
print(self.name,'在睡觉')
def game(self):
print(self.name,'在打豆豆')
2)事物对象化/实例化,创建具体事物,也就是创建对象 说明:创建对象的过程,实际就是在调用构造函数 格式:
对象名=类名(构造函数实际参数) # self参数不用传,就代表的对象自己
p1=person('张三',20,'男','123')
p2=person('李四',30,'男','456')
3)让对象去完成类中定义的具体功能 格式1:通过对象调用
对象名.方法名(方法对应的参数) #self参数不用传,就代表的对象自己
p1.eat()
p2.eat()
p2.game()
格式2:通过类名
类名.方法名(对象名,其他参数) #通过类名调用方法时,需要传self参数,也就是传对象名
person.eat(p1)
person.eat(p2)
person.game(p2)
练习
# 需求:创建一个人类,公共特征:姓名,年龄,性别,身份证号,可以吃饭,可以睡觉,可以打豆豆
# 创建两个人张三,李四,让张三去吃饭,让李四去打豆豆
# 1.抽象化,创建类
class person:
# 1.定义属性 姓名,年龄,性别,身份证号
#定义属性时,通过构造函数来定义
def __init__(self,a,b,c,d):
self.name=a
self.age=b
self.gender=c
self.id=d
# 2.定义方法 可以吃饭,可以睡觉,可以打豆豆
def eat(self):
print(self.name,'在吃饭')
def sleeping(self):
print(self.name,'在睡觉')
def game(self):
print(self.name,'在打豆豆')
# 2.创建具体的对象 创建两个人张三,李四
p1=person('张三',20,'男','123')
p2=person('李四',30,'男','456')
# 3.让对象完成具体的功能 让张三去吃饭,让李四去打豆豆
p1.eat()
p2.eat()
p2.game()
创建一个人类,公共特征:姓名,年龄,性别,存款,可以吃饭(花钱),可以睡觉,可以工作(赚钱)
# 创建两个人张三,李四,让张三去吃饭,吃火锅,花了100块
# 让李四去吃烧烤,花了200块,
# 让张三去工作,工作赚3000块,让李四去工作,赚10000块
class human:
def __init__(self,a,b,c,d):
self.name=a
self.age=b
self.gender=c
self.money=d
def eat(self,food,s_money):
print(self.name,"去吃饭,吃的",food,"花费了",s_money)
self.money=self.money-s_money
def sleeping(self):
print(self.name,'在睡觉')
def work(self,a_money):
print(self.name,'在工作,赚了',a_money)
self.money=self.money+a_money
h1=human('张三',30,'男',5000)
h2=human('李四',35,'男',20000)
h1.eat('火锅',100)
h2.eat('烧烤',200)
h1.work(3000)
h2.work(10000)
print(h1.name,'存款',h1.money)
print(h2.name,'存款',h2.money)
# 开发一个游戏:
# 角色:角色名,性别,等级,体力
# 玩法:练级 等级提升1级
# 打怪 体力消耗 200
# PK 体力消耗300 等级提升1级
# 创建一个王者荣耀游戏:
# 大乔 女 10 1000
# 后羿 男 15 1500
# 超级兵 男 10 2500
# 然后让大乔练级,让后羿去PK,让超级兵去打怪
# 然后查看他们各自的等级和体力
class game:
def __init__(self,a,b,c,d):
self.name=a
self.gender=b
self.level=c
self.power=d
def lianji(self):
print(self.name,'在练级')
self.level=self.level+1
def daguai(self):
print(self.name,'在打怪')
self.power-=200
def PK(self):
print(self.name,'在PK')
self.power-=200
self.level+=1
g1=game('大乔','女',10,1000)
g2=game('后羿','男',15,1500)
g3=game('超级兵','男',10,2500)
print('游戏开始')
g1.lianji()
g2.PK()
g3.daguai()
print("游戏结束")
print(g1.name,'等级为',g1.level,'体力为',g1.power)
print(g2.name,'等级为',g2.level,'体力为',g2.power)
print(g3.name,'等级为',g3.level,'体力为',g3.power)
(3)面向对象三大特征
1)封装
封装的目的是保护类中成员(属性和方法)的安全性,由于在类的外面可以随意访问属性和方法,相对来说不安全,所以将一部分的成员进行封装,在类的外面就不可以随意使用,在类的里面使用不受影响。
封装的方法:将类的成员私有化,在名称前面加两个下划线。
2)继承
让一个类B继承另一个类A,类B被称为子类,类A被称为父类。
子类继承父类之后,可以拥有父类的属性和方法(私有除外)。
父类一般定义一些共性;子类一般实现个性。
子类继承父类的格式:
class 子类名(父类名):
七、web自动化测试:selenium
1.自动化测试介绍
传统的手工测试:人为的验证软件是否符合需求
自动化测试:使用自动化脚本来试验软件是否符合需求
(1)自动化测试的分类
1.UI层(UI自动化):针对界面的自动化测试:selenium(web端)、Appium(APP端)、QTP(web端)
2.接口层(接口自动化:API):Python+requests、jmeter+ant+jenkins
3.单元层(单元自动化:unit):通常是开发人员编写单元测试代码
(2)自动化测试流程
1.熟悉需求,进行需求分析
2.编写测试计划,测试方案
3.根据功能测试用例,编写自动化脚本(自动化测试用例),用自动化测试代码,描述测试用例的操作步骤
4.执行自动化脚本,生成测试报告
为什么要做自动化测试?
传统的人工测试,需要消耗较多的人力,并且有大量重复工作,自动化测试能够通过自动化代码,自动的去运行测试脚本,完成大部分重复工作,提高了测试效率
如何理解自动化测试能够提高测试效率?
1.自动化测试可以用于回归测试,回归验证bug
2.自动化测试还可以用于兼容性测试:自动化脚本可以在不同的浏览器上重复运行
(3)自动化测试的局限性
自动化测试的局限性决定了自动化测试无法取代人工测试
1.自动化不是所有功能都可以做自动化的,比如说:验证码,支付功能
2.自动化脚本不能发现新的bug:代码已经规定了自动化测试要如何运行,操作步骤已经写死在代码里,不像人一样,具备创造性思维
2.自动化环境搭建
1.python安装
2.pycharm:用于编写自动化代码
3.安装selenium:cmd输入:pip install selenium==3.14.0
验证是否安装成功:pip list
4.安装浏览器驱动:
注意:驱动要和浏览器以及浏览器的版本一致,如果驱动版本和浏览器版本不一致,会导致代码无法运行
以谷歌浏览器为例:
1.打开下载谷歌驱动的网址:http://npm.taobao.org/mirrors/chromedriver/
2.下载后解压,并把解压后的Chromedriver.exe复制到Python的安装目录
如何查看Python安装目录:
cmd输入:where Python
如果是win7电脑:
1.把Chromedriver.exe复制到谷歌浏览器的安装目录
5.启动Tomcat浏览器
1.配置JRE_HOME环境变量
值为:C:\Program Files\Java\jre1.8.0_131(jre的路径)
2.打开apache-tomcat-8.5.73目录--bin--(Windows)--startup.bat
3.浏览器输入(http://localhost:8080/),成功连接上Tomcat网页即可
3.自动化脚本编写的基本思路
1.导入selenium:
from selenium import webdriver
2.创建一个driver驱动,并打开浏览器:
driver=webdriver.Chrome()
3.打开网址:driver.get("网址")
4.进行元素定位,定位要操作的元素:
id定位:driver.find_element_by_id("id值")
5.进行元素操作:
输入文字:send_key("文字")
点击:.click()
清空:.clear()
6.退出浏览器:driver.quit()
7.等待方式:
强制等待:import time
4.元素的8中定位方式
(1)id定位
driver.find_element_by_id("id值")
(2)name定位
driver.find_element_by_name("name值")
(3)class定位
driver.find_element_by_class_name("class值")
注意:如果class的值内容有空格,则只需要写其中一部分,不能包含空格
(4)tag定位
使用标签名定位,使用范围非常小,只使用于一个页面只有一个唯一标签时,才能用
driver.find_element_by_tag_name("标签名")
(5)link_text定位
这种方式只使用于定位a标签
driver.find_element_by_link_text("连接的完整文本")
(6)partial_text定位:
driver.find_element_by_partial_text("连接的部分文本")
(7)xpath定位
大部分元素都使用xpath定位
1.复制对应元素的xpath
2.driver.find_element_by_xpath('xpath的路径')
扩展:
xpath公式:
//标签名[@属性="属性值"]
*代表任意标签
谷歌浏览器的控制台判断xpath是否存在:
$x('xpath')
(8)css定位
driver.find_element_by_css_selector()
1)css的id定位
driver.find_element_by_css_selector("#id值")
例:driver.find_element_by_css_selector("#kw")
2)css的class定位
driver.find_element_by_css_selecor(".s_类名")
如果类名有空格,写一部分即可,不能包含空格
例:driver.find_element_by_css_selecor(".s_btn")
3)css的组合属性
属性可以是一个,也可以是多个
单个属性:
driver.find_element_by_css_selector('属性="属性值"')
例:driver.find_element_by_css_selector('id="password"')
2个属性:
driver.find_element_by_css_selector('[属性1="属性值1"][属性2="属性值2"]')
例: driver.find_element_by_css_selector('[id="password"][name="password"]')
4)css的标签和属性
driver.find_element_by_css_selector('标签[属性="属性值"]')
例:driver.find_element_by_css_selector('input[id="userName"]')
注意:部分定位,元素的属性可能会重复,比如class的值可能会对应有多个同样的标签,需要选用合理的定位方式
8中定位方式总结:
id最简单,并且效率最高,有id的情况,一般是选用id定位
如果没有id,通用的方式可以xpath,或者结合实际的html元素,选用不同的定位方式
4.web自动化测试:selenium
(1)常用的浏览器操作
from selenium import webdriver
一、浏览器的基本操作
1.打开浏览器:
谷歌浏览器:driver=webdriver.Chrom("驱动文件的路径")
火狐浏览器:driver=webdriver.Firefox()
ie浏览器:driver=webdriver.IE()
注意:不同的浏览器,要把浏览器对应的驱动,存放到Python安装路径和浏览器的安装路径下
2.打开网页:
driver.get("网址")
3.关闭浏览器:
退出浏览器:driver.quit()
关闭浏览器窗口,不会销毁driver:driver.close()
4.最大化浏览器:
driver.maximize_window()
5.最小化窗口
driver.minimize_window()
6.指定窗口大小
driver.set_window_size(300,600)--300是宽度,600是高度
7.后退:driver.back()
8.前进:driver.forward()
9.获取浏览器窗口的标题:driver.title
10.获取浏览器的url:driver.current_url
11.刷新:driver.refresh()
(2)多窗口处理
1.获取所有窗口句柄:
句柄:浏览器窗口的随机编号
h1=driver.window.handles
2.获取当前窗口句柄:
driver.current_window_handle
3.切换窗口句柄:
driver.switch_to.window(h1[1])
(3) 弹框处理
弹框确定:driver.switch_to.alert.accept()
弹框取消:driver.switch_to.alert.dismiss()
获取弹框提示文本:driver.switch_to.alert.text
弹框输入:driver.switch_to.alert.send_keys("输入的文本")
(4)常用的元素操作
1)基本元素操作
el=driver.find_element_by_id("id")
1.点击:el.click()
2.获取元素的文本:
el.text
注意:这种方式只能获取在开始和结尾标签之间的文本
3.获取元素属性的值:
el.get_attribute("属性名")
4.输入文本框:el.send_keys("文本")
5.清空文本框:el.clear()
2)框架操作
框架相关的标签:iframe,frameset,frame
在框架内的元素,需要先切换到框架内部,才能去定位操作框架内的元素
1.切换框架:
driver.switch_to.frame
切换到框架里面后,如果要操作框架外面的元素,需要先切换回主页面
2.切换回主页面:
driver.switch_to.default_content()
思考:为什么要添加等待?
time sleep(2)
由于代码的执行速度非常快,网页的元素操作相对较慢,所以需要让代码等待一段时间,再去运行后续的代码
3)下拉框操作
1.定位下拉框元素:
s=driver.find_element_by_tag_name("select")
2.导入处理下拉框的类:
from selenium.webdriver.support.select.import Select
3.三种选中操作
(1)通过下标选中
Select(s).select_by_index(1)
(2)通过value选中
Select(s).select_by_value("value值")
(3)通过文本选中
Select(s).select_by_visible_text("下拉文本内容")
4.四种取消选中操作:
(1)通过index(索引、下标)取消:
Select(s).deselct_by_index(1)
(2)通过value取消:
Select(s).deselect_by_value("value值")
(3)通过文本取消选中:
Select(s).deselect_by_visible_text("下拉文本内容")
(4)全部取消:
Select(s).deselect_all()
(5)鼠标键盘操作
1)鼠标操作
左键点击:.clicl()
1.导入鼠标操作的包:(也可以快捷键alt+enter键)
from selenium.webdriver.common.action_chains import ActionChains
2.定位要进行鼠标操作的元素:(鼠标每一种操作前都需要先进行元素定位)
el=driver.find_element_by_id("id值")
3.进行对应的鼠标操作:
3.1.鼠标左键双击:
ActionChains(driver).double_click(el).perform()
3.2.鼠标悬停:
ActionChains(driver).move_to_element(el).perform()
3.3.鼠标右击:
ActionChains(driver).context_click(el).perform()
2)键盘操作
思路:
1.导入键盘操作的包:(也可以快捷键alt+enter键)
from selenium.webdriver.common.keys.import Keys
2.定位键盘操作的元素:
el=driver.find_element_by_id("id值")
3.进行键盘操作:
单个按键:el.send_keys(Keys.键名)
例:el.send_keys(Keys.ENTER)
组合按键:el.send_keys(Keys.键名,"键名")
例:el.send_keys(Keys.CONTROL,"a")(control+a)代表全选
(6)执行js
负责用户和浏览器之间的交互
注意:selenium如果要操作网页上的元素,元素必须在浏览器窗口的可见范围内,否则无法操作
1定义js:
js="js语句"
js="window.scrollTo(0,1000)"
2.执行js:
driver.excute_scripts(js)
(7)Unittest框架
1)框架的介绍
框架规定了代码的整体结构
unittest框架的规范:
1.测试文件名以:test_开头
例:test_lexian
2.测试类必须是:Test开头
3.测试方法: test_开头
2)框架的运行逻辑
1.导入unitest:import unittest
2.创建测试类,并继承unittest
class TestLexian(unitest.TestCase)
3. 前置: setUp()
作用:
1.可以用于封装测试用例的一些前置公共操作
运行逻辑: 在运行每一个测试方法之前,都会先运行前置setUp()
4. 测试方法:test_开头
运行顺序: 0-9,A-Z,a-z
5. 后置:tearDown()
作用: 用于封装测试用例的公共后置操作
运行逻辑: 在运行每一个测试方法之后,都会运行后置tearDown()
5. 断言:
作用: 判断预期结果和实际结果是否一致
如果预期结果和实际结果一致,则断言通过
如果预期结果和实际结果不一致,则断言失败
预期结果: 人为定义
实际结果: 脚本在运行的过程中,产生的实际结果
断言的方法:
1. assertEqual(a,b): 判断a和b是否一致,如果一致,则断言通过
2. assertNotEqual(a,b): 判断a和b是否不一致,如果不一致,则断言通过
3. assertIn(a,b): 断言a是否被b包含
4. assertNotIn(a,b): 断言a是否不被b包含
5. assertTrue(判断表达式),如果表达式为真,则断言通过
6. assertFalse(判断表达式),如果表达式为假。则断言
3)批量运行测试用例,并生成测试报告
批量运行测试用例,并生成测试报
1.指定测试用例文件的路径:
case_path = r"D:\test_selenium_38\testcase"
2.指定测试用例文件的路径下,寻找要运行的测试用例,并赋值给测试套件:
suite=unitest.defaultTestLoader.discover(case_path,pattern="test_*")
3.指定测试报告的路径和测试报告文件名
report = r"D:\test_selenium_38\report\report.html"
4.以二进制的方式,打开测试报告
f = open(report,"wb")
5.批量运行测试用例,并生成测试报告
HTMLTestRunner.HTMLTestRunner(f,title="报告题",description="报告的描述").run(suite)
6.关闭测试报告文件写入:
f.close()
(8)配置管理
1)定义
配置:在软件开发生命周期(计划,需求分析,设计,编码,测试,运维,废弃)整个过程中,所有软件资产的综合叫配置。比如:合同,需求规格说明书,调研报告,会议纪要,设计规格说明书,评审报告,测试用例,测试计划,源代码,测试环境,测试工具等。
2)为什么要进行配置管理
1.对所有的配置信息进行统一管理,避免由于人员的流逝造成软件配置的丢失
2.在项目组内部共享项目资料时,保证资料的版本一致性和安全保密性;
3.对项目变更过程进行管理和控制
3)配置管理做什么?
1.版本管理:
对项目资料进行统一版本管理
2.变更管理:
在配置管理中对于项目的变更进行严格的控制。一般项目资料在评审通过后,都会进入管控范围,如果需要变更,要走变更流程。变更流程:首先发起变更申请,由项目组开会讨论变更影响范围,来决定是否允许变更。如果影响特别大,可以不允许变更,驳回变更申请;如果能接收变更影响,就允许变更。然后相应需要变更修改的材料进行修改,然后再次对变更的相关材料再次评审,评审通过,变更完成,评审后的材料纳入管控范围,形成一个新的版本。
3.过程管理:
对软件开发过程中产生的过程文档进行统一的管理。
4.配置管理由谁来做
配置管理一般由项目经理来指定管理计划,然后由配置管理员来负责实施,项目组的其他成员(开发、测试)参与
5.配置管理工具:
配置管理一般通过工具来辅助完成。
常用工具: SVN、git
6.SVN工具常用操作:
工具原理:
SVN是分为服务端和客户端。
SVN服务端:用来创建、维护、管理项目资料库,创建和授权SVN用户。一般由配置管理员来进行维护操作。
SVN客户端:用来访问SVN的服务端,从服务端上下载或者上传项目资料。一般给项目的成员去使用。
准备工作:
1.在工作电脑上安装SVN客户端:TortoiseSVN-1.14.0.28885-x64-svn-1.14.0.msi
2.跟配置管理员,获取项目svn库的url,以及个人的svn账号。
svn的URL:https://172.30.63.23/svn/crm38/(一个项目一个url)
svn的账号:
(1)svncheckout==检出
作用:在第一次进入项目组时,一次性将项目组svn的所有资料下载到本地个人电脑
步骤:
1)进入到自己想要存放项目资料的目录,比如:c:\svn
2)
(3)updeat==更新
作用:将svn上更新(增加的文件/文件夹,修改的文件,删除的文件或文件夹)的资料下载到本地。
步骤:在D:\svn目录上点击右键,选择svn Update
(4)commit==提交
作用:将个人电脑上的资料提交到svn资料库中。
操作:在D;/svn目录上点击右键,选择svn commit
注意:更新或者提交的操作可以针对整个项目库,也可以针对项目库中某一级的文件或者文件夹,如果选择的是某一级的文件或者文件夹,那么更新或者操作只针对一级有效。
(9)selenium中的三种等待
在进行UI自动化时,第一步就是进行元素定位,通常会出现页面与水泥素还未加载出来,页面元素定位不到的问题。所以需要在代码中添加等待来让浏览器完成页面的加载,才能进行定位。
1.强制等待
sleep(等待时间)
sleep方法是python中内置的方法,作用是当代码运行到sleep时,强制暂定运行设置的时间。
特点:等待时间是固定。由于受到外界环境的影响,有些情况页面块,有些时候页面加载慢,如果设置固定的等待时间,可能会出现,有时候时间等的不够,页面还没加载出来,有时候出现时间多了,浪费时间的问题。
2.隐形等待
implicitly_wait(最大等待时间)
特点:等待时间不是固定,设置的最大等待时间,如果等到了,就继续马上往下执行。
一般的用法:driver.impolicitly_wait(最大等待时间)
等待的是整个浏览器页面的加载,需要等到页面上所有元素加载完成才能继续往下执行。
3.显性等待
使用WebDriverWait类,来进行元素等待
一般是将等待封装成一个方法,然后在需要使用的地方直接调用就可以了。
特点:针对页面上具体的一个元素进行等待
(10)selenium中的Excel操作
在实际工作中,通常会将测试数据与代码进行分离,方便统一维护管理测试数据,减少代码量。
一般可以将测试数据放在单独Excel、txt、csy、yaml等格式的数据文件中,然后从这些数据文件中读取测试数据,在测试用例代码中使用。
安装第三方的包完成对Excel操作,在cmd输入命令:pip install xlrd,安装完成后可以输入pip list检查是否安装成功
九、APP测试
1.认识app的网络架构
web端:是B/S架构
B:浏览器端:指的是运行在浏览器的网页
S:服务端:Tomcat/nginx,mysql,网站的源代码,接口
B==URL==>S
APP端:C/S架构:
C:client:客户端:安装在手机上的应用
S:server:服务端:Tomcat/nginx,mysql,网站的源代码,接口
C==URL==>S
客户端的URL,开发人员已经写死在代码中,不需要用户另外输入
2.认识Android的四大组件
Android:是一个基于Linux的操作系统,Linux发行版之一
1.Activity:活动页面(APP的界面)
例如:淘宝APP的首页
2.BroadCast Receiver:广播接收
例如:微信断网时的断网提示,就是一个广播
3.Content Provider:内容共享,内容提供: 用于APP之间获取数据
例如:支付宝要获取通讯录的数据,支付宝和通讯录两个APP是相互独立的,不能直接获取,需要通过该组件
4.Service:后台服务:后台服务可以常驻在后台,通常用于接收APP的通知
例如:手机上的某个APP没有开,但是也可以接收到该APP的消息通知
为什么Android手机越用越卡?
在以前,国内的安卓手机,每一个APP都会有一个对应的后台服务常驻后台用于接收通知
为了解决该问题,中国信通院和各大国内手机厂商共同组建了:统一推送联盟
安卓在国外也有统一推送服务,由于安卓是谷歌推出的,它的统一推送服务需要依赖谷歌服务
ios的推送:苹果自建了统一推送服务
3.APP和web测试的测试流程
1.两者功能测试基本一致,都是依照需求文档编写测试用例,并执行测试
2.两者的测试流程基本一致:
web端测试流程:
1.需求阶段:熟悉需求,提取功能点
2.计划阶段/编码设计阶段:编写测试计划,测试方案,测试用例
3.执行测试:
前置:搭建测试环境
1.执行冒烟测试
2.按轮次执行测试
3.验收测试(通常由需求方或客户或产品经理来做验收)
4.编写测试报告
5.上线发布,并跟进线上运行情况
web端上线,只需要更新服务器即可
APP端的测试流程:
1.需求阶段:熟悉需求,提取功能点
2.计划阶段/编码设计阶段:编写测试计划,测试方案,测试用例
3.执行测试:
前置:搭建测试环境
1.执行冒烟测试
2.按轮次执行测试
3.验收测试(通常由需求方或客户或产品经理来做验收)
4.编写测试报告
5.上线发布,并跟进线上运行情况
APP的上线:
服务端:更新服务器
客户端:
1.测试通过以后,开发人员提交客户端的安装包到各大应用市场的开发者平台
2.应用市场需要对APP进行审核,审核通过之后,用户可以在应用市场更新最新版本,如果审核不通过根据不通过的原因进行修改,并重新测试,然后再重新上传应用市场
用户如何更新客户端:
1.应用市场更新
2.应用内消息推送更新
3.自己下载最新的APP包来更新
4.app和web测试的区别
(1)网络架构不一样
web端是BS架构,没有客户端,不需要进行安装卸载测试
APP端是CS架构,有客户端,需要对客户端进行安装,卸载,升级测试
1.安装测试:
apk文件:Android系统
安装方式:
1.应用市场安装
2.下载安装包安装
3.电脑上的手机助手,也可以给手机安装app
4.使用adb(工具)命令进行安装
测试点:
基本流:1.使用不同的安装方式,能否正常安装APP,并能正常启动APP
备选流:
1.存储空间不足导致安装失败时,能够重新安装
2.安装过程中突然中断(手机关机,手动终止安装进程),导致安装失败,能够再次进行安装
3.覆盖安装,能否安装成功:覆盖安装,可能会覆盖低版本的APP,也可能会覆盖高版本的APP,两者都要能正常安装
4.卸载后,能够重新正常安装
5.安装是否会被杀毒软件拦截
6.安装过程中,把安装界面退到后台,能够正常继续安装
7.安装过程中,手机占用CPU内存较大(比如打王者),如果安装失败,可以再次安装
8.使用损坏的安装包导致安装失败时,再次使用正常的安装包,能重新安装
卸载测试:
卸载的方式:
1.桌面长按卸载
2.应用市场卸载
3.使用第三方工具卸载
4.adb命令卸载
5.电脑上的手机助手,也可以卸载APP
6.系统设置-应用管理-卸载
卸载的测试点:
基本流:1.使用不同的卸载方式,能够正常卸载
备选流:1.卸载是否干净
2.卸载后是否能够重新安装
3.能否多次卸载重装
4.卸载过程被中断(断电,CPU占用过高),后续还能够重新进行卸载
5.如果卸载有残留文件,是否能够再次安装
6.卸载过程中进行安装,是否能正常卸载(实际工作中可以不用考虑这点)
升级测试:
客户端的升级:
1.应用市场升级
2.应用内升级
3.高版本安装包覆盖安装升级
4.电脑上的手机助手,能否进行升级
升级的测试点:
基本流:使用不同的方式,能否正常升级
备选流:
1.升级弹框提示:
(1)有新版本时,能够弹出升级提示
(2)没有新版本时,不会弹出升级提示
(3)升级的提示内容是否正确
2.强制升级,能否正常升级
3.升级以后,客户端的版本是否正常
4.新升级的功能是否正常
5.取消升级,后续还能够继续升级
7.下载APP后,如果退出APP,下一次启动APP要能够成功弹窗提示用户是否更新
(2)兼容性测试不一样
兼容性测试:验证软件在不同环境下的依赖程度
web端的兼容性:
1.不同的浏览器
2.同一浏览器的不同版本
3.操作系统
4.分辨率
app的兼容性:
1.硬件环境:机型品牌(CPU),屏幕(分辨率):挖孔屏,刘海屏,折叠屏,曲面屏,现在有新的卷轴屏,屏幕会直接影响到APP界面的展示,甚至可能遮挡APP的某些功能按钮
2.软件环境:
1.操作系统:Android,iOS,harmonyOS
2.UI系统:MIUI,EMUI,ColorOS
3.和第三方软件的兼容:主要是指有数据交互的软件的兼容,杀毒软件
例:分享抖音视频到微信
3.网络环境:不同运营商(移动,联通,电信)的2g,3g,4g,5g网络,WiFi
如何执行APP的兼容性测试?
注意:实际测试的时候,禁止使用模拟器进行测试
挑选市场是主流热销的机型和用户主流的操作系统及版本:
(可以参考各大电商网站的销量网站:)站:
1.大数据统计网站:百度移动统计:https://tongji.baidu.com/research/app
2.云测网站:testin
3.云真机:腾讯wetest
4.自动化脚本:APPium
(3)app的push测试
push:推送通知
push测试主要测试通知
通知的测试点:
1.基本流:通知能够正常推送到用户的通知栏,通知内容正确
2.备选流:
1.通知的应用图标,通知的标题,通知的跳转是否正常
2.通知推送的逻辑:
1.什么时候推送:验证推送的时间是否准确
2.个性化推送:验证个性化推送逻辑
个性化:指的是不同用户群体,喜好不一样,根据用户的喜好,来进行推送
3.条件推送:满足特定条件时,会触发推送
3.推送失败的重试机制是否正常
4.免打扰时间段:在用户设置的免打扰时间段内,不推送通知给用户
5.查看推送的消息能够跳转到APP对应的页面查看
通知屏蔽:本质上不属于推送失败,只是操作系统隐藏了通知。
(4)权限测试
权限:是由操作系统管理的,不同的操作系统,权限机制可能不太一样
权限分为两大类:
一般权限:该类权限不涉及到用户隐私数据,系统会自动授权
例:联网,震动等
危险权限:该类权限涉及到用户隐私数据,需要用户手动授权
例:位置信息、摄像头、麦克风、存储、电话(移动网络信息)、短信、通讯录、传感器、运动健康
在进行APP权限测试时,实际是测试依赖这些危险权限的功能使用情况
当给APP不同的权限时APP的使用情况,以及是否能够正常使用
权限操作:
允许权限
拒绝权限
仅在运行期间允许
拒绝后不再提示
仅本次允许
权限测试的测试点:
1.允许权限后,依赖权限的功能能够正常运行
2.拒绝权限后,依赖权限的功能不会出现闪退崩溃等异常,能够提示用户进行对应的授权操作(用户体验感)
3.拒绝权限后,再次允许权限,依赖权限的功能能够正常运行
4.仅在运行期间允许:软件在运行的时候,依赖权限的功能能够正常运行
5.拒绝后不再提示:拒绝权限,并勾选不再提示,依赖权限的功能不会闪退崩溃,并能够引导用户授权
6.仅本次允许:本次运行时依赖权限的功能能够正常运行,并且下一次运行会提示用户是否授权
7.多次允许,拒绝权限,再次允许权限后,依赖权限的功能能够正常运行
(5)交叉事件测试
(中断测试)
某个功能正在运行时,出现的会影响该功能运行的事件
例:正在支付的时候,突然有一个来电,会导致手机自动切换到2G网络,可能导致支付失败
手机的运行场景相对复杂,手机上正在运行的功能,可能会受到一些突发的交叉时间的影响
常见的交叉事件:
来电
短信
弹框提示
前后台切换
低电量提示
关机重启
断网
插入耳机
插入USB
麦克风:正在录音时,来了一个电话两者都需要用到麦克风,可能会冲突
摄像头:在拍照的时候,突然发来一个微信视频两者都需要用到摄像头,可能会冲突
物理按键:音量键,电源键(在看视频的时候按了电源键)
音频播放
蓝牙传输
(6)用户体验测试
web端的用户操作更关注鼠标键盘操作
APP操作更注重收拾滑屏操作
APP的报错:
1.crash:崩溃
2.ANR:应用程序无响应
3.exception:异常
5.APP的稳定性测试
什么是APP稳定性测试?
monkey首选,一般软件要求能够长时间稳定不出现问题地持续运行,为了校验系统版本是否稳定,是否能够持续为用户进行服务。
monkey是随机进行各类操作指令,确保APP能够稳定,不出现任何的奔溃异常情况
(1)monkey的原理
只有Android系统才有monkey,其本身是安卓操作系统下的一个jar文件,是在进行调用之后,生成了系统进程,基于进程来执行的monkey。
monkey其实就是monkey.jar文件,通过adb指令调用monkey.jar文件。基于配置,实现随机性测试
为啥要讲monkey测试指令
1、是目前企业中对于APP稳定性使用度很高的指令
2.因为APP测试现在是市场中比较主流的东西
adb monkey--monkey.shell--monkey.jar--安卓进程执行测试
(2)monkey指令
1.搭建环境:
SDK环境,通过sdk manager进行安装
一台手机或者模拟器
2.连接手机设备
通过adb devices指令进行连接
devices--已识别设备
unkown--未识别设备
offline--离线设备
3.monkey操作
adb shell--连接手机
-p 指定被测试程序或者包(可以通过pm list package查看所有的包)
events 事件数
adb shell monkey -p 包名 200(对该包名随机执行200次事件,并且速度很快)
--throttle 等待,每次事件之间,插入的等待操作(以毫秒为单位)
adb shell monkey -p 包名 --throttle 300 200(对该包名随机执行200次事件,并且每次事件之间间隔3秒等待)
-v 添加日志
缺省:lv0(0级)
-v(1级)
-v-v(2级)
-v-v-v(3级)
adb shell monkey -p 包名 --throttle 300 -v -v 200()
当我们monkey中出现异常的时候,一定要重现bug,就需要monkey再按照之前的行为执行一次
通过-s指令为本次的monkey运行设置编号,当下次要重现bug的时候,再重新执行以下命令即可
adb shell monkey -s 1 -p 包名 --throttle 300 -v -v 200
这时候seed=1(如果没有设置编号之前,seed值是随机生成的一串数字)
在运行过程中,除了kill指令与monkey结束之外,出现异常、奔溃等情况monkey也会停止
–ignore-crashes 忽略在系统出现crash(奔溃)时导致的monkey挂起
–ignore-timeouts 忽略在monkey运行过程中,因为ANR(Application Not Responding--无响应)导致的挂起
–ignore-security-exceptions: 指应用程序发生许可错误,monkey依然发送事件,直到事件数完成
adb shell monkey -p 包名 -s 1 --throttle 300 -ignore-crashes --ignore-timeouts --ignore-security-exceptions -v -v 200>d:rizhi.txt(把日志以TXT格式保存到d盘)
当关键字是一个字母是,用-
当关键字是一个单词时,用--
如果日志有异常,就直接打开该TXT文件,Ctrl+f搜索“crash”,“exception”,“timeout”关键字定位到报错的位置找出问题
事件类型参数:
--pct-touch(百分数)--只执行对应的操作,或者按照百分比来执行对应的操作
monkey支持的操作类型由如下:
轻触:--pct-touch
动作(长按):--pct-motion
轨迹球(滑动、拖拽):--pct-trckball
基本导航(向上/向下/向左/向右):--pct-nav
主要导航(菜单键/返回键/方向键的中间按钮):--pct-majornav
系统按键(主屏幕/返回/发起通话/结束通话/音量控件):--pct-syskeys
activity(活动页面)启动次数(monkey会以随机间隔发起startActivity()调用,以最大限度地覆盖软件包中所有):Activity--pct-appswitch
其他类型(所有其他类型的时间,例如按键,设备上其他不太常用的按钮等等):--pct-anyevent
adb shell monkey -p 包名 -v 1000 -s 123 --throttle 2000 --pct-touch 100
例如:adb shell monkey -p 包名 -v -v -v --pct-touch 100 20 (执行20次100%都为触摸事件这里触摸事件为100%,则没有其他事件)
十、adb工具
adt开发环境的搭建: Android Development Tools:安卓开发者工具集
adb(Android debug bridge 安卓调试桥)是一个命令行工具,作用是用于pc连接安卓设备(安卓模拟器、真机)
adb命令,对设备进行操作,并且监控设备运行情况。如APP安装,卸载,查看电池情况,上传下载文件等。
1.adb环境搭建
(1)安装jdk
由于Android是基于java开发的,所以要先安装jdk,jdk是java程序的运行环境
(1)安装软件:jdk-8u231-windows-x64.exe
(2)配置java环境变量:(环境变量相当于命令行的快捷方式)
Windows进入环境变量:我的电脑--右键(属性)--高级系统设置--高级(环境变量)--系统变量
1)在系统变量,新建一个JAVA_HOME变量,值为jdk的安装目录
2)在系统变量,编辑path变量,在值的最前面加上以下内容:
%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;
3)在系统变量,新建一个classpath变量,值为:
.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;
4)验证环境变量是否配置成功,在cmd输入命令:
java -version
java
javac
(2)安装SDK
SDK(software Development Kit 安卓软件开发组件),作用是对安卓开发程序进行编译,调试,打包等。
SDK中包括adb工具,aapt工具,uiautomatiorviewer工具(UI自动化),ddms等。
1)首先在D盘新建一个Android文件夹;
2)将adt-bundle-windows-x86.rar解压,解压到d:\android
3)配置android环境变量:
(1)在系统变量中,新建一个ANDROID_HOME的变量,值就是第二步中解压后的目录:
d:\android\adt-bundle-windows-x86\sdk
(2)在系统变量中,编辑Path,在最前面加上以下值:
%ANDROID_HOME%\tools;%ANDROID_HOME%\platform-tools;%ANDROID_HOME%\build-
tools\android-4.3;
(3)然后一直点确定
(4)验证android环境变量是否配置成功,重新打开cmd,输入命令:
adb
aapt
ddms
(3)安装安卓模拟器==逍遥模拟器
双击安装XYAZSetup6.1.0.exe
部分系统启动模拟器时,会卡在99%启动不成功,需要升级设备驱动以支持模拟器,下载驱动精灵,升级驱动即可。
在Windows中,直接打开cmd,就可以输入adb命令。
在实际工作中,通常都是用真机来进行测试。pc如何连接真机?
(1)有线连接:真机和电脑在同个局域网;打开手机的开发者选项(USB调试也要打开);将手机和电脑使用USB线连接
(2)无线连接:真机和电脑在同个局域网;打开开发者选项;打开5555端口(adb tcpip 5555),第一次打开端口时,先要有有线连接上,然后开启端口;连接设备(adb connet 设备IP:5555)
电脑连接手机,需要手机打开开发者选项(两个需要勾选,USB调试也要勾选)。如果没有找到开发者选项,可以找到手机的版本号,连续点击7次也可以打开开发者选项。
注意:电脑与手机连接同一个局域网;连接USB线。
2.adb常用命令
(1)查看当前设备
查看当提前连接设备:adb devices
可以查看当前连接了几个设备,连接了多少设备,这里就有多少记录。
如果是模拟器,显示的是IP:端口
如果是真机,显示的是真机序列号,是一串字符串,有数字和英文字母
注意:以后如果需要使用电脑操作设备,都需要先连接上设备,所以先用此命令查看设备是否连接上。
(2)查看版本号
查看adb版本号:adb version
(3)安装APP
安装APP:adb install apk的文件路径(文件可以直接拖到cmd中就会自动输入apk的文件路径)
(1)重复安装:
对于已安装设备,再次安装app时会失败,提示已经存在。
-r 表示覆盖安装,覆盖已安装的版本
命令:adb install -r C:\kaoyan3.1.0.apk
(2)多个设备
如果有多个设备连接电脑,使用adb命令操作设备时,需要指定希望操作哪台设备。如果不指定设备,会报错,如下:
-s 指定设备
命令:adb -s 127.0.0.1:21513 install c:\kaoyan3.1.0.apk
(4)卸载APP
卸载APP:adb uninstall app的包名路径
app包名如何获取?
1)问开发;
2)有apk文件,可以通过apk文件获取:aapt dump badging apk的文件路径
lauchable-activity就是app启动后的启动页。activity就是指app的页面。
3)没有apk文件时:adb shell pm list packages
此命令会将设备中所有已安装的app的所有包名都列出来
(5)进入设备操作系统
由于Android系统是基于Linux内核进行界面化二次开发,所以可以支持部分linux命令
命令:adb shell
进去之后可以查看到手机的具体目录和路径
(6)推送文件
将电脑上的文件传输到设备
adb push 电脑上的文件路径 设备上存储文件的目录路径
(7)拉取文件
将设备上的文件传输到电脑
adb pull 设备上的文件路径 电脑上存储的目录路径
(8)设备截图
1.先截图保存
adb shell screencap 截图文件保存的路径
2.将设备上截图的图片拉取到电脑上
adb pull 设备上的文件路径 电脑上存储的目录路径
(9)查看设备电池情况
adb shell dumps battery
(10)查看当前包名和activity名
adb shell dumpsys window|findstr mCurrentFocus
(11)抓取客户端日志
adb logcat
1.根据日志级别抓取日志
日志级别:
V==明细(最详细)
D==debug调试
I==info
W==warning警告
E==error错误
F==Fatal严重错误
一般我们是关注W以上的级别有错误的日志
adb logcat *:W
2.根据日志时间:adb logcat -v time
3.根据日志级别和时间过滤:adb logcat -v time *:E
4.导出日志到文件:adb logcat >d:\log28.txt
5.根据关键字过滤日志:adb logcat -v time *:E | findstr kaoyan >d:\log28.txt
(12)ddms工具
在命令行输入,ddms命令,打开ddms工具。
3.APP的抓包
1.手机和电脑要在同一个局域网(手机和电脑连同一个WiFi)
2.手机WiFi配置代理服务器(电脑):
配置代理之前,手机网络请求通过WiFi发送到外网
配置代理之后,手机网络请求通过WiFi发送到电脑上的抓包工具,然后流向外网
手机把网络请求发送到电脑,需要手机连接(无线连接)电脑
IP协议规定,网络上互相通信的计算机,必须要有IP地址
1.获取电脑IP:cmd输入ipconfig
2.手机WiFi设置-高级-代理-手动配置:
主机名:电脑ip
端口号:fiddler抓包工具默认8888
4.APP的弱网模拟
弱网:低速率,高延迟
弱网测试关注什么:关注的是,出现弱网时,APP不会出现闪退,白屏等,会有良好的用户提示体验
如何进行弱网模拟:
1.路由器管家,WiFi管理助手等等,可以用于限制网络速度
2.通过网络抓包工具来进行限速
一、Charles弱网模拟:
1.手机和电脑在同一局域网
2.手机WiFi要配置电脑的ip和抓包工具的端口号
3.
5.app客户端的性能测试
1.什么是monkey测试
monkey测试:随机压力测试,主要用于测试APP客户端的稳定性,目的是验证客户端的稳定性(是否会崩溃,闪退(crash),无响应(ANR))
猴子喜欢上蹿下跳,动作毫无规律
优点:随机的操作,能够发现一些人为测试难以发现的bug
缺点:无法针对单一模块进行精准测试
2.如何使用monkey命令
monkey命令:adb shell monkey -p 'com.tal.kaoyan' -v 500
常用参数:-p: 指定报名
-v:日志
数字:monkey时间次数
-s:随机seed值(自己定义值),如果多次monkey指定相同的seed值,则会执行相同的monkey动作,该参数通常用于复现bug
3.monkey运行结果:
1.正常运行:
会显示:
1.monkey finish
2.会显示monkey运行的时间
2.运行出错:
1.不会显示monkey finish,并且不会显示运行时间
2.出错以后,需要把错误日志截图给开发
如果是APP闪退崩溃等:日志中会有crash关键字
如果是APP卡顿无响应:日志中会有ANR关键字
其他异常:Exception
monkey日志写入文件:adb shell monkey -p 包名 -v 次数>日志文件
二、腾讯GT客户端性能监控工具:
客户端性能测试:
客户端性能体现在哪些方面:
CPU:CPU通常占用不能超过80%
内存:占用不能超过80%
流量
帧数:流畅度,帧数越高,画面越流畅
每秒跟新刷新的画面
流畅度,帧数越高,画面越流畅
游戏,直播和视频类应用比较关注帧数
电量:可以使用手机自带的电量统计工具
腾讯GT是腾讯开源的客户端性能测试工具,主要用于客户端的性能监控
CPU和内存占用越低,
十一、APP自动化测试appium
1.appium的介绍
appium是一个开源测试自动化框架,可用于原生,混合和移动web应用程序。它使用webdriver协议驱动iOS,Android应用程序。
appium很多脚本都是参考的selenium操作,实际上很多自动化测试都是参考的selenium。
原生APP:纯java语言开发
混合APP:java和html语言组合开发--APP的一些页面,直接使用H5开发
移动web APP:纯html前台语言开发
Appium的优势:
可以跨平台同时支持Android,iOS
支持多中语言,java,python、PHP、Ruby等等
2.Appium自动化原理
Appium是在手机操作系统自带的测试框架基础上实现的,Android和iOS的系统上使用的工具分别如下:
Android(版本>4.3):UIAutomator,Android 4.3之后系统自带的UI自动化测试工具。
Android(版本≤4.3):Selendroid,基于Android Instrumentation框架实现的自动化测试工具。
iOS:UIAutomation(instruments框架里面的一个模板),iOS系统自带的UI自动化测试工具。
3.Appium的工作原理
通过pycharm运行python代码--脚本代码发送appium服务器--appium服务器来驱动设备
客户端编写相关的代码自动化脚本,通过appium server 提供的端口号4723,接受客户端相关的命令,并解析成UIAutomator认识的命令。Appium server解析完命令,就发送给手机端,手机端中有一个Bootstrap.jar 处理appium server的命令,命令整理完后,发给手机中的UIAutomator库,UIAutomator 实现页面操作。
4.Appium环境搭建
1.配置jdk。--配置JAVA_HOME 验证:javac
配置环境变量的原理:可执行文件(.bat和.exe)的路径添加至path中
提前创建了JAVA_HOME,这是一个变量(jdk的路径):
注意:修改path中,
2.配置AndroidSDK。--配置SDK的环境;
SDK的版本是多少?
按照V25,一般是基于Android7以上。
SDK测试:安卓的开发工具包,以后的APP测试大部分都会涉及到SDK测试。内部项目和外部接口/开发工具的软件兼容,测试兼容后的一个整体情况。具体测试包含一些功能,兼容性,安装卸载升级···
例:我公司开发一款捕鱼游戏,和腾讯合作,把捕鱼的账户系统换成腾讯账户系统,谈收益比例。---达到双赢
3.配置模拟器。--配置逍遥游模拟器。
(实际工作中,可以说配置真机连接,手机安装好驱动)
4.配置python--pycharm(编译器)方便编写代码
5.安装node.js--添加path
6.安装appium服务器
7.安装appium-python-client(用python封装的操作appium通讯的模块)
5.Appium的快速体验
1、导入包:
from appium import webdriver
2、声明手机驱动对象
driver=webdriver.Remote(“http://127.0.0.1:4723/wd/hub”,desird_caps)
3、手机启动参数
desired_caps:负责启动服务端时的参数设置,appium server 与手机端建立会话关系时,根据这些参数服务端可以做出相应的处理
desired_caps常用参数:
platformName:平台的名称:iOS,Android or FirefoxOS platformVersion:设备系统版本号
deviceName:设备号 IOS:instruments --s devices,Android: adb devices
app:安装文件路径:/abs/path/to/my.apk or http://myapp.com/app
appActivity:启动的Activity
appPackage:启动的包
unicodeKeyboard:unicode设置(允许中文输入)
resetKeyboard:键盘设置(允许中文输入)
noReset:清除缓存 False则清除,True则不清除
6.注意事项
当appium脚本运行报错后,修复完代码后不要立即运行脚本。因为运行appium报错了实际上driver没有退出?
1.要么等一会儿,让系统回收driver
2.重启appium-sever 关闭,重新打开。 主动回收。
3.还有一个最方便的方法:服务器点设置然后勾选覆盖已退出会话
首次启动Appium会在设备上自动安装2个守护app,Appium Settings和Unlock 部分设备系统
由于权限的问题(如:三星S6 edge+)需要用户手动确认安装,否则不安装守护App会导致脚本运行失败,安装好后不要随意卸载这两个App。
• Unlock :用于解锁手机弹窗提示
• Appium Setting:Appium守护app
7.Appium的基本定位
元素定位:元素的基本定位基于当前屏幕范围内展示的可见元素。
可以通过属性元素定位:类似于selenium
借助于Android-sdk中的另外一款工具:uiautomatorviewer来查看app界面元素的属性;
(1)id定位
appium的id属性也就是通过-----> resource-id属性
日常生活中身边可能存在相同名字的人,但是每个人的身份证号码是唯一的,在app界面元素中也可以使用id值来区分不同的元素,然后进行定位操作。Appium中可以使用 find_element_by_id() 方法来进行id定位。
例:定位设置中搜索功能
driver.find_element_by_id('com.android.settings:id/search').click()
(2)accessibility_id定位
accessibility_id定位就是通过---->content-desc属性
例:定位设置中搜索功能
driver.find_element_by_accessibility_id('搜索').click()
(3)class_name定位
class定位就是通过----->class属性(一般页面上的class属性不唯一,元素不唯一的话定位就会错了)
例:elements=driver.find_elements_by_class_name('android.widget.TextView')
(4)name定位
name定位 ---->text属性
说明:由于text稳定性不是很好,所以appium 1.5开始废弃了该方法。
例:driver.find_element_by_name('提示音和通知').click()
(5)xpath定位
xpath定位是一种路径定位方式,主要是依赖于元素绝对路径或者相关属性来定位,但是绝对路径xpath执行效率比较低(特别是元素路径比较深的时候),一般使用比较少。通常使用xpath相对路径和属性定位。
例:driver.find_element_by_xpath("//android.widget.TextView[@text='蓝牙']").click()
8.Appium的基础操作
(1)在脚本内启动其他APP
应用场景:
如果一个应用需要跳转到另外一个应用,就可以使用这个api进行应用的跳转;
方法名和参数:
appPackage:要打开的程序的包名
appActivity:要打开的程序的界面名
driver.start_activity('app包名','appActivity名')
例:
driver.start_activity('com.tal.kaoyan','com.tal.kaoyan.ui.activity.SplashActivity')
(2)获取APP的界面名
应用场景:
当我们从一个应用使用跳转到另外一个应用的场景时,需要获取另外一个app的信息属性名:
获取界面名:driver.current_activity
例:
driver.find_element_by_name('蓝牙').click()
print(driver.current_activity)
aapt:获取包名和activity,前提能够拿到那个apk包。
adb中:adb shell dumpsys window | findstr mCurrentFocus 可以直接获取当前的包名和activity名
(3)关闭app和驱动对象
应用场景:closed是关闭当前窗口,quit是关闭所有的窗口;
有的时候我们需要关闭某个应用程序后,再打开新的应用,那么如何关闭应用程序呢?
方法:
关闭当前操作的app,不会关闭驱动对象:driver.close_app()
关闭驱动对象,同时关闭所有关联的app:driver.quit()
(4)安装和卸载以及是否安装app
应用场景:appium只是保留了这个功能
一些应用市场的软件可能会有一个按钮,如果某一个程序已经安装则卸载,如果没有安装则安装;
方法名:
安装app:driver.install_app(app_path)
例:
driver.install_app(r'E:\课件\appium\appium\kaoyan3.1.0.apk')
卸载app:driver.remove_app(app_id)
例:driver.remove_app('com.tal.kaoyan')
判断app是否已经安装:driver.is_app_installed(app_id)
例:driver.is_app_installed('com.tal.kaoyan')
(5)应用置于后台
应用场景:银行类app会在进入后台一定时间后,如果再回到前台页面会重新输入密码。
方法:
drvier.backgroud_app(seconds)
9.Appium对元素操作
(1)获取元素的文本内容
获取文本内容--text
例:driver.find_element_by_name('蓝牙').text
(2)获取元素在屏幕上的坐标
方法:location
同时获取x轴和y轴坐标
driver.find_element_by_name('蓝牙').location
单独获取x轴坐标
driver.find_element_by_name('蓝牙').location['x']
单独获取y轴坐标
driver.find_element_by_name('蓝牙').location['y']
(3)获取屏幕分辨率
方法:get_window_size
例:driver.get_window_size()
print("屏幕的横坐标为:{}".format(window_size['width']))
print("屏幕的纵坐标为:{}".format(window_size['height']))
(4)根据属性名获取属性值
方法:get_attribute
例:driver.find_element_by_name('蓝牙').get_attribute('text')
(5)点击/输入内容/清空
方法:click;send_keys;clear
例:
driver.find_element_by_id('com.android.settings:id/search').click()
driver.find_element_by_id('android:id/search_src_text').send_keys('test')
driver.find_element_by_id('android:id/search_src_text').clear()
10.滑动和拖拽事件
(1)swipe滑动事件
从一个坐标位置滑动到另一个坐标位置,只能是两个点之间的滑动
方法:swipe(start_x, start_y, end_x, end_y, duration=None)
参数:
start_x:起点X轴坐标
start_y:起点Y轴坐标
end_x:终点X轴坐标
end_y:终点Y轴坐标
duration:滑动这个操作一共持续的时间长度,单位:ms
例:
x=driver.get_window_size()['width']
y=driver.get_window_size()['height']
x1=x*0.5
y1=y*0.8
x2=x*0.5
y2=y*0.2
driver.swipe(x1,y1,x2,y2,duration=500)
(2)drag_and_drop拖拽事件
从一个元素滑动到另一个元素,第二个元素替代第一个元素原本屏幕上的位置
方法:drag_and_drop(origin_el, destination_el)
参数:
origin_el:滑动开始的元素
destination_el:滑动结束的元素
例:
battery=driver.find_element_by_name('电池')
more=driver.find_element_by_name('更多')
driver.drag_and_drop(battery,more)
11.高级手势--长按
先导包:from appium.webdriver.common.touch_action import TouchAction
方法:TouchAction中的long_press
示例:长按应用逍遥向导然后和逍遥市场应用换位置
x1=driver.find_element_by_xpath("//android.widget.TextView[@text='逍遥向导']")
x2=driver.find_element_by_xpath("//android.widget.TextView[@text='逍遥市场']")
driver.drag_and_drop(x1,x2)
12.手机操作
(1)截图
1)截图保存到指定文件夹
方法:
get_screenshot_as_file('保存的电脑路径\图片名字.格式')
例:
driver.get_screenshot_as_file('d:/test.png')
driver.save_screenshot('test.png')
2)截图保存在脚本所在文件夹
方法:save_screenshot('图片名.格式') 该方法直接保存当前屏幕截图到当前脚本所在文件位置。
driver.save_screenshot('login.png')
(2)发送按键
方法:keyevent(seconds)
发送home键:driver.keyevent(3)
例:打开设置中的蓝牙后返回home键
driver.find_element_by_name('蓝牙').click()
driver.keyevent(2)
(3)操作通知栏
方法:open_notifications
例:
driver.open_notifications()
13.pytest框架
(1)介绍和安装
pytest是一个单元测试框架
(1)框架是什么?能不能不用?框架能够带来什么作用?
框架是已经封装好的一个结构,遵循框架的模式,能够高效解决代码中的问题,减少工作量。
框架必须要解决部分问题:
1.批量执行大量的脚本。
2.收集脚本执行后的结果。
3.将结果写入测试报告中。
4.能够接收和处理用例的一些异常操作
(2)什么是单元测试框架?
单元测试是指在软件开发当中,针对软件的最小单位(函数、方法)进行正确性的检查测试
(3)单元测试框架的分类
java:Junit和testng
python:unittest和pytest
(4)单元测试框架主要做什么?
1.测试发现:从多个文件里面去找到我们测试用例
2.测试执行:按照一定的顺序和规则去执行,并生成结果
3.测试判断:通过断言判断预期结果和实际结果的差异
4.测试报告:统计测试进度,耗时,通过率,生成测试报告
(5)单元测试框架和自动化测试框架有什么关系?
单元测试框架只是自动化测试框架中的组成部分之一。
自动化测试框架的组成部分还有:
pom设计模式
数据驱动
关键字驱动
全局配置文件的封装
日志监控
selenium(UI)和request(接口)二次封装
断言
报告邮件
······
pytest简介
1.pytest是一个非常成熟的python的单元框架,比unittest更灵活,容易上手
2.pytest可以和selenium,requests,Appium结合实现web自动化,接口自动化,APP自动化
3.pytest可以实现测试用例的跳过以及reruns失败用例重试
4.pytest可以和allure生成非常美观的测试报告
5.pytest可以和Jenkins持续集成
6.pytest有很多非常强大的插件,并且这些插件能够实现很多实用的操作
pytest的插件:
pytest
pytest-html(生成html格式的自动化测试报告)
pytest-xdist(测试用例分布式执行,多CPU分发)
比如有一万条自动用例,每条用例需要1秒钟执行,那就要一万秒,时间就比较长,如果用分布式执行,同时用多个进程来跑一万个用例,分布5个进程,那就每个进程跑2千个用例,时间就会快了5倍,所以这个插件是非常有意义的
pytest-ordering 用于改变测试用例的执行顺序
pytest-rerunsfailures 用于用例失败后重跑
allure-pytest 用于生成美观的测试报告
安装:
pip install pytest
pip install -u pytest 都可;
如果多个插件一起安装,可以先创建一个.txt格式的文件,通过pip install -r 文件名.txt来安装
安装校验:两种方式
pip list
(2)用例规则
测试文件以test_开头(以_test结尾也可以)
测试类以Test开头,并且不能带有 __init__ 方法
测试函数以test_开头
断言使用assert
(3)运行模式
1)主函数模式:
(1)运行所有:pytest.main()
(2)运行指定模块:pytest.main(['-vs','test_login.py'])
(3)运行指定目录:pytest.main(['-vs','目录路径/目录名'])
(4)通过nodeid指定用例运行:nodeid由目录路径/目录名,模块名,分隔符,类名,方法名,函数名组成
pytest.main(['-vs','./myappium_day2/test_setting.py::Test_01_test001'])
2)命令行模式
(1)运行所有:pytest
(2)运行指定模块:pytest -vs test_login.py
(3)运行指定目录:pytest -vs ./myappium_po
参数详解: -s:表示输出调试信息,包括print打印的信息 -v:显示更详细的的信息(包括类名、函数名) -vs:两个参数一起用 -n:支持多线程或者分布式运行测试用例 如:pytest-vs ./testcase/test_login.py -n 2
-x:表示只要有一个用例报错,那么测试停止
--maxfail=2 出现两个用例失败就停止
-k:根据测试用例的部分字符串指定测试用例
如:pytest-vs ./testcase -k "ao"
3)通过读取pytest.ini配置文件运行
pytest.ini这个文件是pytest单元测试框架的核心配置文件
1.位置:一般放在项目的根目录
2.编码:必须是ANSI,可以使用notepad++修改编码格式
3.作用:可以改变pytest的默认行为
4.运行规则:不管是主函数的模式运行,命令行模式运行,都会去读取这个配置文件