白盒测试day03

单元测试-执行

目标
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)

生成报告示例图


原文地址:https://www.cnblogs.com/st998/p/13831807.html