一文掌握python单元测试unittest(二)

 接上篇:https://blog.csdn.net/qq_38120851/article/details/141642215

目录

四、参数化测试

1、使用 subTest

2、使用装饰器

3)使用第三方库parameterized

五、跳过测试

1、使用 unittest.skip() 或 unittest.skipIf() 装饰器:

2、使用 setUp() 方法中的断言来跳过整个测试类:

3、在测试方法内部使用 unittest.TestCase.skipTest() 方法:

六、预期失败

七、自定义测试结果类

八、参数化测试进阶,parameterized 库

1、什么是 parameterized?

2、安装 parameterized

3、使用类属性定义参数集:parameterized.expand

4、使用外部文件加载参数集

        1)  使用 CSV 文件加载参数集

        2)  使用yaml加载参数集,推荐使用yaml, 因为yaml结构更清晰,方便维护。

5、使用函数生成参数集

6、使用字典参数集

7、使用param和name_func提供更多的信息,比如参数的名称、描述。

8、使用类级别的参数化

        1)使用属性元组和元组列表

        2)使用字典列表

        3)使用 class_name_func 来动态生成测试类的名字

九、参数化测试进阶,ddt 库

1、通过 pip 安装:

2、data:为测试函数提供多个数据集。

        1)data传参list(同理如果传tuple,即将相应的list换成tuple): 

        2)data传参dict: 

3、unpack:解包

4、file_data:从文件中加载测试数据。每个用例的key会添加到用例名中去。

        1)加载json文件

        2)加载yaml文件

5、named_data:为每组测试数据提供一个名称,这有助于识别测试案例。


四、参数化测试

参数化测试是一种常见的需求,特别是在需要针对一组数据多次运行相同的测试逻辑时。unittest 本身并没有直接支持参数化测试的功能,但是可以通过一些技巧来实现这一点。

通常用第三方库pytest或parameterized来进行参数化测试。

1、使用 subTest

unittest 提供了 subTest 方法来实现参数化测试,可以在测试方法内部使用它来创建子测试,每个子测试都有一个特定的上下文。即结合循环来间接实现参数化测试。

import unittest


class TestMultiplication(unittest.TestCase):

    def test_multiply(self):
        cases = [
            (2, 3, 6),
            (2, -3, -6),
            (-2, -3, 6)
        ]

        for x, y, expected in cases:
            with self.subTest(x=x, y=y):
                self.assertEqual(x * y, expected)
                print(f'Test passed for x={x}, y={y}, expected={expected}')


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

2、使用装饰器

缺点是实际是运行了3个用例,但是控制台上输出是Ran 1 tests in 0.000s,统计测试输出报告时比较麻烦。

import unittest

class parameterized(object):
    @staticmethod
    def expand(argvalues):
        def decorator(func):
            def wrapper(*args):
                for arg in argvalues:
                    func(*(args + arg))
            return wrapper
        return decorator

class TestMathFunctions(unittest.TestCase):

    @parameterized.expand([
        (2, 3, 5),
        (3, 4, 7),
        (1, 9, 10)
    ])
    def test_add(self, a, b, expected):
        result = a + b
        self.assertEqual(result, expected)
        print("Test add with a={}, b={}, expected={}".format(a, b, expected))


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

但是控制台上输出是Ran 1 test in 0.000s

3)使用第三方库parameterized

import unittest
from parameterized import parameterized


class TestMathFunctions(unittest.TestCase):
    @parameterized.expand([
        (1, 2, 3),
        (4, 5, 9),
        (10, -2, 8)
    ])
    def test_add(self, a, b, expected):
        result = a + b
        self.assertEqual(result, expected)


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

控制台上输出是Ran 3 tests in 0.000s

五、跳过测试

1、使用 unittest.skip()unittest.skipIf() 装饰器

  • unittest.skip(reason):可以无条件地跳过一个测试方法,并给出跳过的理由。
  • unittest.skipIf(condition, reason):只有当给定的条件为 True 时才会跳过测试方法。
import unittest


class TestSkipExample(unittest.TestCase):

    @unittest.skip("无条件跳过这个测试")
    def test_always_skipped(self):
        self.fail("应该不会执行到这里")

    @unittest.skipIf(True, "条件为真时跳过这个测试")
    def test_skipped_if_true(self):
        self.fail("条件为真时不应该执行到这里")

    @unittest.skipIf(False, "条件为假时跳过这个测试")
    def test_not_skipped_if_false(self):
        self.assertTrue(True)  # 这个测试将会被执行


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

2、使用 setUp() 方法中的断言来跳过整个测试类

  • 如果 setUp() 方法中抛出异常(例如通过 assert),那么整个测试类将不会被执行。
import unittest


class TestSetupSkipExample(unittest.TestCase):

    def setUp(self):
        self.skipTest("setUp 中的断言失败,跳过整个测试类")  # 这行代码将导致整个测试类被跳过

    def test_example_one(self):
        self.assertTrue(True)

    def test_example_two(self):
        self.assertTrue(True)


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

3、在测试方法内部使用 unittest.TestCase.skipTest() 方法

  • 如果在一个测试方法内部想要跳过后续的测试步骤,可以使用 self.skipTest(reason)
import unittest


class TestSkipInMethodExample(unittest.TestCase):

    def test_example(self):
        self.skipTest("测试方法内部决定跳过")
        self.assertTrue(False)  # 这行代码不会被执行

    def test_example_2(self):
        self.assertTrue(True)  # 这行代码不会被执行


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

六、预期失败

使用 expectedFailure 装饰器来标记那些预期会失败的测试用例。这在开发过程中非常有用,特别是当正在重构代码或逐步改进现有功能时。这样,可以跟踪哪些测试在当前状态下应该是失败的,直到它们最终通过为止。

import unittest


class TestExpectedFailures(unittest.TestCase):

    def test_known_failure(self):
        """ 这个测试应该失败,因为我们还没有修复这个 bug。 """
        self.assertEqual(1, 2)  # 这个断言应该失败

    @unittest.expectedFailure
    def test_known_failure_with_decorator(self):
        """ 使用装饰器标记已知的失败测试。 """
        self.assertEqual(1, 2)  # 这个断言应该失败

    def test_known_failure_without_decorator(self):
        """ 这个测试应该失败,但我们没有使用装饰器标记。 """
        self.assertEqual(1, 2)  # 这个断言应该失败


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

七、自定义测试结果类

通过继承 unittest.TextTestResult 类来自定义测试结果的处理方式。这样做可以增加更多的定制功能,比如记录额外的信息、更改输出格式等。

import unittest
import sys


class CustomTestResult(unittest.TextTestResult):
    """自定义测试结果类,扩展了unittest.TextTestResult以添加额外的测试结果输出功能."""

    def __init__(self, stream, descriptions, verbosity):
        """初始化自定义测试结果,设置输出流、描述和详细程度."""
        super().__init__(stream, descriptions, verbosity)

    def startTest(self, test):
        """在测试开始时调用,打印开始测试的信息."""
        super().startTest(test)
        print(f"Starting test: {test}")

    def addSuccess(self, test):
        """在测试成功时调用,打印测试通过的信息."""
        super().addSuccess(test)
        print(f"Test {test} passed.")

    def addFailure(self, test, err):
        """在测试失败时调用,打印测试失败的信息及错误."""
        super().addFailure(test, err)
        print(f"Test {test} failed: {err}")

    def addError(self, test, err):
        """在测试出错时调用,打印测试出错的信息及错误."""
        super().addError(test, err)
        print(f"Test {test} err

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

EasyCVR智慧公园视频智能管理方案:赋能公园安全管理新高度

随着城市化进程的加速,智慧城市建设已成为提升城市管理效率、增强居民生活质量的重要途径。智慧公园作为智慧城市的重要组成部分,其安全与管理水平直接影响着市民的休闲娱乐体验。EasyCVR智慧公园视频智能管理方案,正是基于这一背景应运而生&…

Android 车载应用开发指南 - CarService 详解(下)

车载应用正在改变人们的出行体验。从导航到娱乐、从安全到信息服务,车载应用的开发已成为汽车智能化发展的重要组成部分。而对于开发者来说,如何将自己的应用程序无缝集成到车载系统中,利用汽车的硬件和服务能力,是一个极具挑战性…

【Docker】01-Docker常见指令

1. Docker Docker会下载镜像,运行的时候,创建一个隔离的环境,称为容器。 docker run -d \ # 创建并运行一个容器,-d表示后台运行 --name mysql \ # 容器名称-p 3307:3306 \ # 端口映射,宿主机端口映射到容器端口-e TZ…

Cilium + ebpf 系列文章-什么是ebpf?(一)

前言: 这篇非常非常干,很有可能读不懂。 这里非常非常推荐,建议使用Cilium官网的lab来辅助学习!!!Resources Library - IsovalentExplore Isovalents Resource Library, your one-stop destination for ins…

linux命令:显示已安装在linux内核的模块的详细信息的工具modinfo详解

目录 一、概述 二、使用方法 1、基本的使用语法 2、常用选项 3、输出字段 4、获取帮助 三、示例 四、实际用途 1、诊断问题 2、模块依赖 3、参数配置 五、其他事项 一、概述 modinfo 是 Linux 系统中的一个工具,用于显示有关已安装内核模块的详细信息。…

中间件:maxwell、canal

文章目录 1、底层原理:基于mysql的bin log日志实现的:把自己伪装成slave2、bin log 日志有三种模式:2.1、statement模式:2.2、row模式:2.3、mixed模式: 3、maxwell只支持 row 模式:4、maxwell介…

MySQL多版本并发控制MVCC实现原理

MVCC MVCC 是多版本并发控制方法,用来解决读和写之间的冲突,比如脏读、不可重复读问题,MVCC主要针对读操作做限制,保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。 概述 当一个事务要对数据库中的数据进行selec…

十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)

十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式) 文章目录 十七,Spring Boot 整合 MyBatis 的详细步骤(两种方式)1. Spring Boot 配置 MyBatis 的详细步骤2. 最后: MyBatis 的官方文档:https://mybatis.p2hp.com/ 关于 MyBa…

828华为云征文|使用Flexus X实例安装宝塔面板教学

目录 一、Flexus X实例简介 1.1 概述 1.2 产品规格 二、切换操作系统 2.1 Huawei Cloud EulerOS 2.0 标准版 2.2 切换镜像 三、部署宝塔面板 3.1 安装宝塔面板 3.2 放通安全组规则 3.3 登录宝塔面板 四、使用感受 4.1 柔性算力随心配 4.2 一直加速一直快 4.3 越用…

【小程序】微信小程序课程 -2 快速上手

目录 1、快速上手基本概念 1.1 小程序常用组件 1.2 tabbar配置 1.3 尺寸单位 1.4 样式 1.4.1 全局样式 app.wxss 1.4.2 局部样式 xx.wxss 2、首页案例 2.1 button组件使用 2.2 swiper swiper-item 2.3 tips效果 2.4 引入矢量图 2.5 flex(布局&#…

Java中List、ArrayList与顺序表

List、ArrayList与顺序表 List什么是List常用方法介绍List的使用 ArrayList与顺序表线性表顺序表接口的实现 ArrayList简介ArrayList的使用ArrayList的构造ArrayList的常见操作ArrayList的遍历ArrayList的扩容机制 ArrayList的具体使用杨辉三角简单的洗牌算法 ArrayList的问题及…

2024.9.26 作业 +思维导图

一、作业 1、什么是虚函数?什么是纯虚函数 虚函数:函数前加关键字virtual,就定义为虚函数,虚函数能够被子类中相同函数名的函数重写 纯虚函数:把虚函数的函数体去掉然后加0;就能定义出一个纯虚函数。 2、基…

前台项目启动/打包报错 Error: error:0308010C:digital envelope routines::unsupported

在package.json中修改启动/打包语句 如图,我这里是打包时候报错,就在build里前面加上 set NODE_OPTIONS--openssl-legacy-provider && 再次打包,成功。

刷题计划 day10 栈与队列上【用栈实现队列】【用队列实现栈】【有效的括号】【删除字符串中的所有相邻重复项】

⚡刷题计划day10栈与队列继续,可以点个免费的赞哦~ 往期可看专栏,关注不迷路, 您的支持是我的最大动力🌹~ 目录 ⚡刷题计划day10继续,可以点个免费的赞哦~ 往期可看专栏,关注不迷路, 您的…

Vue引入js脚本问题记录(附解决办法)

目录 一、需求 二、import引入问题记录 三、解决方式 一、需求 我想在我的Vue项目中引入jquery.js和bootstrap.js这种脚本文件,但发现不能单纯的import引入,问题如下。 二、import引入问题记录 我直接这么引入,发现控制台报错TypeError: …

使用kaggle命令下载数据集和模型

点击用户头像,点击Settings: 找到API,点击create new token,将自动下载kaggle.json: 在用户目录下创建.kaggle文件夹,并将下载的kaggle.json文件移动到该文件夹: cd ~ mv Downloads/kaggle.j…

postman控制变量和常用方法

1、添加环境: 2、环境添加变量: 3、配置不同的环境:local、dev、sit、uat、pro 4、 接口调用 5、清除cookie方法: 6、下载文件方法:

数据结构升华部分:排序与字符串匹配算法应用

数据结构入门学习(全是干货)——综合应用 习题选讲 - 排序与字符串匹配算法 习题选讲 - Insert or Merge 习题-IOM.1 插入排序的判断 题意理解 如何区分简单插入和非递归的归并排序 插入排序:前面有序,后面没有变化。归并排…

react hooks--useCallback

概述 useCallback缓存的是一个函数,主要用于性能优化!!! 基本用法 如何进行性能的优化呢? useCallback会返回一个函数的 memoized(记忆的) 值;在依赖不变的情况下,多次定义的时候,返回的值是…

【计算机组成原理】实验一:运算器输入锁存器数据写实验

目录 实验要求 实验目的 主要集成电路芯片及其逻辑功能 实验原理 实验内容及步骤 实验内容 思考题 实验要求 利用CP226实验箱上的K16~K23二进制拨动开关作为DBUS数据输入端,其它开关作为控制信号的输入端,将通过K16~K23设定…