python教程(4更新中)

单元测试

如果你听说过“测试驱动开发”(TDD:Test-Driven Development),单元测试就不陌生。

单元测试是用来对一个模块、一个函数或者一个类来进行正确性检验的测试工作。

比如对函数abs(),我们可以编写出以下几个测试用例:

  1. 输入正数,比如11.20.99,期待返回值与输入相同;
  2. 输入负数,比如-1-1.2-0.99,期待返回值与输入相反;
  3. 输入0,期待返回0
  4. 输入非数值类型,比如None[]{},期待抛出TypeError

把上面的测试用例放到一个测试模块里,就是一个完整的单元测试。

如果单元测试通过,说明我们测试的这个函数能够正常工作。如果单元测试不通过,要么函数有bug,要么测试条件输入不正确,总之,需要修复使单元测试能够通过。

单元测试通过后有什么意义呢?如果我们对abs()函数代码做了修改,只需要再跑一遍单元测试,如果通过,说明我们的修改不会对abs()函数原有的行为造成影响,如果测试不通过,说明我们的修改与原有行为不一致,要么修改代码,要么修改测试。

这种以测试为驱动的开发模式最大的好处就是确保一个程序模块的行为符合我们设计的测试用例。在将来修改的时候,可以极大程度地保证该模块行为仍然是正确的。

我们来编写一个Dict类,这个类的行为和dict一致,但是可以通过属性来访问,用起来就像下面这样:

>>> d = Dict(a=1, b=2)>>> d['a']1>>> d.a1

mydict.py代码如下:

class Dict(dict):def __init__(self, **kw):super().__init__(**kw)def __getattr__(self, key):try:return self[key]except KeyError:raise AttributeError(r"'Dict' object has no attribute '%s'" % key)def __setattr__(self, key, value):self[key] = value

为了编写单元测试,我们需要引入Python自带的unittest模块,编写mydict_test.py如下:

import unittestfrom mydict import Dictclass TestDict(unittest.TestCase):def test_init(self):d = Dict(a=1, b='test')self.assertEqual(d.a, 1)self.assertEqual(d.b, 'test')self.assertTrue(isinstance(d, dict))def test_key(self):d = Dict()d['key'] = 'value'self.assertEqual(d.key, 'value')def test_attr(self):d = Dict()d.key = 'value'self.assertTrue('key' in d)self.assertEqual(d['key'], 'value')def test_keyerror(self):d = Dict()with self.assertRaises(KeyError):value = d['empty']def test_attrerror(self):d = Dict()with self.assertRaises(AttributeError):value = d.empty

编写单元测试时,我们需要编写一个测试类,从unittest.TestCase继承。

test开头的方法就是测试方法,不以test开头的方法不被认为是测试方法,测试的时候不会被执行。

对每一类测试都需要编写一个test_xxx()方法。由于unittest.TestCase提供了很多内置的条件判断,我们只需要调用这些方法就可以断言输出是否是我们所期望的。最常用的断言就是assertEqual()

self.assertEqual(abs(-1), 1) # 断言函数返回的结果与1相等

另一种重要的断言就是期待抛出指定类型的Error,比如通过d['empty']访问不存在的key时,断言会抛出KeyError

with self.assertRaises(KeyError):value = d['empty']

而通过d.empty访问不存在的key时,我们期待抛出AttributeError

with self.assertRaises(AttributeError):value = d.empty

运行单元测试

一旦编写好单元测试,我们就可以运行单元测试。最简单的运行方式是在mydict_test.py的最后加上两行代码:

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

这样就可以把mydict_test.py当做正常的python脚本运行:

$ python mydict_test.py

另一种方法是在命令行通过参数-m unittest直接运行单元测试:

$ python -m unittest mydict_test.....----------------------------------------------------------------------Ran 5 tests in 0.000sOK

这是推荐的做法,因为这样可以一次批量运行很多单元测试,并且,有很多工具可以自动来运行这些单元测试。

setUp与tearDown

可以在单元测试中编写两个特殊的setUp()tearDown()方法。这两个方法会分别在每调用一个测试方法的前后分别被执行。

setUp()tearDown()方法有什么用呢?设想你的测试需要启动一个数据库,这时,就可以在setUp()方法中连接数据库,在tearDown()方法中关闭数据库,这样,不必在每个测试方法中重复相同的代码:

class TestDict(unittest.TestCase):def setUp(self):print('setUp...')def tearDown(self):print('tearDown...')

可以再次运行测试看看每个测试方法调用前后是否会打印出setUp...tearDown...

练习

对Student类编写单元测试,结果发现测试不通过,请修改Student类,让测试通过:

# -*- coding: utf-8 -*-import unittestclass Student(object):def __init__(self, name, score):self.name = nameself.score = scoredef get_grade(self):if self.score >= 60:return 'B'if self.score >= 80:return 'A'return 'C'class TestStudent(unittest.TestCase):def test_80_to_100(self):s1 = Student('Bart', 80)s2 = Student('Lisa', 100)self.assertEqual(s1.get_grade(), 'A')self.assertEqual(s2.get_grade(), 'A')def test_60_to_80(self):s1 = Student('Bart', 60)s2 = Student('Lisa', 79)self.assertEqual(s1.get_grade(), 'B')self.assertEqual(s2.get_grade(), 'B')def test_0_to_60(self):s1 = Student('Bart', 0)s2 = Student('Lisa', 59)self.assertEqual(s1.get_grade(), 'C')self.assertEqual(s2.get_grade(), 'C')def test_invalid(self):s1 = Student('Bart', -1)s2 = Student('Lisa', 101)with self.assertRaises(ValueError):s1.get_grade()with self.assertRaises(ValueError):s2.get_grade()if __name__ == '__main__':unittest.main()

小结

单元测试可以有效地测试某个程序模块的行为,是未来重构代码的信心保证。

单元测试的测试用例要覆盖常用的输入组合、边界条件和异常。

单元测试代码要非常简单,如果测试代码太复杂,那么测试代码本身就可能有bug。

单元测试通过了并不意味着程序就没有bug了,但是不通过程序肯定有bug。

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

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

相关文章

逆向入门:为CTF国赛而战day03

今天来做几道题目。 环境准备:ida ,Exeinfo,万能脱壳器(后面有写资源) 强推,亲测有效CTF小工具下载整理_ctf工具御剑下载-CSDN博客 [网站BUUCTF] 目录 题目一 题目二三 题目4:新年快乐 题目一 easyre题解_easyr…

电脑硬件 - 硬盘

硬盘是一台电脑的数据中心,存放着我们用户的所有文件和数据 对于一块硬盘,其重要指标:顺序读写能力,随机读写能力 顺序读写影响大文件的拷贝,随机读写影响大量小文件的拷贝(打开软件的快慢) 因…

【算法详解】双指针

双指针 常见的双指针有两种形式,一种是对撞指针,一种是左右指针。 1. 双指针简介 双指针(Two Pointers):指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问&#…

vue2转vue3一些属性使用方法总结 (持续更新中)

1.vue3中不再需要用this.$set 方法 在 Vue 3 中,this. s e t 方法不再存在,因为 V u e 3 使用了 P r o x y 来实现其响应式系统,使得对象的属性访问和修改都能够被自动追踪。因此,在 V u e 3 中,你通常不需要使用特殊的…

chrome google浏览器添加插件扩展失败怎么办,无法从该网站添加应用、扩展程序和用户脚本确定,

无法从该网站添加应用、扩展程序和用户脚本确定 chrome google浏览器添加插件扩展失败怎么办,无法从该网站添加应用、扩展程序和用户脚本确定, 需要打开调试模式 chrome://extensions/

【Vue】Vue3父子组件相互调用示例

目录 1. 父调子示例1.1 父组件1.2 子组件 2. 子调父示例2.1 父组件2.2 子组件 Tips:使用场景情况有很多,通常常见于页面表单赋值,表单属性页面回显。 页面给弹窗dialog表单赋值,通常情况为父传子;而表单提交后回传给页…

第32篇:实时时钟

Q:本期我们使用BCD计数器设计实现分--秒--厘秒实时时钟。 A:实时时钟设计:在2个七段数码管上显示分钟(从0到59),在2个七段数码管显示秒(从0到59),在2个七段数码管上显示…

要不要那么卷啊?前端是不是死了?

最近在找前端工作。发现好多还要求至少会一个后端的语言php或者java。这个我理解毕竟要和后端对接要求懂点也是可以的。但是最近发现还要会设计,有设计感可以自己设计。what?这我都会了。工资总是要多一点吧?结果工作经验3-5年竟然9k-12k。离…

信息工程大学第五届超越杯程序设计竞赛(同步赛)vp

目录 A.遗失的旋律 C.财政大臣 D.实验室有多少人 E.在雾中寻宁静 F.不规则的轮回 G.完美数字 M.Monikas game A.遗失的旋律 思路&#xff1a;模拟即可 代码如下&#xff1a; #include<bits/stdc.h>using namespace std; #define fs first #define sc second #de…

中国平安八度蝉联Brand Finance全球保险品牌价值第一,品牌价值持续增长4.2%

近日&#xff0c;国际知名品牌价值评级机构Brand Finance发布《2024年全球保险品牌价值100强》&#xff0c;中国平安连续第八年蝉联全球第一&#xff0c;品牌价值高达336亿美元&#xff0c;较上年增长4.2%。榜单其余前五位依次为德国安联保险、中国人寿、法国安盛保险、中国太平…

JavaScript的事件对象

event 对象包含“与创建它的事件有关的”属性和方法。触发的事件类型不一样&#xff0c;可用的属性和方法不一样。 1.什么是事件对象 官方解释&#xff1a;event 对象代表事件的状态&#xff0c;比如键盘按键的状态、鼠标的位置、鼠标按钮的状态等。简单理解&#xff1a;事件发…

目标检测——RCNN系列学习(一)

前置知识 包括&#xff1a;非极大值抑制&#xff08;NMS&#xff09;、selective search等 RCNN [1311.2524] Rich feature hierarchies for accurate object detection and semantic segmentation (arxiv.org)https://arxiv.org/abs/1311.2524 1.网络训练 2.推理流程 3.总…

leetcode/2024.4.8/双指针简单题(1)

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0]示例 2: 输入: nums [0] 输出: […

Vant使用自定义图标(阿里图标)

前言 阿里图标官网 备用地址&#xff1a; https://www.iconfont.cn/ 添加图标 1、进入官网添加图标&#xff0c;如箭头所示 2、复制如图选中的文件&#xff0c;粘贴项目中的src/assets/icon_font/目录下 3、在main.js引入图标css //引入自定义图标 import /assets/icon_fon…

基于springboot教师人事档案管理系统,2024年最新基于web的毕业设计题目代码

管理员 教师端 目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 研究现状 2 1.3 研究意义 3 第2章 相关技术 4 2.1 系统开发平台 5 2.2 平台开发相关技术 6 第3章 系统分析 7 3.1 系统目标 8 3.2系统流程和逻辑 9 第4章系统概要设计 10 4…

Vue常见简写 “:“ , “@“ , “#“

一、 : 是什么&#xff1f; 1. : 是什么意思? 示例&#xff1a;:data"tableData" 其中这个 : 其实是v-bind的简写形式,实际开发中非常常见,所以首先先来说一下这个 : 的意义和使用. 首先需要了解一下v-bind,v-bind指令指示Vue将元素的id属性与组件的tabalData属…

Linux虚拟主机中如何进行扫描检查恶意软件

看到论坛中有网友留言想要知道Linux虚拟主机上是否有扫描检测工具可以检测病毒文件或者恶意软件的。因为想要知道是否有此功能&#xff0c;以便他后去购买产品是可以更清晰的去咨询以及了解。正如这边是有使用Hostease提供商的Linux 虚拟主机&#xff0c;而cPanel中如何进行扫描…

012——LED模块驱动开发(基于I.MX6uLL)

目录 一、 硬件原理图 二、 驱动程序 三、 应用程序 四、 Makefile 五、操作 一、 硬件原理图 又是非常经典的点灯环节 &#xff0c;每次学新语言第一步都是hello world&#xff0c;拿到新板子或者学习新的操作系统&#xff0c;第一步就是点灯。 LED 的驱动方式&#xff0…

2024年阿里云优惠券(代金券)在哪里领取?

阿里云作为国内领先的云计算服务提供商&#xff0c;不仅提供了稳定、高效的云服务&#xff0c;还时常推出各种优惠活动&#xff0c;以此来吸引用户上云。其中&#xff0c;阿里云优惠券就是一种常见的优惠方式。那么&#xff0c;在2024年&#xff0c;我们该如何领取阿里云优惠券…

[开源] 基于GRU的时间序列预测模型python代码

基于GRU的时间序列预测模型python代码分享给大家&#xff0c;记得点赞哦 #!/usr/bin/env python # coding: utf-8import time time_start time.time() import numpy as np import matplotlib.pyplot as plt import pandas as pd import math from keras.models import Sequent…