Python基础入门7--编写测试用例

Python 基础入门前六篇:

  • Python 基础入门–简介和环境配置
  • Python基础入门_2基础语法和变量类型
  • Python基础入门_3条件语句和迭代循环
  • Python基础入门_4函数
  • Python基础入门_5面向对象基础
  • Python基础入门6_文件和异常

这是第七篇,也是这个基础入门系列的最后一篇内容,简单介绍如何采用 unittest 模型编写测试用例。


测试函数

首先是给出用于测试的代码,如下所示,这是一个接收姓和名然后返回整洁的姓名的函数:

def get_formatted_name(first, last):full_name = first + ' ' + lastreturn full_name.title()

简单的测试代码:

first = 'kobe'
last = 'bryant'
print(get_formatted_name(first, last)) # 输出 Kobe Bryant

在 Python 标准库中的模块 unittest 提供了代码测试工具。这里介绍几个名词的含义:

  • 单元测试:用于核实函数的某个方面没有问题;
  • 测试用例:一组单元测试,它们一起核实函数在各种情形下的行为符合要求。
  • 全覆盖式测试用例:包含一整套单元测试,涵盖了各种可能的函数使用方式。

通常,最初只需要对函数的重要行为编写测试即可,等项目被广泛使用时才考虑全覆盖。

接下来就开始介绍如何采用 unittest 对代码进行测试。

首先是需要导入 unittest 模块,然后创建一个继承 unittest.TestCase 的类,并编写一系列类方法对函数的不同行为进行测试,如下代码所示:

import unittestclass NamesTestCase(unittest.TestCase):'''测试生成名字函数的类'''def test_first_last_name(self):formatted_name = get_formatted_name('kobe', 'bryant')self.assertEqual(formatted_name, 'Kobe Bryant')unittest.main()

输出结果如下,显示运行的测试样例是 1 个,耗时是 0.001s。

.
----------------------------------------------------------------------
Ran 1 test in 0.001sOK

上述是给了一个可以通过的例子,而如果测试不通过,输出是怎样的呢,如下所示:

# 添加中间名
def get_formatted_name(first, middel, last):full_name = first + ' ' + middle + ' ' + lastreturn full_name.title()class NamesTestCase(unittest.TestCase):'''测试生成名字函数的类'''# 不能通过的例子def test_first_name(self):formatted_name = get_formatted_name('kobe', 'bryant')self.assertEqual(formatted_name, 'Kobe Bryant')unittest.main()

输出结果如下,这里会打印错误发生的地方和错误原因:

E
======================================================================
ERROR: test_first_last_middle_name (__main__.NamesTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):File "E:/Python_Notes/Practise/unittest_practise.py", line 39, in test_first_last_middle_nameformatted_name = get_formatted_name('kobe', 'bryant')
TypeError: get_formatted_name() missing 1 required positional argument: 'middle'----------------------------------------------------------------------
Ran 1 test in 0.001sFAILED (errors=1)

很明显是因为缺少 middle 参数,如果希望通过测试,可以将原函数进行如下修改:

def get_formatted_name(first, last, middle=''):'''接收姓和名然后返回完整的姓名:param first::param last::return:'''if middle:full_name = first + ' ' + middle + ' ' + lastelse:full_name = first + ' ' + lastreturn full_name.title()

然后添加新的测试方法,继续运行,就可以测试通过。

def test_first_last_middle_name(self):formatted_name = get_formatted_name('kobe', 'bryant', 'snake')self.assertEqual(formatted_name, 'Kobe Snake Bryant')

测试类

上一小节介绍了给函数写测试的代码,接下来介绍如何编写针对类的测试。

断言方法

unitest.TestCase 类中提供了很多断言方法,上一小节就采用了 assertEqual 这一个判断给定两个参数是否相等的断言方法,下面给出常用的 6 个断言方法:

方法用途
assertEqual(a, b)核实 a == b
assertNotEqual(a, b)核实 a != b
assertTrue(x)核实 x 是 True
assertFalse(x)核实 x 是 False
assertIn(item, list)核实 item 在 list 中
assertNotIn(item, list)核实 item 不在 list 中

这些方法都只能在继承了 unittest.TestCase 的类中使用这些方法。

编写针对类的测试

首先,编写用于进行测试的类,代码如下所示,这是一个用于管理匿名调查问卷答案的类:

class AnonymousSurvey():'''收集匿名调查问卷的答案'''def __init__(self, question):''':param question:'''self.question = questionself.responses = []def show_question(self):'''显示问卷:return: '''print(self.question)def store_response(self, new_response):'''存储单份调查问卷:param new_response: :return: '''self.responses.append(new_response)def show_results(self):'''显示所有答卷:return: '''print('Survey results:')for response in self.responses:print('- ' + response)

这个类包含三个方法,分别是显示问题、存储单份问卷以及展示所有调查问卷,下面是一个使用例子:

def use_anonymous_survey():question = "世上最好的语言是?"language_survey = AnonymousSurvey(question)# 显示问题language_survey.show_question()# 添加问卷language_survey.store_response('php')language_survey.store_response('python')language_survey.store_response('c++')language_survey.store_response('java')language_survey.store_response('go')# 展示所有问卷language_survey.show_results()if __name__ == '__main__':use_anonymous_survey()

输出结果如下:

世上最好的语言是?
Survey results:
- php
- python
- c++
- java
- go

然后就开始编写对该类的测试代码,同样创建一个类,继承 unittest.TestCase ,然后类方法进行测试,代码如下所示:

import unittestclass TestAnonmyousSurvey(unittest.TestCase):def test_store_single_response(self):'''测试保存单份问卷的方法:return:'''question = "世上最好的语言是?"language_survey = AnonymousSurvey(question)language_survey.store_response('php')self.assertIn('php', language_survey.responses)
unittest.main()

上述代码采用了 assertIn 断言方法来测试函数 store_response()

这里还可以继续测试能否存储更多的问卷,如下所示,测试存储三份问卷:

 def test_store_three_response(self):question = "世上最好的语言是?"language_survey = AnonymousSurvey(question)responses = ['c++', 'php', 'python']for response in responses:language_survey.store_response(response)for response in responses:self.assertIn(response, language_survey.responses)

最后,在 unittest.TestCase 中其实包含一个方法 setUp() ,它的作用类似类的初始化方法 __init()__,它会在各种以 test_ 开头的方法运行前先运行,所以可以在这个方法里创建对象,避免在每个测试方法都需要创建一遍,所以上述代码可以修改为:

class TestAnonmyousSurvey(unittest.TestCase):def setUp(self):'''创建一个调查对象和一组答案:return:'''question = "世上最好的语言是?"self.language_survey = AnonymousSurvey(question)self.responses = ['c++', 'php', 'python']def test_store_single_response(self):'''测试保存单份问卷的方法:return:'''self.language_survey.store_response(self.responses[1])self.assertIn('php', self.language_survey.responses)def test_store_three_response(self):for response in self.responses:self.language_survey.store_response(response)for response in self.responses:self.assertIn(response, self.language_survey.responses)

运行后,输出结果如下:

..
----------------------------------------------------------------------
Ran 2 tests in 0.000sOK

注意,这里运行成功,打印一个句号,因为是运行两个测试方法成功,所以打印了两个句号;如果运行出错,打印一个 E ;测试导致断言失败,打印一个 F


参考

  • 《Python编程–从入门到实践》

小结

Python 的基础入门系列就介绍到这里,最初第一篇初步制定的计划是如下所示:

  1. 简介和环境配置
  2. 变量和简单的数据类型
  3. 列表和元组
  4. 字典
  5. if 条件语句
  6. for / while循环语句
  7. 函数
  8. 文件和异常
  9. 测试代码

刚好基本都介绍上述 10 个方面的知识,后续还会有进阶的知识点,包括函数和类的高级知识点,正则表达式,网络编程方面的如进程和线程知识,当然还会总结或者翻译一些不错的介绍 Python 技巧的文章,以及一些常用库的使用方法,比如 numpy、pandas、matplotlib 等等。

当然,还有就是努力做一些有趣的项目。

本文的代码例子也都上传到我的 Github 上:

  • https://github.com/ccc013/Python_Notes/blob/master/Practise/unittest_practise.py
  • https://github.com/ccc013/Python_Notes/blob/master/Practise/unitest_class_example.py

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

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

相关文章

实战|手把手教你训练一个基于Keras的多标签图像分类器

图片来自 pexels,作者:Jean-Christophe Andr2019 年第 63 篇文章,总第 87 篇文章原文链接:https://www.pyimagesearch.com/2018/05/07/multi-label-classification-with-keras/作者:Adrian Rosebrock今天介绍的是基于 …

poj 2182 Lost Cows 解题报告

题意&#xff1a;每个奶牛都有一个编号&#xff0c;1- N 从第二个牛开始给出前面比她编号小的牛的个数&#xff0c;问你求牛的编号序列 解题思路:线段树 二分查找 (多个相同的数二分边界问题需要注意)  解题代码&#xff1a; 1 #include <stdlib.h>2 #include <stri…

基于Keras的多标签图像分类

原文链接&#xff1a;https://www.pyimagesearch.com/2018/05/07/multi-label-classification-with-keras/ 作者&#xff1a;Adrian Rosebrock 今天介绍的是基于 Keras 实现多标签图像分类&#xff0c;主要分为四个部分&#xff1a; 介绍采用的多标签数据集简单介绍使用的网…

html标签默认属性值之margin;padding值

一.h1~h6标签&#xff1a;有默认margin&#xff08;top,bottom且相同&#xff09;值&#xff0c;没有默认padding值。 在chrome中&#xff1a;16,15,14,16,17,19; 在firefox中&#xff1a;16,15,14,16,17,20; 在safari中&#xff1a;16,15,14,16,17,19; 在opera中&#xff1a;1…

快速入门 Jupyter notebook

2019 年第 64 篇文章&#xff0c;总第 88 篇文章本文大约 6400 字&#xff0c;阅读大约需要 17 分钟原文链接&#xff1a;https://www.dataquest.io/blog/jupyter-notebook-tutorial/Jupyter notebook 是一个很强大的交互式和展示数据科学项目的工具&#xff0c;它可以作为一个…

简单ORACLE分区表、分区索引

一段听说CSDN.COM里面很多好东西&#xff0c;同事建议看看合适自己也可以写一写&#xff0c;呵呵&#xff0c;今天第一次开通博客&#xff0c;随便写点东西&#xff0c;就以第一印象分区表简单写第一个吧。 ORACLE对于分区表方式其实就是将表分段存储&#xff0c;一般普通表格是…

【进程】进程通信-信号方式(中断)

信号方式(中断) 信号的基本概念 每个信号都对应一个正整数常量(称为signal number,即信号编号。定义在系统头文件<signal.h>中)&#xff0c;代表同一用户的诸进程之间传送事先约定的信息的类型&#xff0c;用于通知某进程发生了某异常事件。每个进程在运行时&#xff0c…

Jupyter notebook 入门教程

原文链接&#xff1a;https://www.dataquest.io/blog/jupyter-notebook-tutorial/ Jupyter notebook 是一个很强大的交互式和展示数据科学项目的工具&#xff0c;它可以作为一个开发文档&#xff0c;包含代码、解释说明文字、代码运行结果、数学公式等等&#xff0c;功能非常强…

HTML5拖尾效果

HTML5拖尾效果loading……转载于:https://www.cnblogs.com/yorhom/articles/3237266.html

【图像分类】细粒度图像分类是什么,有什么方法,发展的怎么样

欢迎大家来自《图像分类》专栏&#xff0c;今天讲述细粒度图像分类问题&#xff0c;这是计算机视觉领域一项极具挑战的研究课题&#xff0c;本文介绍了细粒度图像分类算法的发展现状、相关数据集和竞赛&#xff0c;供大家参考学习。作者 | 郭冰洋编辑 | 言有三1 简介细粒度图像…

阻止事件冒泡——商品编辑

阻止事件冒泡 冒泡事件流当事件在某一DOM元素被触发时&#xff0c;例如用户在客户名字节点上点击鼠标&#xff0c;事件将跟随着该节点继承自的各个父节点冒泡穿过整个的DOM节点层次&#xff0c;直到它遇到依附有该事件类型处理器的节点&#xff0c;此时&#xff0c;该事件是onc…

Jupyter 进阶教程

2019 年第 65 篇文章&#xff0c;总第 89 篇文章本文大约 7500 字&#xff0c;建议收藏阅读原题 | Tutorial: Advanced Jupyter Notebooks作者 | Benjamin Pryke译者 | kbsc13("算法猿的成长"公众号作者)原文 | https://www.dataquest.io/blog/advanced-jupyter-note…

多个表添加几个相同的字段

最近要整理一个论坛数据结构&#xff08;其实就是Discuz!nt&#xff09;&#xff0c;按公司规定每个表后面要增加三个字段&#xff0c;备注&#xff0c;创建人&#xff0c;创建时间&#xff0c;修改人&#xff0c;修改时间&#xff0c;公司规定啊&#xff0c;虽然我觉得这几个字…