【Python】Python代码的单元测试

news2024/11/27 4:26:07

Python代码的单元测试

单元测试的概念

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

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

单元测试的策略

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

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

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

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

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

单元测试类的编写

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

    def add(x, y):
        """加法函数"""
        return x + y
    
    def subtract(x, y):
        """减法函数"""
        return x - y
    
    def multiply(x, y):
        """乘法函数"""
        return x * y
    
    def divide(x, y):
        """除法函数"""
        if y != 0:
            return x / y
        else:
            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 == r
    
    
    def 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 / y
    else:
        raise ValueError("除数不能为0")

测试工具类:

import unittest
from myfunctions import *

class TestMyFunctions(unittest.TestCase):

    def setUp(self):
        self.test_value_a = 10
        self.test_value_b = 5
        self.test_value_c = 0
        print("setUp called")

    def tearDown(self):
        del self.test_value_a
        del self.test_value_b
        del self.test_value_c
        print("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 + y

def subtract(x, y):
    """减法函数"""
    return x - y

def multiply(x, y):
    """乘法函数"""
    return x * y

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

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

import unittest
from myfunctions import *

class TestMyFunctions(unittest.TestCase):

    def setUp(self):
        self.test_value_a = 10
        self.test_value_b = 5
        self.test_value_c = 0
        print("setUp called")

    def tearDown(self):
        del self.test_value_a
        del self.test_value_b
        del self.test_value_c
        print("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.coloradmin.cn/o/1448814.html

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

相关文章

2024最新APP下载单页源码 带管理后台 首发

2024最新APP下载单页源码 带管理后台 首发 新版带后台管理app应用下载页,自动识别安卓苹果下载页,带管理后台,内置带3套App下载模板带中文模板/英文模板随时切换。 下载地址2023最新APP下载单页源码 带管理后台 .zip官方版下载丨最新版下载丨绿色版下载…

重复导航到当前位置引起的。Vue Router 提供了一种机制,阻止重复导航到相同的路由路径。

代码&#xff1a; <!-- 侧边栏 --><el-col :span"12" :style"{ width: 200px }"><el-menu default-active"first" class"el-menu-vertical-demo" select"handleMenuSelect"><el-menu-item index"…

深度学习-吴恩达L1W2作业

作业1&#xff1a;吴恩达《深度学习》L1W2作业1 - Heywhale.com 作业2&#xff1a;吴恩达《深度学习》L1W2作业2 - Heywhale.com 作业1 你需要记住的内容&#xff1a; -np.exp&#xff08;x&#xff09;适用于任何np.array x并将指数函数应用于每个坐标 -sigmoid函数及其梯度…

【教学类-16-02】20240214《数字卡片1-9(正方形)华光彩云_CNKI》

背景需求&#xff1a; 前期坐过长方形A4纸的数字卡片 【教学类-16-01】20221121《数字卡片9*2》&#xff08;中班)_数字卡片pdf-CSDN博客文章浏览阅读897次。【教学类-16-01】20221121《数字卡片9*2》&#xff08;中班)_数字卡片pdfhttps://blog.csdn.net/reasonsummer/artic…

B端系统从0到1:有几步,其中需求分析要做啥?

一款B系统从无到有都经历了啥&#xff0c;而其中的需求分析又要做什么&#xff1f;贝格前端工场给老铁们做一下分析&#xff0c;文章写作不易&#xff0c;如果咱们有界面设计和前端开发需求&#xff0c;别忘了私信我呦&#xff0c;开始了。 一、B端系统从0到1都有哪些要走的步骤…

第13章 网络 Page729~733 链式任务反应

链式任务反应 当io_service对象身上没有任务的时候&#xff0c;当前正在运行的run()过程就结束了。这时再往它身上添加任务&#xff0c;程序收不到任务完成事件。 如果本次任务完成后&#xff0c;run()函数退出前再添加一项或更多任务&#xff0c;这就叫链式任务。 在asio的…

日志监控须知

在这个领域,最流行的应该是ELK. ELK可以让收集日志,检索日志更加的简单,让定位日志问题更加的高效,在也不需要挨个登录服务器,然后用一堆Linux命令去搜索日志了. ELK ( Elasticsearch Logstash Kibana ) ELK架构: 各个微服务,通过某种机制把自己的日志交给Logstash 这里的某…

455. Assign Cookies(分发饼干)

题目描述 假设你是一位很棒的家长&#xff0c;想要给你的孩子们一些小饼干。但是&#xff0c;每个孩子最多只能给一块饼干。 对每个孩子 i&#xff0c;都有一个胃口值 g[i]&#xff0c;这是能让孩子们满足胃口的饼干的最小尺寸&#xff1b;并且每块饼干 j&#xff0c;都有一个…

代码随想录算法训练营Day25|回溯算法·组合总和III,电话号码的字母组合

组合总和III 题目&#xff1a;找出所有相加之和为n的k个数的组合。组合中只允许含有1-9的正整数&#xff0c;并且每种组合中不存在重复的数字。 组合变量个数为k个&#xff0c;和为n。简单思路是使用k重循环&#xff0c;一层层找出来&#xff0c;然后把每一层的数相加&#x…

数据库被人破解,删除数据,勒索

事情是这样的&#xff0c;我买了一台服务器自己部署项目玩儿玩儿&#xff0c;我的数据库运行在3306端口&#xff0c;密码没改&#xff0c;就是默认的123456&#xff0c;诡异的事情发生了&#xff0c;用了一段时间之后&#xff0c;数据库突然连接不上了&#xff0c;我一通操作猛…

【深度学习】“智能皮肤:深度学习驱动的‘智慧之眼‘应用如何革新皮肤病诊疗未来“

在一个不久的未来世界&#xff0c;医疗科技取得了惊人的突破。一款名为“智慧之眼”的神秘应用横空出世&#xff0c;它如同科幻小说中的神器&#xff0c;能够通过摄像头扫描皮肤病变&#xff0c;并借助深度学习技术迅速得出专业级别的诊断结果。这个革新性的故事始于一场科研马…

Sentinel 流控-链路模式

链路模式 A B C 三个服务 A 调用 C B 调用 C C 设置流控 ->链路模式 -> 入口资源是 A A、B 服务 package com.learning.springcloud.order.controller;import com.learning.springcloud.order.service.BaseService; import org.springframework.beans.factory.annotatio…

ClickHouse--05--MergeTree 表引擎

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 MergeTree 系列表引擎前言MergeTree 系列表引擎 --功能MergeTree 系列表引擎 --种类 1.MergeTree1.1MergeTree 建表语句&#xff1a;1.2 MergeTree 引擎表目录解析查…

【AI视野·今日Robot 机器人论文速览 第七十八期】Wed, 17 Jan 2024

AI视野今日CS.Robotics 机器人学论文速览 Wed, 17 Jan 2024 Totally 49 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers Safe Mission-Level Path Planning for Exploration of Lunar Shadowed Regions by a Solar-Powered Rover Authors Olivier L…

第13讲我创建的投票列表实现

新建我创建的投票页面 {"path": "pages/createVoteList/createVoteList","style": {"navigationBarTitleText": "我创建的投票"}}个人中心页面&#xff0c;加下 点击 “我创建的投票”跳转列表页面 goVoteList:function(){u…

ChatGPT高效提问—prompt实践(教师助手)

ChatGPT高效提问—prompt实践&#xff08;教师助手&#xff09; 下面来看看ChatGPT在教育领域有什么用途。 首先设定ChatGPT的角色为高中教师助手。 输入prompt: ChatGPT输出&#xff1a; ​ 教师助手的角色已经设置完成。下面通过几种不同的情景演示如何使用。 1.1.1 制定…

PhP+vue企业原材料采购系统_cxg0o

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。互联网逐步进入千家万户&#xff0c;改变传统的管理方式&#xff0c;原材料采购系统以互联网为基础&#xff0c;利用php技术&#xff0c;结合vue框架和MySQL数据库开发设计一套原材料采购系统&#xff0c;提高工作效率的…

编译原理实验2——自上而下语法分析LL1(包含去消除左递归、消除回溯)

文章目录 实验目的实现流程代码运行结果测试1&#xff08;含公共因子&#xff09;测试2&#xff08;经典的ii*i文法&#xff0c;且含左递归&#xff09;测试3&#xff08;识别部分标识符&#xff09; 总结 实验目的 实现自上而下分析的LL1语法分析器&#xff0c;给出分析过程 …

快速搭建PyTorch环境:Miniconda一步到位

快速搭建PyTorch环境&#xff1a;Miniconda一步到位 &#x1f335;文章目录&#x1f335; &#x1f333;一、为何选择Miniconda搭建PyTorch环境&#xff1f;&#x1f333;&#x1f333;二、Miniconda安装指南&#xff1a;轻松上手&#x1f333;&#x1f333;三、PyTorch与Minic…

机器学习:ROC曲线笔记

ROC曲线&#xff08;Receiver Operating Characteristic Curve&#xff09;是一种用于评估二分类模型性能的图形化工具&#xff0c;主要用于展示在不同阈值&#xff08;Threshold&#xff09;下模型的真阳性率&#xff08;True Positive Rate&#xff0c;TPR&#xff09;和假阳…