自动化测试系列 之 Python单元测试框架unittest

一、概述

什么是单元测试

单元测试是一种软件测试方法,是测试最小的可测试单元,通常是一个函数或一个方法。

在软件开发过程中,单元测试作为一项重要的测试方法被广泛应用。

为什么需要单元测试

单元测试是软件开发中重要的一环,具有以下作用:

  1. 验证代码的正确性:单元测试可以自动化地验证代码的正确性,避免开发人员手动测试时漏掉某些情况或错误。通过单元测试,可以及时发现和定位代码中的错误,并保障代码质量和缺陷率。
  2. 更好地组织和维护代码:通过单元测试,代码将被分割为小的可测试单元,每一个单元都有对应的测试用例,更好地组织代码,增加代码的可读性和可维护性。
  3. 提高开发效率:单元测试的快速执行和反馈,可以有助于开发人员快速找到问题并迅速地解决它们。这样可以加快迭代速度,提高软件开发效率。
  4. 自信心:通过单元测试,开发人员可以自信地修改和重构现有的代码,因为单元测试可以保证代码质量和正确性,减少犯错的机会。
Python 中的单元测试框架

各种编程语言都有自己的单元测试框架,Python中主流的单元测试框架包括:

  1. unittest: Python自带的单元测试框架,是xUnit风格的测试框架。
  2. pytest: 一个第三方的Python单元测试框架,具有更好的扩展性和灵活性。pytest具有更好的预期错误展示和简化测试用例编写的特点。
  3. nose: 另一个第三方的Python单元测试框架,它具有可插拔的插件架构,可以轻松地扩展其功能。
  4. doctest: Python自带的另一个单元测试框架,可以在Python代码中使用文档字符串编写测试用例
  5. Testify: 一个相对较新的Python单元测试框架,专注于在类与海量测试用例下提供更快速的速度和更好的效率。

本文将着重介绍Python自带的带有测试皇家 unittest

二、 unittest框架介绍

unittest框架的背景和产生

unittest 是一个Java单元测试框架 JUnit 的Python版本。unittest最初由Python的核心开发者Tim Peters在2001年开发,旨在提供一种规范的方式来编写单元测试,以改进传统的debugging因试错所造成的时延。

unittest框架的特点与优势

unittest框架有以下特点与优势:

  • 标准化的测试工具: unittest框架提供了标准化的测试工具和从标准TestCase集成的测试运行器,为新手和高级用户提供了一个可用的接口。
  • 支持自动化测试: 可以通过编写自动化测试用例,加快测试效率,缩短测试时间,减少人工测试工作。
  • 支持测试定制: unittest框架可以轻松集成第三方库,支持创建自定义的测试用例和测试套件。
  • 执行结果明确: unittest框架提供了详细的错误信息,让测试人员能够快速地定位和修复错误。

三、unittest框架基础

安装和配置unittest框架

unittest是Python的内置模块,所以你不需要额外安装。

unittest 简单示例

被测试的代码demo,包含了两个方法, addsub

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def add(a, b):
    return a + b

def sub(a, b):
    return a - b

为这两个函数编写单元测试用例

import unittest
from calculate import add, sub

class TestCalcuate(unittest.TestCase):
    def test_add(self):
        result = add(2, 3)
        self.assertEqual(result, 5) 

    def test_sub(self):
        result = sub(5, 3)
        self.assertEqual(result, 2)

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

在这个测试用例中,我们导入了addsub函数,并创建了一个名为 TestCalcuate 的测试类(所有的测试类都必须是unittest.TestCase 的子类)。在这个类中,我们定义了两个测试方法test_addtest_sub,分别用于测试加法和减法函数的行为。

在每个测试方法中,我们调用相应的函数,并使用self.assertEqual断言方法来验证计算结果是否等于预期值。

最后,我们使用unittest.main()来运行测试用例。

四、unittest框架常用的测试类和方法

Python的unittest框架中,提供了许多用于辅助构建单元测试的类和方法

常用的测试类
  1. unittest.TestCase:这是unittest框架中最重要的测试类,所有的测试用例都应该继承自它。它提供了一些常用的断言方法和测试辅助方法,用于编写和运行测试。
  2. unittest.TestSuite:这个类用于组织和管理一组测试用例。你可以将多个测试用例添加到一个测试套件中,并一次性运行它们。
  3. unittest.TestLoader:这个类用于加载测试用例。它提供了一些方法,可以从模块、类或者目录中自动发现和加载测试用例。
  4. unittest.TextTestRunner:这个类用于运行测试用例并生成测试结果的文本报告。它提供了一些方法,可以控制测试的输出格式和详细程度。
  5. unittest.TestResult:这个类用于存储测试结果。它提供了一些方法,可以获取测试的状态、错误信息和失败信息等。
常用的方法

在unittest框架中,常用的方法包括setUp()tearDown()setUpClass()tearDownClass()。这些方法用于在测试用例的执行过程中进行准备和清理工作。

  1. setUp()方法:在每个测试方法运行之前调用。它用于准备测试环境,例如初始化对象、打开文件等。每个测试方法都会在调用setUp()方法后执行。
  2. tearDown()方法:在每个测试方法运行之后调用。它用于清理测试环境,例如关闭文件、释放资源等。每个测试方法都会在调用tearDown()方法后执行。
  3. setUpClass()方法:在测试类中的所有测试方法运行之前调用。它用于进行一次性的测试环境准备工作,例如连接数据库、启动服务器等。setUpClass()方法需要使用@classmethod装饰器进行标记。
  4. tearDownClass()方法:在测试类中的所有测试方法运行之后调用。它用于进行一次性的测试环境清理工作,例如断开数据库连接、关闭服务器等。tearDownClass()方法需要使用@classmethod装饰器进行标记。

这些方法可以在测试类中重写,并根据需要进行自定义操作。

五、编写测试用例

当使用unittest框架编写测试用例时,通常需要进行以下步骤:

  1. 创建测试用例:
    • 创建一个继承自unittest.TestCase的测试类。
    • 在测试类中定义一个或多个测试方法。每个测试方法应该以test_开头,以便unittest能够自动识别并运行它们。
    • 在每个测试方法中,编写测试逻辑并使用断言方法来验证结果是否符合预期。
  2. 管理测试用例:
    • 使用unittest.TestLoader类来加载测试用例。你可以使用loadTestsFromModule()方法从模块中加载测试用例,或者使用loadTestsFromTestCase()方法从测试类中加载测试用例。
    • 创建一个unittest.TestSuite对象,并将加载的测试用例添加到测试套件中。你可以使用addTest()方法添加单个测试用例,或者使用addTests()方法添加多个测试用例。
  3. 运行测试用例:
    • 使用unittest.TextTestRunner类来运行测试用例并生成测试结果的文本报告。
    • 创建一个unittest.TextTestRunner对象。
    • 调用run()方法运行测试套件,并将结果输出到控制台或文件中。

结合前面的例子,进一步演示如何编写、管理和运行测试用例:

import unittest

class MyTestCase(unittest.TestCase):
    def test_add(self):
        result = 2 + 2
        self.assertEqual(result, 4)

    def test_sub(self):
        result = 5 - 3
        self.assertEqual(result, 2)

if __name__ == '__main__':
    # 创建测试套件并添加测试用例
    suite = unittest.TestSuite()
    suite.addTest(MyTestCase('test_add'))
    suite.addTest(MyTestCase('test_sub'))

    # 创建测试运行器并运行测试套件
    runner = unittest.TextTestRunner()
    runner.run(suite)

在这个示例中,我们创建了一个名为MyTestCase的测试类,并在其中定义了两个测试方法test_addtest_sub。然后,我们创建了一个测试套件,并使用addTest()方法将测试用例添加到测试套件中。最后,我们创建了一个测试运行器,并使用run()方法运行测试套件。

运行这个示例,你将看到测试结果的输出。如果所有测试通过,你将看到一个成功的消息。如果有测试失败,你将看到失败的消息和详细的错误信息。

这是使用unittest编写、管理和运行测试用例的基本步骤。你可以根据需要编写更多的测试方法,并使用各种断言方法来验证你的代码的行为。

六、unittest常用的断言方法

以下是unittest常用的断言方法以markdown表格的方式呈现:

断言方法 描述
assertEqual(a, b) 断言a和b相等
assertNotEqual(a, b) 断言a和b不相等
assertTrue(x) 断言x为True
assertFalse(x) 断言x为False
assertIs(a, b) 断言a和b是同一个对象
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的实例
assertRaises(exception, callable, *args, **kwargs) 断言调用callable(*args, **kwargs)会引发指定的异常
assertWarns(warning, callable, *args, **kwargs) 断言调用callable(*args, **kwargs)会引发指定的警告
assertLogs(logger=None, level=None) 断言在指定的日志记录器上发生了指定级别的日志记录
assertAlmostEqual(a, b, places=None, msg=None, delta=None) 断言a和b近似相等
assertNotAlmostEqual(a, b, places=None, msg=None, delta=None) 断言a和b不近似相等
assertSequenceEqual(a, b, msg=None, seq_type=None) 断言a和b是相同的序列
assertListEqual(a, b, msg=None) 断言a和b是相同的列表
assertTupleEqual(a, b, msg=None) 断言a和b是相同的元组
assertSetEqual(a, b, msg=None) 断言a和b是相同的集合
assertDictEqual(a, b, msg=None) 断言a和b是相同的字典

这些断言方法可以根据需要选择合适的方法来编写测试用例,并验证代码的行为是否符合预期。

相关推荐
尘浮生1 分钟前
Java项目实战II基于Spring Boot的光影视频平台(开发文档+数据库+源码)
java·开发语言·数据库·spring boot·后端·maven·intellij-idea
明月看潮生21 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
南宫理的日知录32 分钟前
99、Python并发编程:多线程的问题、临界资源以及同步机制
开发语言·python·学习·编程学习
coberup41 分钟前
django Forbidden (403)错误解决方法
python·django·403错误
逊嘘1 小时前
【Java语言】抽象类与接口
java·开发语言·jvm
Half-up1 小时前
C语言心型代码解析
c语言·开发语言
龙哥说跨境1 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
Source.Liu1 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng1 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马1 小时前
Rust-Trait 特征编程
开发语言·后端·rust