Unittest框架使用教程

Unittest框架使用教程

    • UnitTest框架介绍
    • [1. UnitTest框架的组件](#1. UnitTest框架的组件)
      • [TestCase 测试用例](#TestCase 测试用例)
      • [TestSuite 测试套件](#TestSuite 测试套件)
      • [TestLoader 测试加载](#TestLoader 测试加载)
      • [TestRunner 测试执行](#TestRunner 测试执行)
      • [Fixture 测试夹具](#Fixture 测试夹具)
    • [2. TestLoader与TestSuite区别](#2. TestLoader与TestSuite区别)
    • [3. 断言与参数化](#3. 断言与参数化)
    • [4. 测试报告和跳过](#4. 测试报告和跳过)

UnitTest框架介绍

框架(framework):

为解决一类事情的功能集合

UnitTest框架:

1.定义 : 是Python自带的一个单元测试框架,可以直接使用,不需要单外安装。

不仅仅可以用来做单元测试,测试人员也经常用来做自动化测试。

  1. 用途: 能够组织多个用例去执行,提供丰富的断言方法,最终生成测试报告

1. UnitTest框架的组件

TestCase 测试用例

用来书写真正的用例代码(脚本)

步骤:

  • 导包 unittest
  • 定义测试类,只要集成unittest.TestCase类,就是测试类
  • 书写测试方法,方法中的代码就是用例代码,方法名必须以test开头
  • 运行:在类名或者方法名后边右键运行; 调用unittest.main()来运行

代码如下:

python 复制代码
# 导包 unittest
import unittest


#定义测试类,只要集成unittest.TestCase类,就是测试类
class TestDemo(unittest.TestCase):

#书写测试方法,方法中的代码就是用例代码,方法名必须以test开头
    def test_01(self):
        print("测试方法1")

    def test_02(self):
        print("测试方法2")

 #运行:在类名或者方法名后边右键运行; 调用unittest.main()来运行
if __name__ == "__main__":
    unittest.main()

注意事项 :

  • 代码文件名,要满足标识符的规则,不要使用中文

运行结果:

TestSuite 测试套件

用来组装(打包)TestCase(测试用例)的,即多条测试用例集合在一起就是一个测试套件

使用步骤:

  • 实例化测试套件: unittest.TestSuite()
  • 添加用例方法
  • 实例化 执行对象: unittest.TextTestRunner()
  • 执行对象执行: run()

先将TestCase.py文件复制一份,粘贴后修改文件名为TestCase_02.py

修改的内容如下,为了区分第一个用例:

新建测试套件类并运行:

代码如下:

python 复制代码
import unittest
from  TestCase import  TestDemo
from TestCase_02 import TestDemo02

#实例化测试套件: unittest.TestSuite()
suite = unittest.TestSuite()

#添加用例方法
suite.addTest(TestDemo('test_01'))
suite.addTest(TestDemo('test_02'))
suite.addTest(TestDemo02('test_01'))
suite.addTest(TestDemo02('test_02'))

#实例化 执行对象并执行: unittest.TextTestRunner().run()
unittest.TextTestRunner().run(suite)

运行结果:

添加扩展:把指定ClassName类中的测试用例全部添加到测试套件中

复制TestSuite_TestRunner.py文件,命名为TestSuite_TestRunner_02.py

代码修改:

python 复制代码
#把指定ClassName类中的测试用例全部添加到测试套件中
suite.addTest(unittest.makeSuite(TestDemo))
suite.addTest(unittest.makeSuite(TestDemo02))

运行结果和挨个添加测试用例方法一样的:

TestLoader 测试加载

用来加载TestCase到TestSuite中,即夹杂满足条件的测试用例,并把测试用例封装成测试套件

使用unittest.TestLoader,通过该类下面的discover()方法自动搜索执行目录下指定开头的.py文件,并将查找到的测试用例组装到测试套件中

用法 :

suite = inittest.TestLoader().discover(test_dir,pattern = 'test*.py')

最终返回的还是测试套件对象,运行测试套件还需要使用TestRunner

使用步骤:

  • 实例化加载对象并加载用例 ,返回的是套件对象
  • 实例化执行对象并执行

新建文件TestLoader_TestRunner.py文件

代码如下:

python 复制代码
import unittest

#实例化加载对象并加载用例  ,返回的是套件对象
#unittest.TestLoader().discover('用例所在的目录','用例代码文件名*.py')
# .:代表当前目录下
suite = unittest.TestLoader().discover('.','TestCase*.py')
# 实例化执行对象并执行
unittest.TextTestRunner().run(suite)

TestRunner 测试执行

用来执行用例和测试套件

使用步骤:

  • 导包
  • 实例化: unittest.TextTestRunner
  • 执行

Fixture 测试夹具

是一种代码结构,书写 前置方法(执行用例之前的方法)和 后置方法(执行用例之后的方法)代码,即用例执行顺序 前置 → 用例 → 后置

分类:

  • 方法级别 Fixture :在每个用例执行前后都会自动调用
python 复制代码
def setUp(self):  #方法前置
	pass

def tearDown(self): #方法后置
	pass
	
  • 类级别 Fixture : 在类中所有的测试方法前后 会自动执行的代码,只执行一次
python 复制代码
@classmethod
def setUpClass(cls):  #类前置
	pass

def tearDownClass(cls): #类后置
	pass
	
  • 模块级别 Fixture
    模块就是代码文件,在这个代码文件执行前后执行一次(在类外部定义函数)
python 复制代码
@classmethod
def setUpModule():  #模块前置
	pass

@classmethod
def tearDownModule(): #模块后置
	pass
	

2. TestLoader与TestSuite区别

TestSuite (测试套件) :

灵活,方便控制要执行的测试用例,需要手动挑选、组装用例,可以自由控制执行顺序。
estLoader(测试加载器):自动去找、读取、加载用例,生成 Suite,自动发现用例,不用手动一个个 add。

3. 断言与参数化

断言:

让程序代替人为判断测试程序执行结果是否符合预期结果的过程

常用的UnitTest断言方法 :


参数化 :

通过参数的方式来传递数据,从而实现数据和脚本分离。并且可以实现用例的重复执行。

unittest测试框架,本身不支持参数化,但是可以通过安装unittest扩展插件parameterized来实现.

安装parameterized: pip install parameterized

查看已安装插件列表:pip list

使用:

  1. 导包 from parameterized import parameterized
  2. 修改测试方法,将测试方法张的测试数据使用变量表示
  3. 组织测试数据,格式: () , () , () , ...,一个元组就是一组数据。
  4. 参数化:在测试方法上方是哟个装饰器@parameterized.expand(测试数据)
  5. 运行

元组参数化:

新建参数化添加功能文件,代码如下:

python 复制代码
import unittest
from parameterized import parameterized

data = [(1,1,2),(1,2,3),(2,3,5),(4,5,9)]

class tools_add (unittest.TestCase):
  @parameterized.expand(data)
  def test_add(self,a,b,expect):
      print(f'a:{a},b:{b},expect:{expect}')
      self.assertEqual(expect, a+b)

if __name__ == '__main__':
    unittest.main()

运行结果:

json参数化

  1. json数组参数化:
    创建一个json数组格式的数据文件:add_data.json
python 复制代码
[
   [1,1,2],
   [1,2,3],
   [2,3,5],
   [4,5,9],
   [10,10,20]
]

将json文件中的数组格式转换为unittest参数化元组格式:

新建read_data.py文件:

代码如下:

python 复制代码
import json

def build_add_data():
    with open('add_data.json') as f:
        data = json.load(f)
    return data

调整之前的测试参数化添加功能文件,代码如下:

python 复制代码
import unittest
from parameterized import parameterized
from read_data import build_add_data

class tools_add (unittest.TestCase):
  @parameterized.expand(build_add_data())
  def test_add(self,a,b,expect):
      print(f'a:{a},b:{b},expect:{expect}')
      self.assertEqual(expect, a+b)

if __name__ == '__main__':
    unittest.main()

运行输出结果:

  1. json字典参数化

创建一个json数组格式的数据文件:add_data_02.json

python 复制代码
[
  {
    "a": 1,
    "b": 2,
    "expect": 3
  },
  {
     "a": 10,
     "b": 20,
     "expect": 30
  },
  {
     "a": 2,
     "b": 3,
     "expect": 5
  },
  {
     "a": 20,
     "b": 30,
     "expect": 50
  }
]

在read_data.py文件中新增方法build_add_data_02(),代码如下:

python 复制代码
def build_add_data_02():
    base_path = os.path.dirname(__file__)
    json_full_path = os.path.join(base_path, "add_data_02.json")
    with open(json_full_path, "r", encoding="utf-8") as f:
        data_list = json.load(f)
        new_list = []
        for data in data_list:
            new_list.append(tuple(data.values()))
    return new_list

将test_tools_add_parameterized.py文件中的test_add()参数化方法调整一下,

运行后的结果如下:

4. 测试报告和跳过

HTML测试报告:就是执行完测试用例后,使用第三方的报告模板(HTMLTestReport),以HTML(网页)方式将执行结果生成报告。本质是TestRunner

安装:pip install HTMLTestReport

使用:

  • 导包 unittest,HTMLTestReport
  • 组装用例(套件,loader)
  • 使用HTMLTestReport 中的runner执行套件
  • 查看报告

新建文件 TestReporter.py,执行参数化tools_add接口,生成测试报告

内容如下:

python 复制代码
import unittest
from htmltestreport import HTMLTestReport
# 这里注意一下:我的用例是写在case文件夹下的,所以加载的路径是:`../case`
suite = unittest.TestLoader().discover('../case', 'test_tools_add_paramete*.py')
runner = HTMLTestReport('test_add_report.html','参数化tools_add接口测试报告','json参数化+parameterized测试')
runner.run(suite)

执行结果:

报告文件及查看:

跳过:对于一些未完成的或者不满足测试条件的测试函数和测试类,可以跳过执行。

使用方式:

  • 直接将测试函数标记跳过:@unittest.skip('代码未完成')
  • 根据条件判断测试函数是否跳过:@unittest.skipif(condition,reason)

创建跳过用例文件:test_skip.py

python 复制代码
import unittest

a = 11

class TestSkip(unittest.TestCase):
    @unittest.skip('跳过,代码未完成')
    def test_skip_01(self):
        print(f'测试跳过01')
    @unittest.skipIf('a >=10 ','a大于10,跳过不执行')
    def test_skip_02(self):
        print(f'测试跳过02')

    def test_skip_03(self):
        print(f'测试跳过03')

if __name__ == '__main__':
    unittest.main()

执行结果:

组装到suite里执行:

代码如下:

python 复制代码
import unittest

from case.test_skip import TestSkip

suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestSkip) )

unittest.TextTestRunner().run(suite)

执行结果:

相关推荐
一个简单的TTS开发者2 小时前
中文TTS工具有哪些-8款主流方案横向对比
人工智能·后端·python·indextts
yunfanleo2 小时前
temperature 详解:大模型采样参数原理、三种用法与工程实践
人工智能·python·rpa
CarIise2 小时前
Maven依赖传递与聚合工程
python·r语言·django
VidDown10 小时前
24fps 转 25fps 不只是改个数字:帧率转换、PAL/NTSC 与音频补偿
python·网络协议·音视频·视频编解码·视频
死磕音视频12 小时前
让小模型做选择题:限定候选项并读取 logits 概率的入门实践(附 Python 代码)
开发语言·python·大模型·文本分类·transformers
凤山老林13 小时前
Spring Boot 接入国密 SM2/SM3/SM4 的一些实践记录
spring boot·后端·python
pride.li14 小时前
第03章 Python 教程-基础语法:注释与变量
服务器·前端·后端·python·算法·计算机视觉
databook14 小时前
用 Pydantic AI 从零搭建一个能干活的 AI Agent
人工智能·python
康小旺15 小时前
把 markitdown 做成 Windows 桌面版:拖进文档就出 Markdown,附 233MB→64MB 打包裁剪全过程
python