python基础8 单元测试

embedded/2025/3/22 14:30:04/

通过前面的7个章节,作者学习了python的各项基础知识,也学习了python的编译和执行。但在实际环境上,我们需要验证我们的代码功能符合我们的设计预期,所以需要结合python单元测试类,编写单元测试代码。

Python有一个内置的unittest模块,我们可以使用它来进行单元测试

基础用法

基本流程:

  1. 新建类,继承自unittest.TestCase
  2. 类的成员函数统一用test_开头,否则会无法识别和执行
  3. 通过调用unittest.main()来执行测试用例

简单的示例程序如下:

python">import unittest#新建类,继承自unittest.TestCase
#类的成员函数统一用test_开头,否则会无法识别和执行
#通过调用unittest.main()来执行测试用例class TestMath(unittest.TestCase):def test_add(self):self.assertEqual(1 + 1, 2)def test_subtract(self):self.assertEqual(3 - 2, 1)if __name__ == '__main__':unittest.main()

结果输出如下:

python">..
----------------------------------------------------------------------
Ran 2 tests in 0.000sOK

测试函数和类方法

对函数的单元测试

python">import unittest#定义测试用的函数
def add(v1,v2):return v1+v2def subtract(v1,v2):return v1-v2class TestMath(unittest.TestCase):def test_add(self):#测试用例实现对函数的调用self.assertEqual(add(1, 1), 2)def test_subtract(self):#测试用例实现对函数的调用self.assertEqual(subtract(2, 3), -1)if __name__ == '__main__':unittest.main()

结果输出:

python">..
----------------------------------------------------------------------
Ran 2 tests in 0.000sOK

对类的单元测试

在下面示例中,我们对函数和复用的Car类同时进行了单元测试

python">import unittest#定义测试用的函数
def add(v1,v2):return v1+v2def subtract(v1,v2):return v1-v2#复用前期定义的Car类
class Car(object):__slots__ = ('_color', '_number')@propertydef color(self):return self._color@color.setterdef color(self,value):self._color = value@propertydef number(self):return self._number@number.setterdef number(self,value):self._number = value@number.deleterdef number(self):print('oops! number is deleted!')def func(self):print('car number: %d' %  self._number)passclass TestAll(unittest.TestCase):def test_add(self):#测试用例实现对函数的调用self.assertEqual(add(1, 1), 2)def test_subtract(self):#测试用例实现对函数的调用self.assertEqual(subtract(2, 3), -1)def test_car_color(self):car = Car()car.color ="blue"self.assertEqual(car.color, "blue")#属性测试def test_car_property(self):car = Car()with self.assertRaises(AttributeError):value = car.engineif __name__ == '__main__':unittest.main()

结果输出: 

python">....
----------------------------------------------------------------------
Ran 4 tests in 0.000sOK

测试套件和测试运行器

继承自unittest.TestCase的类,用test_开头的成员函数,可以称为一个测试用例。

使用测试套件的方法,可以自由的执行这些测试用例。如执行先后次序,部分执行等。

示例代码如下:

python">import unittest#定义测试用的函数
def add(v1,v2):return v1+v2def subtract(v1,v2):return v1-v2#复用前期定义的Car类
class Car(object):__slots__ = ('_color', '_number')@propertydef color(self):return self._color@color.setterdef color(self,value):self._color = value@propertydef number(self):return self._number@number.setterdef number(self,value):self._number = value@number.deleterdef number(self):print('oops! number is deleted!')def func(self):print('car number: %d' %  self._number)passclass TestAll(unittest.TestCase):def test_add(self):#测试用例实现对函数的调用self.assertEqual(add(1, 1), 2)def test_subtract(self):#测试用例实现对函数的调用self.assertEqual(subtract(2, 3), -1)def test_car_color(self):car = Car()car.color ="blue"self.assertEqual(car.color, "blue")#属性测试def test_car_property(self):car = Car()with self.assertRaises(AttributeError):value = car.engineif __name__ == '__main__':# 创建测试套件suite = unittest.TestSuite()suite.addTest(TestAll('test_add'))#suite.addTest(TestAll('test_subtract'))suite.addTest(TestAll('test_car_property'))# 创建测试运行器runner = unittest.TextTestRunner()runner.run(suite) # 通过执行结果,我们可以看到仅执行了我们添加的两个测试用例

测试准备和清理

很多时候,我们在测试用例执行之前,需要做一些准备操作,如执行数据库相关测试用例之前,需要进行数据库连接;之后需要断开数据库连接。这种场景下,我们需要使用python单元测试类默认的setUp和tearDown方法。修改上面的代码,并测试。

python">import unittest#定义测试用的函数
def add(v1,v2):return v1+v2def subtract(v1,v2):return v1-v2#复用前期定义的Car类
class Car(object):__slots__ = ('_color', '_number')@propertydef color(self):return self._color@color.setterdef color(self,value):self._color = value@propertydef number(self):return self._number@number.setterdef number(self,value):self._number = value@number.deleterdef number(self):print('oops! number is deleted!')def func(self):print('car number: %d' %  self._number)passclass TestAll(unittest.TestCase):def setUp(self):# 准备工作print("准备工作完成")def tearDown(self):# 结束后的工作print("结束清理工作完成")def test_add(self):#测试用例实现对函数的调用self.assertEqual(add(1, 1), 2)def test_subtract(self):#测试用例实现对函数的调用self.assertEqual(subtract(2, 3), -1)def test_car_color(self):car = Car()car.color ="blue"self.assertEqual(car.color, "blue")#属性测试def test_car_property(self):car = Car()with self.assertRaises(AttributeError):value = car.engineif __name__ == '__main__':# 创建测试套件suite = unittest.TestSuite()suite.addTest(TestAll('test_add'))#suite.addTest(TestAll('test_subtract'))suite.addTest(TestAll('test_car_property'))# 创建测试运行器runner = unittest.TextTestRunner()runner.run(suite)

结果输出:

python">准备工作完成
结束清理工作完成
.准备工作完成
结束清理工作完成
.
----------------------------------------------------------------------
Ran 2 tests in 0.001sOK

高级测试用法

条件测试

可以使用@unittest.skip关键字,来表示测试用例只有在满足特定条件下才执行。下面的示例中,我们使用关键字实现了一直跳过和条件跳过的功能。

@unittest.skip(reason

Unconditionally skip the decorated test. reason should describe why the test is being skipped.

无条件跳过,需要输入填过的原因。

   @unittest.skip("Always skip!")

@unittest.skipIf(conditionreason)

Skip the decorated test if condition is true.

条件满足时跳过。

python">@unittest.skipIf(mylib.__version__ < (1, 3),"not supported in this library version")

@unittest.skipUnless(conditionreason)

Skip the decorated test unless condition is true.

除此条件外,跳过。

python">    @unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")

@unittest.expectedFailure

Mark the test as an expected failure or error. If the test fails or errors in the test function itself (rather than in one of the test fixture methods) then it will be considered a success. If the test passes, it will be considered a failure.

失败时,测试用例返回成功。

python">    @unittest.expectedFailuredef test_fail(self):self.assertEqual(1, 0, "failed test")

exception unittest.SkipTest(reason)

This exception is raised to skip a test.

python">import unittest
import sys#定义测试用的函数
def add(v1,v2):return v1+v2def subtract(v1,v2):return v1-v2#复用前期定义的Car类
class Car(object):__slots__ = ('_color', '_number')@propertydef color(self):return self._color@color.setterdef color(self,value):self._color = value@propertydef number(self):return self._number@number.setterdef number(self,value):self._number = value@number.deleterdef number(self):print('oops! number is deleted!')def func(self):print('car number: %d' %  self._number)passclass TestAll(unittest.TestCase):def setUp(self):# 准备工作print("准备工作完成")def tearDown(self):# 结束后的工作print("结束清理工作完成")@unittest.skip("啊!我被永久的跳过了")def test_add(self):#测试用例实现对函数的调用self.assertEqual(add(1, 1), 2)# windows系统下,执行此测试用例。还可以使用版本号版本等等@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")def test_subtract(self):#测试用例实现对函数的调用self.assertEqual(subtract(2, 3), -1)def test_car_color(self):car = Car()car.color ="blue"self.assertEqual(car.color, "blue")#属性测试def test_car_property(self):car = Car()with self.assertRaises(AttributeError):value = car.engineif __name__ == '__main__':# 创建测试套件suite = unittest.TestSuite()suite.addTest(TestAll('test_add'))suite.addTest(TestAll('test_subtract'))suite.addTest(TestAll('test_car_property'))# 创建测试运行器runner = unittest.TextTestRunner()runner.run(suite)

结果输出:

python">准备工作完成
结束清理工作完成
.准备工作完成
结束清理工作完成
.
----------------------------------------------------------------------
Ran 3 tests in 0.001sOK (skipped=1)

模拟对象

Python的unittest.mock模块提供了一种创建模拟对象的方法,我们可以用它来模拟外部的、不可控的因素。

python">import unittest
import sys
import datetime
#使用mock需要执行此引用
from unittest.mock import patch#定义测试用的函数
def add(v1,v2):return v1+v2def subtract(v1,v2):return v1-v2#复用前期定义的Car类
class Car(object):__slots__ = ('_color', '_number')@propertydef color(self):return self._color@color.setterdef color(self,value):self._color = value@propertydef number(self):return self._number@number.setterdef number(self,value):self._number = value@number.deleterdef number(self):print('oops! number is deleted!')def func(self):print('car number: %d' %  self._number)def say(self):current_hour = datetime.datetime.now().hourif current_hour < 12:return "Good morning!"elif current_hour < 18:return "Good afternoon!"else:return "Good evening!"passclass TestAll(unittest.TestCase):def setUp(self):# 准备工作print("准备工作完成")def tearDown(self):# 结束后的工作print("结束清理工作完成")@unittest.skip("啊!我被永久的跳过了")def test_add(self):#测试用例实现对函数的调用self.assertEqual(add(1, 1), 2)# windows系统下,执行此测试用例。还可以使用版本号版本等等@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")def test_subtract(self):#测试用例实现对函数的调用self.assertEqual(subtract(2, 3), -1)def test_car_color(self):car = Car()car.color ="blue"self.assertEqual(car.color, "blue")#属性测试def test_car_property(self):car = Car()with self.assertRaises(AttributeError):value = car.engine@patch('datetime.datetime')# 注意此处多了一个mock_datetime参数def test_car_say(self, mock_datetime):car = Car()mock_datetime.now.return_value.hour = 9self.assertEqual(car.say(), "Good morning!")mock_datetime.now.return_value.hour = 15self.assertEqual(car.say(), "Good afternoon!")mock_datetime.now.return_value.hour = 20self.assertEqual(car.say(), "Good evening!")if __name__ == '__main__':# 创建测试套件suite = unittest.TestSuite()suite.addTest(TestAll('test_add'))suite.addTest(TestAll('test_subtract'))suite.addTest(TestAll('test_car_property'))suite.addTest(TestAll('test_car_say'))# 创建测试运行器runner = unittest.TextTestRunner()runner.run(suite)

结果输出:

python">备工作完成
结束清理工作完成
.准备工作完成
结束清理工作完成
.准备工作完成
结束清理工作完成
.
----------------------------------------------------------------------
Ran 4 tests in 0.002sOK (skipped=1)


http://www.ppmy.cn/embedded/174711.html

相关文章

北京南文观点:AI掘金术激活算法中的“沉默用户”

在流量红利见顶的当下,中小企业正陷入“高成本获客—低效转化—用户流失”的恶性循环。数据显示,2023年国内互联网用户增速降至2.1%,但企业平均获客成本同比上涨37%。当头部平台将90%的流量分配给10%的头部内容时,海量中小企业的优质内容却沉没于算法黑箱中,沦为“沉默用户”。…

Vue+ElementUI 字符串数组标签化展示组件

一. 效果 数据&#xff1a;‘[“苹果”,“香蕉”]’ 可添加&#xff0c;编辑&#xff0c;删除。 二. 组件源码 <template><div><div v-for"(item, index) in items":key"index"><el-inputv-if"inputVisible && ed…

练习-班级活动(map存储键值对)

问题描述 小明的老师准备组织一次班级活动。班上一共有 n 名 (n 为偶数) 同学&#xff0c;老师想把所有的同学进行分组&#xff0c;每两名同学一组。为了公平&#xff0c;老师给每名同学随机分配了一个 n 以内的正整数作为 id&#xff0c;第 i 名同学的 id 为 ai​。 老师希望…

基于微信小程序的充电桩管理系统

一、开发背景 在开发充电汽车管理系统之前&#xff0c;深入的需求分析至关重要。我们要充分了解不同用户群体的需求&#xff0c;比如私家车主希望充电过程便捷、高效、安全&#xff0c;能够实时查看充电状态和费用明细&#xff1b;出租车、网约车司机则更注重充电速度和充电桩…

mac anaconda3遇到无法创建python2.7版本虚拟环境

在Mac M4电脑上安装了Anaconda3之后,想通过conda创建python2.7的时候遇到错误: conda create -n python27 python=2.7(base) yuxuandong@dongyuxuandeMacBook-Air-2 ~ % conda create -n python27 python=2.7 Channels:- defaults- https://repo.anaconda.com/pkgs/main-

1.Go - Hello World

1.安装Go依赖 https://go.dev/dl/ 根据操作系统选择适合的依赖&#xff0c;比如windows&#xff1a; 2.配置环境变量 右键此电脑 - 属性 - 环境变量 PS&#xff1a; GOROOT&#xff1a;Go依赖路径&#xff1b; GOPATH&#xff1a;Go项目路径&#xff1b; …

画出ConcurrentHashMap 1.8的put流程图,记住CAS和synchronized的结合

ConcurrentHashMap 1.8 put 操作流程 结构&#xff1a;数组 链表/红黑树。 并发控制&#xff1a;CAS&#xff08;无锁操作&#xff09; synchronized&#xff08;锁住桶头部节点&#xff09;。 改进&#xff1a;相比1.7的分段锁&#xff08;Segment&#xff09;&#xff0c;…

MyBatis 的一次缓存与二次缓存

在数据访问层的开发中&#xff0c;MyBatis 是一款极为流行的持久层框架&#xff0c;它有效地简化了数据库操作的复杂性。而 MyBatis 的缓存机制更是其一大亮点&#xff0c;能够显著提升数据查询的效率&#xff0c;减少数据库的访问次数&#xff0c;从而优化系统性能。本文将深入…