json
json文件本质也是文本文件 可以直接使用read和write操作
比较特殊,比较像Python的字典和列表
使用 read 和write的操作比较麻烦,专门的方法来操作json文件,可以直接得到python中的列表和数据
基于文本,独立于语言的轻量级数据交换格式
基于文本:文本文件,不包含图片,视频
独立于语言:不是某种语言特有的
轻量级:相同的数据量,json文件占用的文件大小相对较小
数据交换格式:后端服务器和前端页面交换数据使用的格式
在自动化测试中常用来存放测试数据,文件后缀名为.json
json的语法
数据类型:
对象{}
数组【】
字符串 必须使用“”
数字类型 int float bool(true false)
空值:null
json文件是一个对象或者是数组,对象和数组可以相互嵌套
json中的对象是由键值对组成的,键必须是字符串类型
json的数据之间使用,隔开
json文件的读取
1.read 但是读取数据麻烦
2专门的方法
2.1导包 import json
2.2 json.load(文件对象)—》得到的列表或者字典
# with open('demo.json','r',encoding='utf-8') as f:
# buf=f.read()
import json
with open('demo.json','r',encoding='utf-8') as f:
buf=json.load(f)
print(buf)
print(buf.get('name'))
#取出城市
print(buf.get('address').get('city'))
json的写入
将python的列表或者字典转换为json
导包,使用json.dump(python中的数据类型,文件对象)
import json
info={'name':'小明','age':18}
with open('info3.json','w',encoding='utf-8') as f:
json.dump(info,f,ensure_ascii=False,indent=4)#直接显示中文
indent=4#缩进
异常
程序在执行时,如果python解释器遇到一个错误,则会停止程序的执行,并且提示一些错误信息
抛出异常:程序停止执行并且提示错误信息这个动作
如:用例执行报错,打印日志信息等操作
FileNotFoundError: [Errno 2] No such file or directory: 'aaa.txt'
#异常类型:错误信息描述
捕获异常:目的:让程序遇到异常之后不执行不会结束,可以继续执行
try:
可能发生异常的代码
except:
出现异常时执行的代码
num1=input("输入数字:")
try:
num1 = int(num1)
print(num1)
except:
print('输入正确的数据')
捕获指定类型的异常
try:
可能发生异常的代码
except 异常类型1:
执行的代码
except 异常类型2:
执行的代码
num=int(input('请输入一个整数:'))
try:
num1=8/num
print(num1)
except ValueError:
print("类型输入错误")
except ZeroDivisionError:
print("输入的数字为0,请重输入")
捕获未知类型的异常(使用最多)
try :
可能发生的异常
except Exception as 变量:常见异常类的父类Exception 变量 ,异常对象,print()可以打印异常信息
发生异常时执行的代码
try:
num = int(input('请输入一个整数:'))
num1=8/num
print(num1)
except Exception as e:
print(f'发生了异常,{e}')
异常捕获的完整结构
try:
可能发生异常的代码
except 异常类型:
发生了指定类型的异常执行的代码
except Exception as e:
发生了其他类型的异常执行的代码
else:
没有发生异常执行的代码
finally :
不管有没有发生异常,都会执行的代码
if判断 字符串.isdight()判断是否是纯数字
#
# try:
# num = int(input('请输入数字:'))
# except Exception as e:
# print(f'输入异常,{e}')
# else:
# if(num%2==0):
# print(f'{num}是偶数')
# else:
# print(f'{num}是奇数')
# finally:
# print('程序运行结束')
num=input('请输入数字:')
if num.isdigit():
if int(num)%2==0:
print(f"{num}是偶数")
else:
print(f'{num}是奇数')
else:
print("输入的数据错误")
print('程序运行结束')
异常的传递
当函数/方法执行出现异常,会将异常传递给函数/方法的调用一方
如果传到主程序,仍然没有处理异常,程序才会被终止
在函数的嵌套调用过程中,如果发生了异常没有进行捕获,会将这个异常传递到函数调用的地方,直到被捕获为止,才会报错然后终止执行
只需要在最外层捕获
def demo1():
num=int(input('请输入一个整数:'))
return num
def demo2():
demo1()
if __name__ == '__main__':
try:
demo2()
except Exception as e:
print(e)
抛出异常:在代码执行中,之所以会发生异常,终止代码执行,是因为代码执行遇到了raise关键字
raise关键字的作用,就是来抛出异常,让代码终止执行
应用场景:自己书写代码模块,让别人使用,为了让别人按照你的规定使用你的代码,你就可以在她不满足条件的情况下,使用raise抛出异常
unittest框架使用
自动化测试中使用,管理执行测试用例的
框架(framework):为了解决一类事物的功能集合
unitest框架:python自带的一个单元测试框架
测试人员用来做自动化测试,作为自动化脚本的执行框架,管理和执行自动化的
为什么使用:能组织多个用例去执行,提供丰富的断言方法,能够生成测试报告
unitest框架的基本使用
核心要素 组成部分:
TestCase:测试用例,用来书写真正的用例代码(脚本)
步骤:1导包 unitest
2.定义测试类
3.书写测试方法
4.执行(单个测试用例也可以执行)
"""
学习unittest测试用例的使用
"""
#1.导包
import unittest
#2.定义测试类:只需要让类继承unittest.TestCase类即可
class TestDemo(unittest.TestCase):
#3.书写测试方法,方法中的代码就是真正的用例代码,**方法名必须以test开头**
def test_method1(self):
print('测试方法一')
def test_method2(self):
print('测试方法二')
#4.代码执行
#4.1在类名或者方法名后面右键运行
#类名 执行类所有的测试方法
#方法名后边只执行当前的测试方法
# 使用unittest.main()来执行,在主程序中使用
if __name__ == '__main__':
unittest.main()
注意事项
1.命名规范!
2.右键运行没有unitest for
解决方法:1.复制代码新建一个.py
2.使用unittest.main()来执行,在主程序中使用
if name == ‘main’:
unittest.main()
3.
TestSuite:测试套件,作用是用来组装(打包) TestCase的,可以将多个用例脚本组装到一起
步骤1:导包 import unnitest
2.实例化套件对象suite= unittest.TestSuite()
3.添加用例方法suite.addTest(ClassName(“MethodName”)
扩展:suite.addTest(unitest.defaultTestLoader.loadTestsFromTestCase(ClassName))
#套件对象.addTest(unittest.makeSuite(测试类名)
suite.addTest(unittest.makeSuite(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
TestRunner:测试执行,用来执行TestSuite的
步骤:
1.导包:import unnitest
2.实例化执行对象:unittest.TextTestRunner()
3.执行对象执行套件方法 套件对象.执行对象.run(套件对象)
整体步骤:
导包 import unnitest
2.实例化套件对象suite= unittest.TestSuite()
3.添加用例方法suite.addTest(ClassName("MethodName")
4.实例化执行对象:unittest.TextTestRunner()
5.执行对象执行套件方法 套件对象.执行对象.run(套件对象)
# 1.导包import unnitest
import unittest
from demo01 import TestDemo1
from demo02 import TestDemo2
# 2.实例化套件对象suite = unittest.TestSuite()
suite=unittest.TestSuite()
# 3.添加用例方法suite.addTest(ClassName("MethodName")
suite.addTest(TestDemo1('test_method1'))
suite.addTest(TestDemo1('test_method2'))
suite.addTest(TestDemo2('test_method1'))
suite.addTest(TestDemo2('test_method2'))
# 4.实例化执行对象:unittest.TextTestRunner()
runner=unittest.TextTestRunner()
# 5.执行对象执行套件方法 套件对象.执行对象.run(套件对象)
runner.run(suite)
TestLoader:测试套件,是对 TestSuite(测试套件)功能的补充,组装(打包) TestCase的
同样也需要使用TextTestRunner()去执行
10给用例 makeSuite()
用来加载TestCase到TestSuite中
步骤1.导包 unittest
2.实例化加载对象并加载用例----》得到的是套件对象
3.实例化执行对象并执行
import unittest
# .实例化加载对象并加载用例----》得到的是套件对象
# suite=unittest.TestLoader().discover('用例所在的目录','用例代码文件名.py')
suite = unittest.TestLoader().discover('./', 'demo02*.py')
# runner=unittest.TextTestRunner()
# runner.run(suite)
unittest.TextTestRunner().run(suite)
import unittest
# suite = unittest.TestLoader().discover('用例所在的目录', '用例代码文件名.py')
suite=unittest.TestLoader().discover('case','test*.py',)#括号记得写!!!!
unittest.TextTestRunner().run(suite)
Fixture:测试夹具,是一种代码结构,书写 前置方法(执行用例之前的方法)代码和后置方法(执行用例之后的方法)代码,即用例顺序:前置-》》用例-》》》后置
代码结构,会在用例执行前后自动执行的代码结构,
方法级别Fixture:在每个用例执行前后都会调用,方法名固定,
def setUp(self):#前置代码
pass
def tearDown(self):#后置
pass
方法前置 用例 方法后置
类级别Fixture
在类中所有的测试方法执行前后,会自动执行的代码,只执行一次
需要写作类方法
@classmethod
def setUpClass(cls):#类前置
pass
@classmethod
def tearDownClass(cls):#类后置
pass
类前置 方法前置 用例 方法后置 方法前置 用例 方法后置 类后置
tpshop登录
1.打开浏览器(1次)
2.打开网页,点击登录(每次)
3.输入用户名,密码,验证码,点击登录(测试方法)
4.关闭页面(1次)
5.关闭浏览器(1次)
import unittest
# tpshop登录
# 1.打开浏览器(1次)
# 2.打开网页,点击登录(每次)
# 3.输入用户名,密码,验证码,点击登录(测试方法)
# 4.关闭页面(每次)
# 5.关闭浏览器(1次)
class TestLogin(unittest.TestCase):
@classmethod
def setUpClass(cls):
print('1.打开浏览器')
@classmethod
def tearDownClass(cls):
print('5.关闭浏览器')
def tearDown(self):
print('4.关闭页面')
def test_1(self):
print('3.输入用户名,密码,验证码,点击登录')
def test_2(self):
print('3.输入用户名,密码,验证码,点击登录')
def test_3(self):
print('3.输入用户名,密码,验证码,点击登录')
def setUp(self) -> None:
print('2.打开网页,点击登录')
@classmethod
def setpClass(cls):#类前置
pass
@classmethod
def tearDownClass(cls):#类后置
pass
类前置 方法前置 用例 方法后置 方法前置 用例 方法后置 类后置
模块级别Fixture(了解)
在这个代码文件执行一次
#在类外部定义函数
def setupMoudle():
pass
def tearDownMoudle():
pass
用例执行结果
…用例通过
F用例不通过 False
E用例代码错误Error
TestSuite和TestLoader的区别:
TestSuite:灵活,方便控制要执行的测试用例,缺点:需要手动添加测试用例
TestLoader:添加测试用例方便,但是不方便控制要执行的测试用例
用例脚本中写的
断言
使用代码自动判断执行结果是否符合预期结果的过程
为什么使用?提高效率,实现自动化测试
常用的unitTest断言方法
assertTrue(expr,msg=None)#验证expr是true,如果为falese,则fall
assertFalse(expr,msg=None)#验证expr是false,如果为true,则fall
assertEqual(预期结果,实际结果)#验证expected是actual,不等则fail
assertin(预期结果,实际结果)#验证是否预期结果是否包含在实际结果中,如果存在,用例通过,如果不存在,抛出异常,用例不通过
import unittest
class TestAssert(unittest.TestCase):
def test_equal(self):
self.assertEqual(10,10)#用例通过
# def test_asset_2(self):
# self.assertEqual(10,11)#用例不通过
def test_in(self):
self.assertIn('admin','欢迎admin登录')#包含
self.assertIn('admin','欢迎adminnnnn登录')#包含
self.assertIn('admin', '欢迎addddddmin登录') # 不包含
self.assertIn('admin', 'admin') # 包含
import unittest
from demo01 import TestAssert
suite=unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAssert))
runner=unittest.TextTestRunner()
runner.run(suite)
参数化
通过参数化来传递数据,从而实现数据和脚本分离,并且可以实现用例的重复执行(书写用例方法的时候,测试数据使用变量代替,在执行的时候进行数据传递)
unittest测试框架,本身不支持参数化,可以通过unittest扩展插件parameterized来实现
环境准备:因为参数化插件不是unnitest自带的,所以想要使用,需要进行安装Python中包的安装,使用pip pip install parameterized#cmd中
pip install可以查看安装 的插件
pip 安装install +安装包
查看pip show 包名
卸载 pip uninstall 包名
使用导包
修改测试方法,使用变量来表示
组织测试数据,格式【(),(),()】,一个元组就是一组测试数据
参数化,在测试方法中使用装饰器@parameterized.expand(测试数据)
直接运行(TestSuite或者suite运行)
from parameterized import parameterized
import unittest
from tools import add
data=[(1,1,2),(1,2,3),(2,3,5),(4,5,9)]
class Test_add(unittest.TestCase):
@parameterized.expand(data)
def test_add1(self,a,b,expect):
self.assertEqual(expect,add(a,b))#用例通过
print(f'a:{a},b:{b},expect:{expect}')
if __name__ == '__main__':
unittest.main()
round(3.1415,2)#3.14
round(3.1415,3)#3.142
跳过
不想执行,对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行
直接跳过 @unittest.skip(‘代码来完成’)
根据条件判断测试函数是否跳过
@unittest.skipIf(判断条件,reason=‘原因’)
生成测试报告(suite和runner)
为什么生成?本次测试报告结果的体现形态,包含了有关本次测试用例的详情
HTMLTestReport类库
第三方,需要安装,本质是TestRunner
安装,导包unittest ,HTMLTestReport
组装用例(套件,loader)
使用HTMLTestReport中的runner执行套件
import unittest
from htmltestreport import HTMLTestReport
from readdata import Test_add
#套件
suite=unittest.TestSuite()
suite.addTest(unittest.makeSuite(Test_add))
#运行对象
# HTMLTestReport(测试报告的文件路径后缀.html,报告的标题,其他的描述信息)
runner=HTMLTestReport('test_add_report.html','加法用例测试报告','XXX')
runner.run(suite)
路径
获取当前文件的绝对路径
创建一个app.py导包
Base_DIR=‘相同的路径’
自动获取绝对路径
获取项目的绝对路径
import os
os.path.abspath()
步骤:在项目的根目录下创建一个python文件(app.py/config.py)
在这个文件中获取项目的目录,在其他代码中使用路径拼接使用
Base_DIR=os.path.dirname(__file__)
完整的测试报告生成
1.安装HTMLTestReport
2.导包unittest
3.写测试用例,断言,参数化在里面写
断言(self.assertEqual/self.assertIn)
self.assertEqual(expect,add(a,b))#用例通过
参数化需要导包parameterized,装饰器@parameterized.expand(数据)
测试报告需要组装
suite=unittest.TestSuite()
suite.addTest(unittest.makeSuite(Test_login))
runner=HTMLTestReport('login.html','login测试用例','XXX')
runner.run(suite)