Python 编程必不可少的unittest测试框架

news2024/9/25 7:24:58

一段表面看起来平平无常的代码,很可能暗藏很多bug无法一眼看透,没有经过测试的代码是不可靠的代码。上一篇讲过pytest测试框架这次我们换个框架。

unittest 是一个单元测试框架,单元测试完成对一个模块、一个类或一个函数的运行结果进行检验的测试工作。单元测试是对一个程序最基础的组成部分进行正确性验证,只有所有的单元测试不存在问题才能保证整体程序的正确性。

一个优秀的程序不仅能够写出优秀的功能代码,也要能够写一手优秀的测试代码。

测试驱动开发:要求在开始编写功能代码之前,先编写测试代码,然后编写能够通过测试的代码,通过测试来推动整个开发过程进行。
在这里插入图片描述

通过编写测试代码,不仅使当前的代码设计能够满足预期的功能需要,在将来对代码进行修改时,也能够保证修改后代码的输出结果是正确的。

unittest 是 python 自带的单元测试框架,test fixture「测试框架」、test case「测试用例」、test suite「测试集合」、test runner「测试运行器」是 unittest 的四个核心概念。

test fixture:测试框架,在测试开始前进行一些必要的准备工作,或在测试结束时进行相关的清理工作。
test case:测试用例,作为一个单独的测试单元,提供实际的测试逻辑,检测特定的输入所对应的输出结果是否与预期一致。

test suite:测试集合,将多个测试用例组合起来,统一进行测试。既可以由多个测试用例组成,也可以由多个测试集合组成,还可以是测试用例和测试集合共同组成。

test runner:测试运行器,用于执行测试和输出测试结果。

编写测试代码时,我们需要编写一个继承自 unittest.TestCase 的测试类,在该类中以 test 开头的方法就
是测试方便,在测试过程中会被执行,不以 test 开头的方法在测试时会被跳过。在测试类中有两个特殊的方法 setUp 和 tearDown,这两个方法分别完成资源的创建和销毁,unittest 在调用测试方法之前会先执行 setUp 方法,在测试方法执行完成后会执行 tearDwon 方法,这样将资源的创建与销毁统一起来,不必在测试方法中编写重复的相同代码。

以下是一个测试 math 类中 fabs 函数和 isfinite 函数的单元测试,文件命名为 testMath.py。

import unittest
import math

class TestMath(unittest.TestCase):
    def setUp(self):
      print("setup Func ...")

 def test_abs(self):
        self.assertEqual(3, math.fabs(1 - 4))
        self.assertNotEqual(1, math.fabs(1 - 2))

    def test_isfinite(self):
        self.assertTrue(math.isfinite(456789))
        self.assertFalse(math.isfinite(float('inf')))
        self.assertFalse(math.isfinite(float('nan')))

    def tearDown(self):
        print("tearDown Func ...")

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

可以通过以下任意一个命令来运行该单元测试

python testMath.py或python -m unittest testMath

如果单元测试文件中未实现上面的最后两行代码,则只能使用 python-m unittest testMath 来启动测试。

该单元测试的输出结果如下:

(.venv) ➜  study python -m unittest testMathsetup Func ...tearDown Func ...Fsetup Func ...tearDown Func ....======================================================================FAIL: test_abs (testMath.TestMath)----------------------------------------------------------------------Traceback (most recent call last):  File "/path/testMath.py", line 12, in test_abs    self.assertNotEqual(1, math.fabs(1 - 2))AssertionError: 1 == 1.0
----------------------------------------------------------------------Ran 2 tests in 0.001s
FAILED (failures=1)

从以上测试结果中可以看出 setUp 和 tearDown 函数分别被执行了两次,共进行了两个单元测试,其中有一个出现了错误,在错误提示信息中有错误的语句,错误的位置,以及错误出现的原因。我们共有两个单元测试,因此需要进行两个资源的创建和释放,所以 setUp 和 taerDown 函数各被执行了两次。在每个单元测试运行之前均进行了资源的创建「setUp 函数被执行」,在单元测试运行之后均进行了资源的释放「tearDown 函数被执行」。

unittest 不仅能够实现对基本函数的测试,同样还能够对复杂的应用进行测试,接下来我们共同来看下如何使用 unittest 来测试 Flask 应用的代码。

import unittestimport osfrom server import create_appfrom server.module import dbfrom server.models.user import User, Permissionimport tempfileimport json

DEFAULT_USERNAME = 'test'DEFAULT_PASSWORD = 'test'
class ServerTestUser(unittest.TestCase):    def setUp(self):        self.db_fd, self.db_file= tempfile.mkstemp()        app = create_app()        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + self.db_file        self.app = app        self.clinet = app.test_client()        with app.app_context():            db.drop_all()            db.create_all()            user = User.create(                name=DEFAULT_USERNAME,                password=DEFAULT_PASSWORD,                permission=Permission.ADMINISTRATOR,                active=True)            self.headers = self.login()

    def login(self):        rv = self.clinet.post('/api/v01/user/login',                               data=json.dumps(dict(user_name='test', password='test')),                               content_type='application/json')        data = json.loads(rv.data)        token = data['token']        headers = {"Authorization":"Bearer "+token, 'Content-Type': 'application/json'}        return headers
    def test_login(self):        rv = self.clinet.post('/api/v01/user/login',                               data=json.dumps(dict(user_name=DEFAULT_PASSWORD, password=DEFAULT_PASSWORD)),                               content_type='application/json')        data = json.loads(rv.data)        self.assertEqual(rv.status_code, 200)        self.assertEqual(data['status'], 1)        self.assertEqual(data['name'], 'test')        self.assertIsNotNone(data['token'])        self.assertIsNotNone(data['admin'])        self.assertIsNotNone(data['expire'])
    def test_add_user(self):
        rv = self.clinet.post('/api/v01/user',                               data=json.dumps(dict(user_name='123', password='123', admin=False)),                               headers=self.headers)        data = json.loads(rv.data)        self.assertEqual(data['status'], 1)


    def tearDown(self):        with self.app.app_context():            db.session.remove()            db.drop_all()        os.close(self.db_fd)        os.unlink(self.db_file)

以上代码完成了使用 RESTful API 登录以及登录后添加新用户的 API 的测试。

在 setUp 函数中创建了 Flask 对象,通过 tempfile 创建临时文件用于数据存储,在 Flask 的运行环境中生成数据表、加入默认的用户,同时获取登录 Token 用户后面的 API 测试认证。在 tearDwon 函数中完成测试后的资源清理工作,删除数据表并删除创建的临时文件。

在 testlogin 和 testadd_user 函数中完成了对登录 API 和用户添加 API 的测试,并检测返回结果的正确性。

使用命令 python-m unittest discover-v-s tests 启动测试,测试结果如下:

(.venv) ➜  server git:(master) ✗ python -m unittest discover -v -s tests
test_add_user (test_user.ServerTestUser) ... ok
test_login (test_user.ServerTestUser) ... ok

----------------------------------------------------------------------
Ran 2 tests in 0.741s

OK

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

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

相关文章

SpringSecurity之注销与自动登录

前言 前面我们讲解了用户的登录以及用户授权的过程。今天我们看一下,系统中常用的注销与自动登录各功能! 注销操作 注销操作,首先需要在我们的配置类中添加上我们的注销路径。主要配置详见下方标红处代码,标记了退出的路径以及…

java轻量级框架MiniDao的详解

MiniDao是一款基于Java语言开发的轻量级持久层框架,它的目标是简化数据库操作流程,提高开发效率,减少代码量。MiniDao采用简单的注解配置方式,可以很容易地与Spring等常用框架集成使用。 MiniDao的主要特点包括: 简单…

浙大数据结构网课第一周入门

题目详情 Given a sequence of K integers { N1​, N2​, ..., NK​ }. A continuous subsequence is defined to be { Ni​, Ni1​, ..., Nj​ } where 1≤i≤j≤K. The Maximum Subsequence is the continuous subsequence which has the largest sum of its elements. For …

RBF-UKF径向基神经网络结合无迹卡尔曼滤波估计锂离子电池SOC(附MATLAB代码)RBF神经网络训练部分

1.清空变量 close all clear,clc 2.导入数据用以RBF神经网络训练,一共14组,训练数据P(第一列为电压值,第二列为SOC值,第三列为电流值。),并将所有数据存储在变量PP中,所有电压数据…

蓝桥杯:优秀的拆分

蓝桥杯:优秀的拆分https://www.lanqiao.cn/problems/801/learning/ 目录 题目描述 输入描述 输出描述 输入输出样例 输入 输出 输入 输出 题目分析(位运算) AC代码(Java) 题目描述 一般来说,一个正整数可以拆…

【】:addService 和 getService

一次完整的 Binder IPC 通信过程通常是这样: 首先 Binder 驱动在内核空间创建一个数据接收缓存区; 接着在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用…

无线传感器网络硬件设计简介

无线传感器网络硬件设计简介 无线传感器网络因其巨大的应用前景越来越受到学术界和工业界的广泛关注。本文介绍了无线传感器网络节点的体系结构,分析比较了国内外当前典型的硬件平台,重点讨论了目前无线传感器网络节点常用的处理器、射频芯片、电源和传…

孩子为什么不能玩抖音精彩回答,共勉

2 可是,为什么我的同学、哥哥姐姐…… 反正身边好多人都在玩? 我不知道你父母有没有告诉你这个道理: 你把时间花在哪儿, 你就会成为什么样的人。 他们爱玩,是因为两个字: 空虚。 想象一下&#xff…

02、Cadence使用记录之创建元器件---原理图和封装(OrCAD Capture CIS)

02、Cadence使用记录之创建元器件—器件原理图符号和封装(OrCAD Capture CIS) 参考的教程是B站的视频:allegro软件入门视频教程全集100讲 前置教程: ## 01、Cadence使用记录之新建工程与基础操作(原理图绘制&#xf…

新闻文本分类任务:使用Transformer实现

❤️觉得内容不错的话,欢迎点赞收藏加关注😊😊😊,后续会继续输入更多优质内容❤️ 👉有问题欢迎大家加关注私戳或者评论(包括但不限于NLP算法相关,linux学习相关,读研读博…

13.网络爬虫—多进程详讲(实战演示)

网络爬虫—多进程详讲 一进程的概念二创建多进程三进程池四线程池五多进程和多线程的区别六实战演示北京新发地线程池实战 前言: 🏘️🏘️个人简介:以山河作礼。 🎖️🎖️:Python领域新星创作者&#xff0c…

Spark SQL实战(07)-Data Sources

1 概述 Spark SQL通过DataFrame接口支持对多种数据源进行操作。 DataFrame可使用关系型变换进行操作,也可用于创建临时视图。将DataFrame注册为临时视图可以让你对其数据运行SQL查询。 本节介绍使用Spark数据源加载和保存数据的一般方法,并进一步介绍…

node安装

一、下载nodejs的安装包: 下载地址:https://nodejs.org/zh-cn/download 根据自己电脑系统及位数选择,一般都选择windows64位.msi格式安装包 二、改变nodejs的下载依赖包路径 安装完nodejs后,也同时安装了npm, npm是…

半监督语义分割_paper reading part1

Assignment 要解决的问题思路方法结果自己的想法 01 A Survey on Semi-Supervised Semantic Segmentation University of Granada, 18071, Granada, Spain 2023.02出版 problem to solve ss先前的(19年)不适用先前的调研包含弱监督,ss不…

Docker Desktop使用PostgreSql配合PGAdmin的使用

在看此教程之前,请先下载安装Docker Desktop 安装成功可以查看版本 然后拉取postgresql的镜像:docker pull postgres:14.2 版本可以网上找一个版本,我的不是最新的 发现会报一个问题 no matching manifest for windows/amd64 10.0.19045 i…

小心,丢失的消息!RocketMQ投递策略帮你解决问题!博学谷狂野架构师

RocketMQ消息投递策略 作者: 博学谷狂野架构师GitHub:GitHub地址 (有我精心准备的130本电子书PDF)只分享干货、不吹水,让我们一起加油!😄 前言 RocketMQ的消息投递分分为两种:一种是生产者往MQ …

java中级面试题

1.假如有两个线程共同操作数据库,以乐观锁的角度考虑,怎么确保不会发生并发问题? PS:考点是CAS,比较并替换。CAS中有三个值,内存中的值,新值,旧值。 假如内存中的值是2000&#xf…

[C++]string类的模拟实现和相关函数的详解

目录string总体架构具体实现默认成员函数构造函数构造拷贝函数析构函数赋值重载[]相关操作函数c_str() && size()reserve() && resize()push_back() && append()find()inserterase() && clear其余操作符重载< 、 <、 >、 >、 !<…

【系统集成项目管理工程师】项目整体管理

&#x1f4a5;十大知识领域&#xff1a;项目整体管理 项目整体管理包括以下 6 个过程: 制定项目章程定项目管理计划指导与管理项目工作监控项目工作实施整体变更控制结束项目或阶段过程 一、制定项目章程 制定项目章程。编写一份正式文件的过程&#xff0c;这份文件就是项目章程…

某程序员哀叹:月薪四五万,却每天极度焦虑痛苦,已有生理性不适,又不敢裸辞,怎么办?

高薪能买来快乐吗&#xff1f; 来看看这位程序员的哀叹&#xff1a; 实在是扛不住了&#xff0c;每天都在极度焦虑和痛苦中度过&#xff0c;早上起来要挣扎着做心理建设去上班&#xff0c;已经产生生理性的头晕恶心食欲不振。有工作本身的原因&#xff0c;更多是自己心态的问…