• 白盒测试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)

    生成报告示例图


  • 相关阅读:
    设计模式(6)--Adapter(适配器模式)--结构型
    设计模式原则(1)--Single Responsibility Principle(SRP)--单一职责原则
    设计模式(5)--Builder(建造模式)--创建型
    设计模式(4)--AbstractFactory(抽象工厂模式)--创建型
    设计模式(3)--SimpleFactory( [1] 简单工厂模式)--创建型
    JS 的map和array集合组合返回JSON字符串
    HTML中直接写js 函数
    设计模式(3)--FactoryMethod( [2] 工厂方法模式)--创建型
    图片剪贴工具类
    远程Get,Post请求工具类
  • 原文地址:https://www.cnblogs.com/st998/p/13831807.html
Copyright © 2020-2023  润新知