单元测试-执行
目标
1. 回顾UnitTest框架使用
2. 基于UnitTest测试三角形案例
3. 在UnitTest框架中使用数据分离
什么是单元测试执行
概念:通过单元测试框架对要进行测试代码的实践过程
练习
1. 通过Python语言编写一个运算的类(Calc),类中包含两个函数:
1) add(self,a,b) 返回a+b之和
2) sub(self,a,c) 返回a-c之差
提示:通过练习1,我们先简单复习下UnitTest框架的使用
步骤分析
1. 新建Calc类
2. 在Calc类中新建add函数
3. 在Calc类中新建sub函数
4. 调用对象中方法
# 新建Calc类
class Calc():
# 新建add 返回a+b
def add(self,a,b):
return a+b
# 新建sub 返回a-b
def sub(self,a,b):
return a-b
if __name__ == '__main__':
print(Calc().add(10,10))
print(Calc().sub(10,10))
单元测试
1. 导包 UnitTest 、Calc类
2. 新建单元测试类 Test01(继承 unitTest.TestCase)
3. 新建testAdd()函数
1). 导入Calc类中的add函数
2). 添加断言
4. 新建testSub()函数
1). 导入Calc类中的sub函数
2). 添加断言
5. 执行测试
1). unittest.main()
import unittest
from code.test01_lx01 import Calc
class Test_Calc(unittest.TestCase):
def setUp(self):
print('setUp被执行')
def tearDown(self):
print('tearDown被执行')
def test_add(self):
result = Calc().add(10,10)
print('test_add方法被执行')
self.assertEqual(result,20)
def test_sub(self):
result = Calc().sub(10,10)
print('test_sub方法被执行')
self.assertEqual(result,0)
if __name__ == '__main__':
# main方法运行当前类中所有test开头的方法
unittest.main()
问题
1. 练习1我们数据直接写入代码中,如果数量庞大,我们需要频繁改动数据或复制冗余代码进行实现数据测试目的。
2. 做不到数据分离(代码和数据分开),不便维护
参数化
概念:根据需求动态获取数据并进行赋值的过程
参数化方式XML
1. XML格式(1) # 不推荐使用,太繁琐了
3. CSV格式(2)
2. JSON串 (3)
4. TXT文本(4)
提示:括号内为推荐使用优先级,从小到大;1-2为扩展了解,3-4建议重点了解
xml
概念:XML是一种标记语句,很类似HTML标记语言;后缀 .xml
xml与html区别
XML是传输和存储数据,焦点在数据;HTML是显示数据,焦点在外观;
xml格式
<?xml version="1.0" encoding="UTF-8"?>
<book category="面授">
<title>单元测试</title>
<author>XST</author>
<year>2008</year>
<price>39.95</price>
</book>
1. 必须有XML声明语句:<?xml version="1.0" encoding="UTF-8"?>
2. 必须要有一个根元素,如:<book>
3. 标签大小写敏感
4. 属性值用双引号
5. 标签成对
6. 元素正确嵌套
7. 标签名可随意命名,但有以下限制
1) 不能以数字或者标点符号开始
2)不能以字符 “xml”(或者 XML、Xml)开始
3) 名称不能包含空格
需求
对三角形案例单元测试使用XML格式进行参数化
操作步骤
1. 编写XML数据文件
2. 编写读取XML模块函数
3. 单元测试模块中引用XML读取函数
4. 执行
xml数据文件
<?xml version="1.0" encoding="utf-8" ?>
<SJX>
<bian>
<b1>2</b1>
<b2>3</b2>
<b3>4</b3>
<expect>普通三角形</expect>
</bian>
<bian>
<b1>2</b1>
<b2>2</b2>
<b3>2</b3>
<expect>等边三角形</expect>
</bian>
<bian>
<b1>2</b1>
<b2>3</b2>
<b3>3</b3>
<expect>等腰三角形</expect>
</bian>
<bian>
<b1>3</b1>
<b2>2</b2>
<b3>3</b3>
<expect>等腰三角形</expect>
</bian>
<bian>
<b1>3</b1>
<b2>2</b2>
<b3>2</b3>
<expect>等腰三角形</expect>
</bian>
<bian>
<b1>1</b1>
<b2>2</b2>
<b3>3</b3>
<expect>不是三角形</expect>
</bian>
<bian>
<b1>3</b1>
<b2>2</b2>
<b3>1</b3>
<expect>不是三角形</expect>
</bian>
<bian>
<b1>2</b1>
<b2>3</b2>
<b3>1</b3>
<expect>不是三角形</expect>
</bian>
</SJX>
读取xml数据
# 导包 minidom
from xml.dom import minidom
class Read_Xml():
def readXml(self,node,num,nodeChild):
# 解析xml文档
dom = minidom.parse('../DataPool/sjx.xml')
# 获取文档对象
root = dom.documentElement
#print(root.getElementsByTagName(node))
# 获取边元素
element = root.getElementsByTagName(node)[int(num)]
# 获取指定边元素 如b1
return element.getElementsByTagName(nodeChild)[0].firstChild.data
def get_len(self,node):
# 解析xml文档
dom = minidom.parse('../DataPool/sjx.xml')
# 获取文档对象
root = dom.documentElement
return len(root.getElementsByTagName(node))
if __name__ == '__main__':
print(Read_Xml().get_len('bian'))
动态化参数执行测试
# 导包unittest 、三角形函数、读取xml数据类
import unittest
from code.sjx import Sjx
from ReadData.read_xml import Read_Xml
sjxClass = Sjx() # 实例化三角形类
readClass = Read_Xml() # 实例化读取数据
class Test_Xml(unittest.TestCase):
def test001(self):
for i in range(readClass.get_len('bian')):
# 目的 测试三角形程序
result = sjxClass.sjx(
int(readClass.readXml('bian',i,'b1')),
int(readClass.readXml('bian',i,'b2')),
int(readClass.readXml('bian',i,'b3')),)
# 添加断言,判断预期结果
self.assertEqual(result,readClass.readXml('bian',i,'expect'))
print(readClass.readXml('bian',i,'b1'),
readClass.readXml('bian',i,'b2'),
readClass.readXml('bian',i,'b3'),
readClass.readXml('bian',i,'expect'),
"--->预期通过"
)
重点分析
1. 导入XML包 from xml.dom import minidom
2. 加载解析 dom=minidom.parse(filename)
3. 获取对象 root=dom.documentElement
4. 获取子元素 aas=root.getElementsByTagName(one)[0]
5. 获取子元素值 aas.getElementsByTagName(two)[0].firstChild.data
XML-总结
1. 读取方式
2. 什么是XML
3. XML与HTML区别
4. XML编写格式
5. 缺点:不适合大量参数化数据时使用,每次都写标签太繁琐了,不够简洁
参数化方式CSV
csv格式
概念:CSV是一种以逗号做分割的表格格式; 后缀 .csv
使用csv实现三角形案例参数化
1. 创建CSV文件
2. 编写CSV读取模块函数
3. 单元测试-引用CSV读取函数
4. 执行
CSV文件
2,2,2,等边三角形
2,2,3,等腰三角形
2,3,2,等腰三角形
3,2,2,等腰三角形
1,2,3,不是三角形
2,3,1,不是三角形
3,2,1,不是三角形
2,3,4,普通三角形
2,2,2,等边三角形
2,2,3,等腰三角形
2,3,2,等腰三角形
3,2,2,等腰三角形
1,2,3,不是三角形
2,3,1,不是三角形
3,2,1,不是三角形
2,3,4,普通三角形
CSV读取模块函数
# 导包
import csv
class Read_Csv(object):
def read_csv(self):
# 打开csv
with open('../DataPool/sjx.csv','r',encoding='utf-8') as f:
datas = csv.reader(f)
# 新建空列表,把单行返回的列表添加成整体的列表
lines=[]
for data in datas:
# print(data)
# 添加数组
lines.append(data)
return lines
if __name__ == '__main__':
print(Read_Csv().read_csv())
# 导包
import csv
class Read_Csv(object):
def read_csv(self):
# 打开csv
with open('../DataPool/sjx.csv','r',encoding='utf-8') as f:
datas = csv.reader(f)
# 新建空列表,把单行返回的列表添加成整体的列表
lines=[]
for data in datas:
# print(data)
# 添加数组
lines.append(data)
return lines
if __name__ == '__main__':
print(Read_Csv().read_csv())
单元测试-引用CSV读取函数
# 导包unittest 、三角形函数、读取csv数据类
import unittest
from code.sjx import Sjx
from ReadData.read_csv import Read_Csv
# 实例化三角形类
sjxClass=Sjx()
# 实例化读取csv类
readCsvClass = Read_Csv()
class Test_Csv(unittest.TestCase):
def test001(self):
for i in range(len(readCsvClass.read_csv())):
result=sjxClass.sjx(
int(readCsvClass.read_csv()[i][0]),
int(readCsvClass.read_csv()[i][1]),
int(readCsvClass.read_csv()[i][2]),
)
self.assertEqual(result,readCsvClass.read_csv()[i][3])
print(readCsvClass.read_csv()[i][0],readCsvClass.read_csv()[i][1],
readCsvClass.read_csv()[i][2],readCsvClass.read_csv()[i][3],'--->验证通过')
if __name__ == '__main__':
unittest.main()
'''
2 2 2 等边三角形 --->验证通过
2 2 3 等腰三角形 --->验证通过
2 3 2 等腰三角形 --->验证通过
3 2 2 等腰三角形 --->验证通过
1 2 3 不是三角形 --->验证通过
2 3 1 不是三角形 --->验证通过
3 2 1 不是三角形 --->验证通过
2 3 4 普通三角形 --->验证通过
'''
CSV总结
1. 读取方式
2. 生成CSV文件方式
3. 编码
参数化方式JSON
什么是JSON
概念:一种轻量级数据交换格式;后缀名 .json
提示:
接口测试一般使用JSON为接口传递数据规范格式,所以我们有必要对如何获取JSON数据做个了解;
JSON格式
格式:{"name":"张三","age":28}
提示:由键值对组成,健名和值之间使用分号(:)分割,多个键值对之间使用逗号(,)分割
使用JSON实现三角形案例参数化
1. 编写JSON文件
2. 编写JSON读取模块函数
3. 单元测试-引用JSON读取函数
4. 执行
JSON文件
{"data":
[ {"b1": 2,"b2": 2,"b3": 2,"expect": "等边三角形"},
{"b1":2,"b2":2,"b3":3,"expect":"等腰三角形"},
{"b1":2,"b2":3,"b3":2,"expect":"等腰三角形"}
]
}
JSON读取模块函数
# 导包json
import json
# 打开文件流
class Read_Json(object):
def readJson(self):
with open('../DataPool/sjx.json','r',encoding='utf-8') as f:
# 调用load
datas = json.load(f)
# 返回字典data键名对应的值
return datas["data"]
if __name__ == '__main__':
print(Read_Json().readJson())
单元测试---引用JSON读取函数
# 导包unittest 、三角形函数、读取json数据类
import unittest
from code.sjx import Sjx
from ReadData.read_json import Read_Json
# 实例化对象
sjxClass = Sjx()
readClass = Read_Json()
class test_Json(unittest.TestCase):
def test001(self):
for i in range(len(readClass.readJson())):
result = sjxClass.sjx(
readClass.readJson()[i]['b1'],
readClass.readJson()[i]['b2'],
readClass.readJson()[i]['b3'],
)
self.assertEqual(result,readClass.readJson()[i]['expect'])
print(
readClass.readJson()[i]['b1'],
readClass.readJson()[i]['b2'],
readClass.readJson()[i]['b3'],
readClass.readJson()[i]['expect'],
'--->验证通过'
)
if __name__ == '__main__':
unittest.main()
'''
2 2 2 等边三角形 --->验证通过
2 2 3 等腰三角形 --->验证通过
2 3 2 等腰三角形 --->验证通过
'''
JSON总结
1. JSON概念
2. JSON格式
3. 如何导入JSON包
4. 如何加载JSON
参数化方式--TXT文本
TXT文本优点
1. 编写测试数据方便
2. 使用模块函数读取时便捷
使用TXT文本实现三角形案例参数化
1. 创建txt文本并写入测试数据
2. 编写读取txt模块函数
3. 单元测试-引用JSON读取函数
4. 执行
txt数据
第一条边,第二条边,第三条边,预期结果
2,2,2,等边三角形
2,2,3,等腰三角形
2,3,2,等腰三角形
3,2,2,等腰三角形
1,2,3,不是三角形
2,3,1,不是三角形
3,2,1,不是三角形
2,3,4,普通三角形
读取txt函数模块
class Read_Txt():
def readTxt(self):
# 打开txt文件流
with open('../DataPool/sjx.txt','r',encoding='utf-8') as f:
# 通过文件流调用读取的方式读取数据----》所有行
datas = f.readlines()
#print(datas)
# 新建列表-->添加分割后的单行数据
lines=[]
# 遍历
for data in datas:
'''
strip():去除字符串前后回车
split():使用指定符号进行分割字符串并以列表格式返回分割后的数据
'''
# 把分割后的单行列表数据添加到整体列中,并返回
lines.append(data.strip().split(','))
#返回数据
return lines[1:]
if __name__ == '__main__':
print(Read_Txt().readTxt())
'''
f.read() #读取所有数据
f.readline() # 读取单行
f.readlines() # 读取所有行
'''
单元测试---引用txt读取函数
# 导包unittest 、三角形函数、读取txt数据类
import unittest
from code.sjx import Sjx
from ReadData.read_txt import Read_Txt
# 实例化对象
sjxClass = Sjx()
readClass = Read_Txt()
class Test_Txt(unittest.TestCase):
def test001(self):
for i in range(len(readClass.readTxt())):
# 调用三角形方法
result = sjxClass.sjx(
int(readClass.readTxt()[i][0]),
int(readClass.readTxt()[i][1]),
int(readClass.readTxt()[i][2]),
)
self.assertEqual(result,readClass.readTxt()[i][3])
print(
readClass.readTxt()[i][0],
readClass.readTxt()[i][1],
readClass.readTxt()[i][2],
readClass.readTxt()[i][3],
'----->验证通过'
)
if __name__ == '__main__':
unittest.main()
生成HTML单元测试报告
目标
对单元测试生成HTML报告进行简单回顾
导入HTML报告模板
HTMLTestRunner.py
编写生成HTML模板
# 导入unittest包
import unittest
# 导入 HTMLTestRunner模板包
from UnitTest.Day02.ReadData.HTMLTestRunner import HTMLTestRunner
#导入时间包
import time
# 定义测试模块路径
disconver=unittest.defaultTestLoader.discover('.',pattern='test*.py')
if __name__=='__main__':
#存放报告的文件夹
report_dir='../TestReport'
#报告名称含时间,时间格式
now=time.strftime("%Y-%m-%d %H_%M_%S")
#报告完整路径+名称
report_name=report_dir+'/'+now+'result.html'
#打开报告写入结果
with open(report_name,'wb')as f:
runner=HTMLTestRunner(stream=f,title="UnitTest Report-SJX",description='Test Case Report')
runner.run(disconver)