python-UnitTest框架笔记

UnitTest框架的基本使用方法

UnitTest框架介绍
框架:framework,为了解决一类事情的功能集合

UnitTest框架:是python自带的单元测试框架
自带的,可以直接使用,不需要格外安装
测试人员用来做自动化测试,作为自动化测试的执行框架,即管理和执行测试用例的

使用原因:
能够组织多个用例去执行
提供丰富的断言方法
能够生成测试报告

核心要素(组成):
-TestCase测试用例,这个测试用例是UnitTest的组成部分,作用是用来书写真正的用例代码(脚本)
-TestSuite测试套件,作用是用来组装TestCase的,即可以将多个用例脚本文件组装到一起
-TestRunner测试执行,作用是用来执行TestSuite的
-TestLoader测试加载,是对TestSuite功能的补充,作用是用来组装TestCase的
-Fixture测试夹具,是一种代码结构,书写前置方法代码和后置方法代码,即用例执行顺序:前置–>用例–>后置

TestCase测试用例
书写真正的用例代码(脚本)
步骤:
-1.导包unittest
-2.定义测试类
-3.书写测试方法
-4.执行
注意事项:
代码文件名字要满足标识符的规则
代码文件名不要使用中文
代码:

#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo(unittest.TestCase):#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头def test_method1(self):print("测试方法一")def test_method2(self):print("测试方法二")
#执行
#在类名或者方法名后边右键运行
#在类名后边,执行类中的所有测试方法
#在方法名后边,只执行当前的测试方法#在主程序中使用unittest.main()来执行
if __name__ == '__main__':unittest.main()

TestCase常见错误
1.文件名包含中文-------执行可能报错
2.右键运行没有unittest for …
解决方法一:新建一个代码文件,将之前的代码复制过来
解决方法二:使用unittest.main()运行
解决方法三:在这里插入图片描述
TestSuite和TestRunner的使用
TestSuite测试套件:将多条脚本集合在一起,就是套件,即用来组装用例的
1.导包unittest
2.实例化套件对象unittest.TestSuite()
3.添加用例方法,套件对象.addTest(测试类名(测试方法名))

TestRunner测试执行:用来执行套件对象
1.导包unittest
2.实例化执行对象unittest.TextTestRunner()
3.执行对象执行套件对象,执行对象.run(套件对象)

整体步骤:
1.导包unittest
2.实例化套件对象unittest.TestSuite()
3.添加用例方法,套件对象.addTest(测试类名(测试方法名))
4.实例化执行对象unittest.TextTestRunner()
5.执行对象执行套件对象,执行对象.run(套件对象)

代码案例
套件可以用来组装用例,创建多个代码用例

#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo1(unittest.TestCase):#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头def test_method1(self):print("测试方法1-1")def test_method2(self):print("测试方法1-2")
#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo2(unittest.TestCase):#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头def test_method1(self):print("测试方法2-1")def test_method2(self):print("测试方法2-2")
#1.导包unittest
import unittestfrom unittest1.TestCase.yongli1 import TestDemo2
from unittest1.TestCase.yongli2 import TestDemo1#2.实例化套件对象unittest.TestSuite()
suite=unittest.TestSuite()
#3.添加用例方法,套件对象.addTest(测试类名(测试方法名))
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)

添加整个测试类中的方法
方法一
套件对象.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(测试类名))
#把指定测试类中的测试用例全部添加到测试套件中
方法二
套件对象.addTest(unittest.makeSuite(测试类名))

#1.导包unittest
import unittestfrom unittest1.TestCase.yongli1 import TestDemo2
from unittest1.TestCase.yongli2 import TestDemo1#2.实例化套件对象unittest.TestSuite()
suite=unittest.TestSuite()
#3.添加用例方法,套件对象.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(测试类名))
suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestDemo1))
suite.addTest(unittest.makeSuite(TestDemo2))
#4.实例化执行对象unittest.TextTestRunner()
runner=unittest.TextTestRunner()
#5.执行对象执行套件对象,执行对象.run(套件对象)
runner.run(suite)

查看测试结果
在这里插入图片描述
TestLoader测试加载
在这里插入图片描述

作用和TestSuite作用一样,组装用例代码,同样也需要使用TextTestRunner()方法去执行
TestLoader加载用例更加方便
1.导包import unittest
2.实例化加载对象并加载用例---->得到的是套件对象
3.实例化执行对象并执行

#1.导包
import unittest
#2.实例化加载对象并加载用例---->得到的是套件对象
suite=unittest.TestLoader().discover('.','yongli*.py')   #参数1:用例所在目录,参数2:用例代码文件名
#3.实例化执行对象并执行
runner=unittest.TextTestRunner()
runner.run(suite)

练习
练习1
在这里插入图片描述
用例代码

#导包
import unittest
#定义测试类,只要继承unittest.TestCase类,就是测试类
class TestDemo1(unittest.TestCase):#书写测试方法,方法中的代码就是真正的用例代码,方法名必须以test开头def test_method(self):print("测试方法1")

执行代码

import unittestsuite=unittest.TestLoader().discover('./case','test_*.py')
unittest.TextTestRunner().run(suite)

在这里插入图片描述
练习2
在这里插入图片描述

import unittest
from tools1 import add
class TestDemo(unittest.TestCase):def test_method1(self):if add(1,1) == 2:print("测试通过")else:print("测试失败")def test_method2(self):if add(2,1) == 3:print("测试通过")else:print("测试失败")def test_method3(self):if add(3,4) == 7:print("测试通过")else:print("测试失败")def test_method4(self):if add(4,5) == 9:print("测试通过")else:print("测试失败")
import unittestsuite=unittest.TestLoader().discover('.','test_*.py')unittest.TextTestRunner().run(suite)

fixture说明
代码结构,在用例执行前后会自动执行的代码结构
tpshop登录
1.打开浏览器(一次)
2.打开网页,点击登录(每次)
3.输入用户名,密码,验证码,点击登录(每次)
4.关闭页面(每次)
5.关闭浏览器(一次)

方法级别Fixture:
在每个用例执行前后都会自动调用,方法名是固定的
def setUp(self): #前置方法,每个用例执行前调用
pass
def tearDown(self): #后置方法,每个用例执行之后都会调用
pass

类级别Fixture:
在类中所有的测试方法执行前后,会自动执行的代码,类开始前执行和类执行结束时执行一次
类级别的Fixture需要写作类方法
@classmethod
def setUpClass(cls): #前置方法,类执行前调用
pass
@classmethod
def tearDownClass(cls): #后置方法,类执行之后都会调用
pass

模块级别Fixture:
模块就是代码文件,在代码文件执行前后执行一次
在类外部定义函数
def setUpModule(): #前置
pass
def tearDownpModule(): #前置
pass

Fixture实现
在这里插入图片描述
测试用例

import unittestclass TestDemo(unittest.TestCase):@classmethoddef setUpClass(cls):print("打开浏览器")@classmethoddef tearDownClass(cls):print("关闭浏览器")def setUp(self):print("打开网页,点击登录")def tearDown(self):print("关闭页面")def test_method1(self):print("输入用户名密码验证码1,点击登录")def test_method2(self):print("输入用户名密码验证码2,点击登录")def test_method3(self):print("输入用户名密码验证码1,点击登录")

测试运行

import unittestsuite=unittest.TestLoader().discover('.','test_*.py')unittest.TextTestRunner().run(suite)

断言的使用

断言
使用代码自动判断预期结果和实际结果是否相等
在这里插入图片描述
练习
在这里插入图片描述

import unittest
from tools1 import add
class TestDemo(unittest.TestCase):def test_method1(self):self.assertEqual(2,add(1,1))def test_method2(self):self.assertEqual(3,add(1, 2))def test_method3(self):self.assertEqual(7,add(3, 4))def test_method4(self):self.assertEqual(9,add(4, 5))
import unittest
suite=unittest.TestLoader().discover('.','test_*.py')
unittest.TextTestRunner().run(suite)

实现参数化

参数化环境安装
通过参数的方式来传递数据,从而实现数据和脚本分离,并且可以实现用例的重复执行。(在书写用例方法的时候,测试数据使用变量代替,在执行的时候进行数据传递)
-unittest测试框架,本身不支持参数化,但是可以通过安装unittest扩展插件parameterized来实现。
因为参数化的插件不是unittest自带的,所以想要使用,需要进行安装
安装:pip install -i http://pypi.douban.com/simple parameterized

参数化
1.导包 from parameterized import parameterized
2.修改测试方法,将测试方法中的测试数据使用变量表示
3.组织测试数据,格式[(),(),()],一个元组就是一组测试数据
4.参数化,在测试方法上方使用装饰器@parameterized.expand(测试数据)
5.运行(直接运行TestCase或者使用suite运行)

import unittest
from parameterized import parameterized
from tools1 import addclass TestDemo(unittest.TestCase):list = [(1, 1, 2), (1, 2, 3), (3, 4, 7), (2, 3, 5)]@parameterized.expand(list)def test_method1(self,a,b,expect):self.assertEqual(expect,add(a,b))

练习1
在这里插入图片描述

import json
def getDate():with open('../package1/one.json', 'r', encoding='utf-8') as f:list=json.load(f)list1=[]for i in list:list1.append(tuple(i.values()))return list1
import unittest
from parameterized import parameterized
from lianxi2.getDate import getDate
from tools1 import addclass TestDemo(unittest.TestCase):@parameterized.expand(getDate())def test_method1(self,a,b,expect):self.assertEqual(expect,add(a,b))

测试报告和跳过

测试报告
使用第三方的报告模板,生成报告HTMLTestReport,本质是TestRunner
安装
pip install -i http://pypi.doouban.com/simple/ HTMLTestReport
使用
1.导包unittest;HTMLTestReport
2.组装用例(套件,loader)
3.使用HTMLTestReport中的runner执行
4.查看报告

import unittest
from htmltestreport import HTMLTestReportif __name__ == '__main__':#套件suite = unittest.TestLoader().discover('.', 'test_*.py')#运行runner=HTMLTestReport(报告文件目录, 报告标题,其他描述信息)runner=HTMLTestReport('report.html', '测试报告','add')runner.run(suite)

在这里插入图片描述
使用绝对路径
将来的项目是分目录书写的,使用相对路径,可能会出现找不到文件的情况,此时需要使用绝对路径
方法:
1.在项目的根目录,创建一个python文件(app.py或者config.py)
2.在这个文件中获取项目的目录,在其他代码中使用路径拼接完成绝对路径的书写

在这里插入图片描述

import os
#获取项目绝对路径
path1=os.path.abspath(__file__)   #__file__ 是特殊变量,表示当前代码文件名
base_addr=os.path.dirname(path1)
import os
import unittest
from htmltestreport import HTMLTestReport
from base_addr import base_addrif __name__ == '__main__':#套件suite = unittest.TestLoader().discover('.', 'test_*.py')#运行runner=HTMLTestReport(报告文件目录, 报告标题,其他描述信息)#runner=HTMLTestReport('report.html', '测试报告','add')#绝对路径filepath=os.path.join(base_addr,'lianxi2/report/report.html')runner=HTMLTestReport(filepath, '测试报告','add')runner.run(suite)

案例
在这里插入图片描述
tools.py

def login(username,password):if username=='admin' and password=='123456':return '登录成功'else:return '登录失败'

测试数据one.json

[{"desc": "正确的用户名和密码","username": "admin","password":"123456","excpet":"登录成功"
}, {"desc": "错误密码","username": "admin","password":"admin","excpet":"登录失败"
}, {"desc": "错误用户名","username": "admin1","password":"123456","excpet":"登录失败"
}]

获取测试数据getDate.py

import json
def getDate():with open('../package1/one.json', 'r', encoding='utf-8') as f:list=json.load(f)list1=[]for i in list:list1.append(tuple(i.values())[1:])return list1

测试用例

import unittest
from parameterized import parameterized
from lianxi2.getDate import getDate
from tools import loginclass TestDemo(unittest.TestCase):@parameterized.expand(getDate())def test_method1(self,a,b,expect):self.assertEqual(expect,login(a,b))

执行并生成测试报告

import os
import unittest
from htmltestreport import HTMLTestReport
from base_addr import base_addrif __name__ == '__main__':#套件suite = unittest.TestLoader().discover('.', 'test_*.py')#运行runner=HTMLTestReport(报告文件目录, 报告标题,其他描述信息)#绝对路径filepath=os.path.join(base_addr,'lianxi2/report/report.html')runner=HTMLTestReport(filepath, '测试报告','login')runner.run(suite)

报告
在这里插入图片描述
跳过
对于一些未完成的或者不满足测试条件的测试函数和测试类,可以执行跳过(简单来说,不想执行的代码的存测试方法,可以设置跳过)

直接将测试函数标记成跳过
@unittest.skip(“跳过原因”)
根据条件判断测试函数是否跳过
@unittest.skipIf(判断条件,reason=‘原因’) #判断条件为True,执行跳过

import unittest
from parameterized import parameterized
from lianxi2.getDate import getDate
from tools1 import loginversion=30
class TestDemo(unittest.TestCase):@parameterized.expand(getDate())def test_method1(self,a,b,expect):self.assertEqual(expect,login(a,b))@unittest.skip("跳过举例")def test_method2(self):print("测试方法二")@unittest.skipIf(version>30,"版本大于30跳过")def test_method3(self):print("测试方法三")@unittest.skipUnless(version<30,"版本小于30跳过")def test_method4(self):print("测试方法四")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/69006.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】_链表经典算法OJ:复杂链表的复制

目录 1. 题目链接及描述 2. 解题思路 3. 程序 1. 题目链接及描述 题目链接&#xff1a;138. 随机链表的复制 - 力扣&#xff08;LeetCode&#xff09; 题目描述&#xff1a; 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;…

Linux——进程间通信之SystemV共享内存

前言 SystemV通信一般包括三种&#xff1a;共享内存、消息队列和信号量。共享内存区是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间&#xff0c;这些进程间数据传递不再涉及到 内核&#xff0c;换句话说是进程不再通过执行进入内核的系统调用来…

Linux网络 | 网络层IP报文解析、认识网段划分与IP地址

前言&#xff1a;本节内容为网络层。 主要讲解IP协议报文字段以及分离有效载荷。 另外&#xff0c; 本节也会带领友友认识一下IP地址的划分。 那么现在废话不多说&#xff0c; 开始我们的学习吧&#xff01;&#xff01; ps&#xff1a;本节正式进入网络层喽&#xff0c; 友友们…

SQLGlot:用SQLGlot解析SQL

几十年来&#xff0c;结构化查询语言&#xff08;SQL&#xff09;一直是与数据库交互的实际语言。在一段时间内&#xff0c;不同的数据库在支持通用SQL语法的同时演变出了不同的SQL风格&#xff0c;也就是方言。这可能是SQL被广泛采用和流行的原因之一。 SQL解析是解构SQL查询…

Windows程序设计10:文件指针及目录的创建与删除

文章目录 前言一、文件指针是什么&#xff1f;二、设置文件指针的位置&#xff1a;随机读写&#xff0c;SetFilePointer函数1.函数说明2.函数实例 三、 目录的创建CreateDirectory四、目录的删除RemoveDirectory总结 前言 Windows程序设计10&#xff1a;文件指针及目录的创建与…

线程互斥同步

前言&#xff1a; 简单回顾一下上文所学&#xff0c;上文我们最重要核心的工作就是介绍了我们线程自己的LWP和tid究竟是个什么&#xff0c;总结一句话&#xff0c;就是tid是用户视角下所认为的概念&#xff0c;因为在Linux系统中&#xff0c;从来没有线程这一说法&#xff0c;…

DRM系列七:Drm之CREATE_DUMB

本系列文章基于linux 5.15 DRM驱动的显存由GEM&#xff08;Graphics execution management&#xff09;管理。 一、创建流程 创建buf时&#xff0c;user层提供需要buf的width,height以及bpp(bite per pixel)&#xff0c;然后调用drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &…

我们信仰AI?从神明到人工智能——信任的进化

信任的进化&#xff1a; 信任是我们最宝贵的资产。而现在&#xff0c;它正像黑色星期五促销的廉价平板电视一样&#xff0c;被一点点拆解。在过去&#xff0c;世界很简单&#xff1a;人们相信晚间新闻、那些满是灰尘书籍的教授&#xff0c;或者手持病历、眉头紧锁的医生。而如…

数据分析系列--[11] RapidMiner,K-Means聚类分析(含数据集)

一、数据集 二、导入数据 三、K-Means聚类 数据说明:提供一组数据,含体重、胆固醇、性别。 分析目标:找到这组数据中需要治疗的群体供后续使用。 一、数据集 点击下载数据集 二、导入数据 三、K-Means聚类 Ending, congratulations, youre done.

1-刷力扣问题记录

25.1.19 1.size()和.length()有什么区别 2.result.push_back({nums[i], nums[left], nums[right]});为什么用大括号&#xff1f; 使用大括号 {} 是 C11 引入的 初始化列表 语法&#xff0c;它允许我们在构造或初始化对象时直接传入一组值。大括号的使用在许多情况下都能让代码…

神经网络参数量和运算量的计算- 基于deepspeed库和thop库函数

引言 最近需要对神经网络的参数量和运算量进行统计。找到一个基于deepspeed库函数计算参数量和运算量的例子。而我之前一直用thop库函数来计算。 看到有一篇勘误博文写道使用thops库得到的运算量是MACs (Multiply ACcumulate operations&#xff0c;乘加累积操作次数&#xf…

读书笔记--分布式架构的异步化和缓存技术原理及应用场景

本篇是在上一篇的基础上&#xff0c;主要对分布式应用架构下的异步化机制和缓存技术进行学习&#xff0c;主要记录和思考如下&#xff0c;供大家学习参考。大家知道原来传统的单一WAR应用中&#xff0c;由于所有数据都在同一个数据库中&#xff0c;因此事务问题一般借助数据库事…

无用知识研究:std::initializer_list的秘密

先说结论&#xff0c;用std::initializer_list初始化vector&#xff0c;内部逻辑是先生成了一个临时数组&#xff0c;进行了拷贝构造&#xff0c;然后用这个数组的起终指针初始化initializer_list。然后再用initializer_list对vector进行初始化&#xff0c;这个动作又触发了拷贝…

Jupyterlab和notebook修改文件的默认存放路径的方法

文章目录 1.缘由2.操作流程2.1找到默认的路径2.2创建配置文件2.3修改配置文件内容2.4注意事项 1.缘由 我自己使用jupyterlab的时候&#xff0c;打开是在这个浏览器上面打开的&#xff0c;但是这个打开的文件路径显示的是C盘上面路径&#xff0c;所以这个就很麻烦&#xff0c;因…

HarmonyOS:ArkWeb进程

ArkWeb是多进程模型,分为应用进程、Web渲染进程、Web GPU进程、Web孵化进程和Foundation进程。 说明 Web内核没有明确的内存大小申请约束,理论上可以无限大,直到被资源管理释放。 ArkWeb进程模型图 应用进程中Web相关线程(应用唯一) 应用进程为主进程。包含网络线程、Vi…

基于Spring Security 6的OAuth2 系列之九 - 授权服务器--token的获取

之所以想写这一系列&#xff0c;是因为之前工作过程中使用Spring Security OAuth2搭建了网关和授权服务器&#xff0c;但当时基于spring-boot 2.3.x&#xff0c;其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0&#xff0c;结果一看Spring Security也升级…

音标-- 02-- 重音 音节 变音

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 国际音标1.重音2.音节3.变音 国际音标 1.重音 2.音节 3.变音

Adaptive LLM Transformer²

看到了一个不错的论文https://arxiv.org/pdf/2501.06252 TRANSFORMER-SQUARED: SELF-ADAPTIVE LLMS 挺有意思的&#xff0c;是一家日本AI公司SakanaAI的论文&#xff08;我以前写过他们的不训练提升模型的能力的文章&#xff0c;感兴趣可以去翻&#xff09;它家有Lion Jones坐镇…

优化代码性能:利用CPU缓存原理

在计算机的世界里&#xff0c;有一场如同龟兔赛跑般的速度较量&#xff0c;主角便是 CPU 和内存 。龟兔赛跑的故事大家都耳熟能详&#xff0c;兔子速度飞快&#xff0c;乌龟则慢吞吞的。在计算机中&#xff0c;CPU 就如同那敏捷的兔子&#xff0c;拥有超高的运算速度&#xff0…

linux 函数 sem_init () 信号量、sem_destroy()

&#xff08;1&#xff09; &#xff08;2&#xff09; 代码举例&#xff1a; #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <semaphore.h> #include <unistd.h>sem_t semaphore;void* thread_function(void* arg) …