【Python】Python代码的单元测试

Python代码的单元测试

单元测试的概念

  • 定义:是指对软件中的最小可测试单元进行检查和验证。

  • 作用:可以确保程序模块是否否和我们规范的输出,保证该模块经过修改后仍然是满足我们的需求。

单元测试的策略

如果要创建单元测试,可以遵循如下基本技巧来确保涵盖所有的测试用例。

  • 逻辑检查:给定正确的、符合预期的输入,系统是否能够执行正确的计算并遵循通过代码正确的路径?给定的输入是否涵盖通过代码的所有路径?

  • 边界检查:对于给定的输入,系统如何响应? 系统如何响应典型输入、边缘用例或无效输入?假设您期望输入的整数介于 3 和 7 之间。当您使用 5(典型输入)、3(边缘用例)或 9(无效输入)时,系统会如何响应?

  • 错误处理:当输入中出现错误时,系统会如何响应? 是否提示用户输入其他内容? 软件是否会崩溃?

  • 面向对象的检查:如果通过运行代码更改任何持久对象的状态,则该对象是否正确更新?

单元测试类的编写

  1. 首先编写要进行单元测试的代码。

    def add(x, y):"""加法函数"""return x + ydef subtract(x, y):"""减法函数"""return x - ydef multiply(x, y):"""乘法函数"""return x * ydef divide(x, y):"""除法函数"""if y != 0:return x / yelse:return ValueError("除数不能为0")
  2. 编写测试工具代码。

    # 测试代码应使用test_xxx的名称进行规范
    # 这里使用断言assert进行模拟
    # assert(断言)用于判断一个表达式,在表达式条件为 false 的时候触发异常
    # 如下代码执行正常不报错,则说明函数执行符合预期
    from myfunctions import divide# 一个简单的单元测试示例
    def test_divide(x, y, result):r = divide(x, y)assert result == rdef test_divide_error(x, y):try:divide(x, y)except ValueError:assert False
  3. 执行单元测试的工具代码。

    单元测试执行完成,无错误输出代码执行符合预期。

Python中的单元测试类

如上的代码能够满足Python中进行单元测试的需求,但如果换一套方法,我们的单元测试又需要手动编码,Python中提供了专业的单元测试工具类:unittest,以下是该单元测试类的使用方法介绍。

unittest 将我们常规用到的测试场景封装了以下断言方法,根据测试所需要的场景进行引用。

断言方法方法解释
assertEqual(a, b)检查a 和b 是否相等。
assertNotEqual(a, b)检查a 和b 是否不相等。
assertTrue(x)检查x 是否为True。
assertFalse(x)检查x 是否为False。
assertIs(a, b)检查a 和b 是否为同一对象(is)。
assertIsNot(a, b)检查a 和b 是否不是同一对象。
assertIsNone(x)检查x 是否为None。
assertIsNotNone(x)检查x 是否不是None。
assertIn(a, b)检查a 是否在b 中。
assertNotIn(a, b)检查a 是否不在b 中。
assertIsInstance(a, b)检查a 是否为b 类型的实例。
assertNotIsInstance(a, b)检查a 是否不是b 类型的实例。
assertAlmostEqual(a, b)检查a 和b 是否近似相等(适用于浮点数比较)。
assertNotAlmostEqual(a, b)检查a 和b 是否不近似相等(适用于浮点数比较)。
assertRaises(Error, func, *args, **kwargs)检查当调用function 时是否抛出了Error 异常。

unittest模块的基础使用

单元测试代码:

# unittest 是python自带的工具包,无需单独下载
import unittest
from myfunctions import *class TestMyFunctions(unittest.TestCase):def test_add(self):# assertEqual,断言测试方法,`unittest` 将我们常规用到的测试场景封装成断言方法,根据测试所需要的场景进行引用。self.assertEqual(add(1, 2), 3)self.assertEqual(add(-1, 2), 1)self.assertEqual(add(-1, -2), -3)def test_subtract(self):self.assertEqual(subtract(1, 2), -1)self.assertEqual(subtract(-1, 2), -3)self.assertEqual(subtract(-1, -2), 1)def test_multiply(self):self.assertEqual(multiply(1, 2), 2)self.assertEqual(multiply(-1, 2), -2)self.assertEqual(multiply(-1, -2), 2)def test_divide(self):self.assertEqual(divide(1, 2), 0.5)self.assertEqual(divide(-1, 2), -0.5)self.assertEqual(divide(-1, -2), 0.5)

unittest 代码并不能够直接运行,有以下执行方法:

  • 命令行:

    python -m unittest test_myfunctions.py

    注意:这里的启动如果写成 python.exe -m unittest .\test_myfunctions.py 会报如下错误。

  • main 函数:

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

unittest模块的前置方法

在实际的测试中可能同时存在多个前置相同的测试,unittest模块提供了setUp()用于在测试开始前执行相关环境的设置,tearDown()setUp() 方法之后进行执行。

注:这里的 setUp 和 tearDown 是固定的函数名,不允许更改。

要测试的代码:

def divide(x, y):"""除法函数"""print("divide called")if y != 0:return x / yelse:raise ValueError("除数不能为0")

测试工具类:

import unittest
from myfunctions import *class TestMyFunctions(unittest.TestCase):def setUp(self):self.test_value_a = 10self.test_value_b = 5self.test_value_c = 0print("setUp called")def tearDown(self):del self.test_value_adel self.test_value_bdel self.test_value_cprint("tearDown called")def test_divide(self):self.assertEqual(divide(self.test_value_a, self.test_value_b), 2)self.assertRaises(ValueError, divide, self.test_value_a, self.test_value_c)if __name__ == '__main__':unittest.main()

代码执行测试:

可以看到,在执行函数测试之前,首先调用了 setUp() 前置方法,然后执行测试,测试结束后,调用 tearDown() 清理单元测试。

测试覆盖率

覆盖率是用来度量测试完整性的手段,是测试效果衡量的标准,是测试技术有效性的度量: 覆盖率 = (至少被执行一次的项目(item)数) / (项目的总数)

Python中提供了测试覆盖率的模块类:coverage,该第三方包需要手动安装。

这里使用如下方法直接进行代码的测试覆盖率分析

# 调用单元测试工具类
coverage run -m unittest discover
# 输出测试报告
coverage report

这里的代码测试覆盖率较低,对单元测试工具类进行优化,要测试的代码如下:

def add(x, y):"""加法函数"""return x + ydef subtract(x, y):"""减法函数"""return x - ydef multiply(x, y):"""乘法函数"""return x * ydef divide(x, y):"""除法函数"""print("divide called")if y != 0:return x / yelse:raise ValueError("除数不能为0")

优化后的单元测试方法为:

import unittest
from myfunctions import *class TestMyFunctions(unittest.TestCase):def setUp(self):self.test_value_a = 10self.test_value_b = 5self.test_value_c = 0print("setUp called")def tearDown(self):del self.test_value_adel self.test_value_bdel self.test_value_cprint("tearDown called")def test_add(self):self.assertEqual(add(self.test_value_a, self.test_value_b), 15)self.assertEqual(add(self.test_value_a, self.test_value_c), 10)def test_subtract(self):self.assertEqual(subtract(self.test_value_a, self.test_value_b), 5)self.assertEqual(subtract(self.test_value_a, self.test_value_c), 10)def test_multiply(self):self.assertEqual(multiply(self.test_value_a, self.test_value_b), 50)self.assertEqual(multiply(self.test_value_a, self.test_value_c), 0)def test_divide(self):self.assertEqual(divide(self.test_value_a, self.test_value_b), 2)self.assertRaises(ValueError, divide, self.test_value_a, self.test_value_c)if __name__ == '__main__':unittest.main()

结果测试

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

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

相关文章

比特币再次上演“初五破五”精彩戏法!

号外:2.13教链内参《随着BTC一度突破5万刀,超过9成持有者已盈利》 比特币无惧美通胀数据阻击,在短暂回落之后坚决反攻,在中国农历大年初五,2月14日情人节,大涨6%,从48k绝地反击,再次…

游戏服务器租用多少钱一年?

游戏服务器租用多少钱一年?1个月游戏服务器费用多少?阿里云游戏服务器26元1个月、腾讯云游戏服务器32元,华为云26元,游戏服务器配置从4核16G、4核32G、8核32G、16核64G等配置可选,游戏专业服务器公网带宽10M、12M、15M…

吃瓜 - 春山学

2024年春晚看似一个贵州献上的歌舞节目《上春山》(白敬亭、魏大勋、魏晨合唱)引发网络破案:白敬亭有没有抢C位和故意换衣服?网上的“白敬亭春晚走位风波”不断升级,喂到嘴里的瓜不吃也不行啊。 三人都是明侦的元老嘉…

JavaScript中的Symbol:加密与安全性

JavaScript中的Symbol是一种唯一且不可变的数据类型,引入了一种新的基本数据类型,用于表示独一无二的标识符。在本文中,我们将深入介绍JavaScript中的Symbol,讨论如何将其应用于JS加密中,提供案例代码,并说…

C#通过重写虚方法实现加、减、乘、除运算 通过多态确定人类的说话行为

目录 一、涉及到的知识点1 1.虚方法 2.重写方法 3.重写方法与重载方法的区别 4.通过KeyPressEventArgs.KeyChar限制键盘输入的内容 5.if-else if-else嵌套转换为switch case 二、 涉及到的知识点2 1.多态性 2.使用多态性的注意事项 3. 使用虚方法实现多态性 三、实…

黑马Java——集合进阶(不可变集合、Stream流、方法引用)

目录 一、不可变集合 1、创建不可变集合的应用场景 2、创建不可变集合的书写格式 2.1、不可变的List集合 2.2、不可变的Set集合 2.3、不可变的Map集合 3、小结 二、Stream流 1、体验Stream流的作用 2、Stream流的思想 3、Stream流的使用步骤 3.1、单列集合获取Strea…

站在C/C++的肩膀速通Java面向对象

默认学过C或C,对变量、表达式、选择、循环都会。 运行特征 解释型语言(JavaScript、Python等) 源文件-(平台专属解释器)->解释器中执行编译型语言(C、Go等) 源文件-(平台编译器)->平台可执行文件Java 源文件-(…

【白话前端】JS库的作用和常见的九种类型—值得收藏

js库就好比预制菜,我们想吃美食没必要从买菜、择菜、炒菜开始,直接加工就行。 一、什么是JS库 JS库(JavaScript Library)是指一组封装好的函数、方法、类等,用于简化开发者的编程工作。它们通常提供了常用的功能和算…

Android ·移动应用开发 创建第一个Android项目

文章目录 一、创建第一个Android项目1.1 准备好Android Studio1.2 运行程序1.3 程序结构是什么app下的结构res - 子目录(所有图片、布局、字符串等资源)AndroidManifest.xml 有四大组件,程序添加权限声明 Project下的结构 二、开发android时&…

【ArcGIS Pro二次开发】(79):符号系统_CIMUniqueValueRenderer

CIMUniqueValueRenderer是ArcGIS Pro SDK中的一个类,用于创建唯一值渲染器(Unique Value Renderer)。 在ArcGIS Pro中长这样: 通过对CIMUniqueValueRenderer的操作,可以对符号系统进行更改,实现很多功能。…

尚硅谷最新Node.js 学习笔记(一)

目录 一、Nodejs入门 1.1、为什么要学习Nodejs? 1.2、Nodejs是什么? 1.3、Nodejs的作用 1.4、Nodejs安装 1.5、Nodejs初体验 1.6、编码注意事项 二、Buffer(缓冲器) 2.1、概念 2.2、特点 2.3、使用 创建Buffer Buffe…

Cocos2dx-lua ScrollView[一]基础篇

一.ScrollView概述 cocos游戏中ScrollView控件大量使用,95%以上的项目都会使用ScrollView,个别游戏可能全部使用翻页的滑动效果。如果想要精通Cocos的UI开发,精通ScrollView控件非常关键,因此对ScrollView的使用进行总结很有必要。 下文缩写说明:sv = ScrollView, item代…

嵌入式Linux网络编程入门:轻松构建网络通信

大家好,今天给大家介绍嵌入式Linux网络编程入门:轻松构建网络通信,文章末尾附有分享大家一个资料包,差不多150多G。里面学习内容、面经、项目都比较新也比较全!可进群免费领取。 为什么选择嵌入式Linux网络编程&#x…

vue3+ts+vite+uniapp项目常见问题

vue3tsvite中""路径失效的问题 ""需要进行配置: 首先npm install types/node --save-dev(需要用到node其中的path)接着在vite.config.ts配置文件中进行配置: 引入 import path from ‘path’,然…

Imgui(2) | macOS 绘制 CPU 占用率曲线

Imgui(2) | macOS 绘制 CPU 占用率曲线 文章目录 Imgui(2) | macOS 绘制 CPU 占用率曲线0. 简介1. 绘制曲线 - 以正弦函数为例1.1 基于 sf::RectangleShape 的渲染 - 不好看,效率低1.2 基于 sf::VertexArray 的绘制 2. 获取和绘制所有 CPU 的占用率2.1 测试程序 - 用…

LeetCode Python - 16.最接近的三数之和

目录 题目答案运行结果 题目 给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数,使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1: 输入:nums [-1,2,1,-4],…

基于轻量级卷积神经网络模型MobileNet开发构建基于GTSRB数据集的道路交通标识识别系统

相信经常需要开车出行的人对于各种各样的道路交通标识定是不陌生的,但是对于经常不开车的人来说生活中出现的形形色色的道路交通标识就未必都能认出来了,本文的主要目的就是想要基于CNN来开发构建道路交通标识识别分析系统,实现看图识标&…

谷歌浏览器安装扩展程序axure-chrome-extension

注: 文末附扩展附件:axure-chrome-extension_v0.7.0.crx 1、安装扩展程序axure-chrome-extension 找到axure-chrome-extension.crx,把axure-chrome-extension.crx后缀改为zip,然后解压,得到一个文件夹 2、打开谷歌浏览…

枚举知识点解析

枚举是什么?枚举就是列举, 将东西一一列举出来。 生活中有许多地方需要用到枚举, 比如一年有12个月,一星期有7天, 这些都需要进行枚举。 那么, 如何进行枚举的定义呢? 如下 枚举中的值是一种…

ubuntu22.04@laptop OpenCV Get Started: 008_image_filtering_using_convolution

ubuntu22.04laptop OpenCV Get Started: 008_image_filtering_using_convolution 1. 源由2. convolution应用Demo2.1 C应用Demo2.2 Python应用Demo 3. 重点分析3.1 identity矩阵3.2 all ones 5x5矩阵3.3 blur 5x5矩阵3.4 GaussianBlur 5x5矩阵3.5 medianBlur 5x5矩阵3.6 Sharpe…