原标题:Python单元测试--Unittest

什么是单元测试

单元测试是用来对最小可测试单元(如一个函数、一个类或者一个模块)进行检查和验证。尤其是在对代码进行修改或重构后,可以快速准确的定位出现问题的问题。

为什么要做单元测试

写代码的首要目标就是实现需求。在此基础上,就要尽可能提高代码的质量和可维护性。而单元测试,就是提高代码质量和可维护性的一种方式,也是成本最低的一种方式。因为尽早排除尽可能过的bug,可以减少在后续阶段解决bug的成本(包括时间成本、人力成本等)。

单元测试的基本原则

单元测试代码要非常简单,如果测试代码过于复杂,则测试代码本身也可能存在bug

通过单元测试,并不意味着所测代码没有bug

Python单元测试框架

Unittest:Python标准库自带的单元测试工具,也称为PyUnit,是JUnit(Java语言的单元测试)的Python版本。

Doctest:Python标准库自带的单元测试工具,适合简单的单元测试。其工作原理是在docstring中寻找测试用例并执行,比较输出结果与期望值是否符合。

Pytest:Python的一种单元测试框架,与Unittest测试框架类似。其特点是拥有众多高级功能和插件。

Nose:继承自Unittest,但比Unittest易用,而且能够自动识别测试用例。任何符合正则表达式“(?:^|[b_.-])[Tt]est”的类、函数、文件或目录,以及TestCase的子类都会被识别并执行。

Unittest2:Unittest的升级版。

Unittest

Unittest是Python的标准测试库,无需额外安装,是目前Python使用较为官方的测试框架。下面通过实例,一步一步了解如何使用Unittest。

待测试代码如下,用于验证email和密码。

# -*- coding: utf-8 -*-

import re

class CheckUserInfo: def check_mail(self, mail): flag = False str = '^[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+){0,4}@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+){0,4}$' if re.match(str, mail): flag = True return flag def check_pwd_len(self, pwd): '''密码长度不超过8位''' return len(pwd)>=8 def check_pwd_contain_leter(self, pwd): '''密码包含大小写英文字母''' flag = False pattern = re.compile('[A-Z][a-z]+') match = pattern.findall(pwd) if match: flag = True return flag def check_pwd_contain_num(self, pwd): '''密码包含数字''' flag = False pattern = re.compile('[0-9]+') match = pattern.findall(pwd) if match: flag = True return flag

TestCase — 单元测试用例

对上面代码中的每个方法进行测试,就需要实现一个继承unittest.TestCase 测试用例类。

# -*- coding: utf-8 -*-

import unittest

from com.unit_test.check_user_info import CheckUserInfoclass CheckUserInfoTestCase(unittest.TestCase): def __init__(self, *args, **kwargs): super(CheckUserInfoTestCase, self).__init__(*args, **kwargs) self.check_user_info = CheckUserInfo() @classmethod def setUpClass(cls): print('setUpClass ') @classmethod def tearDownClass(cls): print('tearDownClass') def setUp(self): print('setUp') def tearDown(self): print('tearDown ') def test_check_mail(self): print('test_check_mail') self.assertEqual(True, self.check_user_info.check_mail('aa@bb')) self.assertEqual(False, self.check_user_info.check_mail('aa.bb')) def test_check_pwd_len(self): print('test_check_pwd_len') self.assertEqual(True, self.check_user_info.check_pwd_len('12345678')) self.assertEqual(False, self.check_user_info.check_pwd_len('')) self.assertEqual(False, self.check_user_info.check_pwd_len('1')) self.assertEqual(True, self.check_user_info.check_pwd_len('123456789')) def test_check_pwd_contain_letter(self): print('test_check_pwd_contain_leter') self.assertEqual(True, self.check_user_info.check_pwd_contain_leter('1qazXSW@')) self.assertEqual(False, self.check_user_info.check_pwd_contain_leter('12345678')) self.assertEqual(False, self.check_user_info.check_pwd_contain_leter('')) def test_check_pwd_contain_num(self): print('test_check_pwd_contain_num') self.assertEqual(True, self.check_user_info.check_pwd_contain_num('1qazXSW@')) self.assertEqual(False, self.check_user_info.check_pwd_contain_num('qwertasdfg')) self.assertEqual(False, self.check_user_info.check_pwd_contain_num('')) def aaa(self): print('test_check_pwd_contain_num') self.assertEqual(True, self.check_user_info.check_pwd_contain_num('1qazXSW@'))if __name__ == '__main__': unittest.main()

执行结果如下:

...setUpClasssetUptest_check_mailtearDownsetUptest_check_pwd_contain_letertearDownsetUptest_check_pwd_contain_numtearDownsetUptest_check_pwd_lentearDowntearDownClassRan 4 tests in 0.013sOKProcess finished with exit code 0

使用“unittest.main()”,通过观察上面的测试代码以及执行结果,可以发现:

testXXX方法

使用“unittest.main()”执行测试用例时,每个测试方法必须以“test”开头,否则Unittes无法识别。例如,上面代码中的“aaa”方法未执行。

测试方法执行顺序

每个测试方法执行顺序并不是按照代码的书写顺序执行,而是按照前缀“test”后的字母顺序执行的。

setUp()方法

setUp()方法一般用来准备测试环境,在每个测试方法执行之前执行。

tearDown()方法

tearDown()方法一般用来清理测试环境,在每个测试方法执行之后执行,且不论测试方法执行是否成功。

setUpClass()方法

setUpClass()方法一般用来在所有测试方法执行之前准备一次测试环境,必须使用“@classmethod”装饰符,在所有测试方法执行前执行。

tearDownClass()

tearDownClass()方法一般用来在所有测试方法结束之后清理一次测试环境,必须使用“@classmethod”装饰符,在所有测试方法都执行完成否执行。

skip装饰器

不希望执行某个测试方法时,可以使用skip装饰器。skip装饰器共有三种:unittest.skip(reason)、unittest.skipIf(condition, reason)、unittest.skipUnless(condition, reason)。

unittest.skip(reason):无条件跳过

# -*- coding: utf-8 -*-

import unittestfrom com.unit_test.check_user_info import CheckUserInfoclass CheckUserInfoTestCase(unittest.TestCase): ...... @unittest.skip('skip test_bbb method') def test_bbb(self): print('test_bbb')......

部分执行结果如下:

...Skipped: skip test_bbb method...

unittest.skipIf(condition, reason):当condition为True时跳过

# -*- coding: utf-8 -*-

import unittestfrom com.unit_test.check_user_info import CheckUserInfoclass CheckUserInfoTestCase(unittest.TestCase): ...... @unittest.skipIf(1<2, 'skip test_ccc method') def test_ccc(self): print('test_ccc')......

部分执行结果如下:

...Skipped: skip test_ccc method...

unittest.skipUnless(condition, reason):当condition为False时跳过

# -*- coding: utf-8 -*-

import unittestfrom com.unit_test.check_user_info import CheckUserInfoclass CheckUserInfoTestCase(unittest.TestCase): ...... @unittest.skipUnless(1>2, 'skip test_ddd method') def test_ddd(self): print('test_ddd')......

部分执行结果如下:

...Skipped: skip test_ddd method...

那么,如何控制测试方法的执行顺序呢?如何执行非“test”开头的测试方法?接下来了解一下TestSuite。

TestSuite — 单元测试用例合集

通过上面的测试用例代码,可以发现无法指定测试方法的顺序。那么通过unittest.TestSuite,就可以按照业务逻辑顺序执行测试方法。

# -*- coding: utf-8 -*-

import unittestfrom com.unit_test.check_user_info_test_case import CheckUserInfoTestCaseif __name__ == '__main__': suite = unittest.TestSuite() tests = [ CheckUserInfoTestCase('test_check_mail'), CheckUserInfoTestCase('test_check_pwd_len'), CheckUserInfoTestCase('test_check_pwd_contain_letter'), CheckUserInfoTestCase('test_check_pwd_contain_num') ] suite.addTests(tests) runner = unittest.TextTestRunner() runner.run(suite)

执行结果如下:

...Ran 4 tests in 0.002sOKsetUpClasssetUptest_check_mailtearDownsetUptest_check_pwd_lentearDownsetUptest_check_pwd_contain_letertearDownsetUptest_check_pwd_contain_numtearDowntearDownClassProcess finished with exit code 0

通过数组指定测试方法的执行顺序

tests = [ CheckUserInfoTestCase('test_check_mail'), CheckUserInfoTestCase('test_check_pwd_len'), CheckUserInfoTestCase('test_check_pwd_contain_letter'), CheckUserInfoTestCase('test_check_pwd_contain_num')]suite.addTests(tests)

通过addTests()方法指定测试方法的执行顺序

suite.addTest(CheckUserInfoTestCase('test_check_mail')) suite.addTest(CheckUserInfoTestCase('test_check_pwd_len')) suite.addTest(CheckUserInfoTestCase('test_check_pwd_contain_letter')) suite.addTest(CheckUserInfoTestCase('test_check_pwd_contain_num'))

无法指定测试方法执行顺序的unittest.TestLoader()

通过unittest.TestLoader()加载TestCase,测试方法是按照前缀“test”后的字母顺序执行的。

suite.addTests(unittest.TestLoader().loadTestsFromTestCase(CheckUserInfoTestCase))

执行非“test”开头的测试方法

在TestCase中的示例代码中,可以看到,测试方法名不是以“test”开头时是不会被执行的。那么,通过 TestSuite就可以完美解决这个问题。

suite.addTest(CheckUserInfoTestCase('aaa'))

作者:平安金融壹账通测试架构师 武杜鹃返回搜狐,查看更多

责任编辑:

python单元测试示范卷_Python单元测试--Unittest相关推荐

  1. python简单单元测试示范卷_Python 单元测试的简单示例

    这篇文章主要为大家详细介绍了Python 单元测试的简单示例,具有一定的参考价值,可以用来参考一下. 对python这个高级语言感兴趣的小伙伴,下面一起跟随512笔记的小编两巴掌来看看吧! 以前我是不 ...

  2. python简单单元测试示范卷_Python单元测试简单示例

    本文实例讲述了Python单元测试方法.分享给大家供大家参考,具体如下: Eric书中<Python编程从入门到实践>中的一个例子. <Python编程从入门到实践>随书源码可 ...

  3. python简单单元测试示范卷,Python单元测试实例详解

    本文实例讲述了python单元测试.分享给大家供大家参考,具体如下: 在python中进行单元测试需要用到自动单元测试框架pyunit,python2.1及其以后的版本都将pyunit作为一个标准模块 ...

  4. python测试用例怎么写_Python单元测试unittest的具体使用示例

    Python中有一个自带的单元测试框架是unittest模块,用它来做单元测试,它里面封装好了一些校验返回的结果方法和一些用例执行前的初始化操作. unittest是python的标准测试库,相比于其 ...

  5. python写软件测试用例_Python单元测试框架unittest:单个测试用例编写步骤及实例...

    一.Python单元测试框架的编写步骤 导入模块 必须继承unittest.TestCase 主要是配置环境:进行测试前的初始化工作,比如在接口测试前面做一些前置的参数赋值,数据库操作等等 定义测试用 ...

  6. python代码设计测试用例_Python单元测试与测试用例简析

    Python单元测试与测试用例简析 发布时间:2019-11-20 22:03 来源:互联网 当前栏目:web技术类 本文实例讲述了Python单元测试与测试用例.分享给大家供大家参考,具体如下: 单 ...

  7. python单元测试框架作用_Python单元测试框架:Pytest简介

    Pytest简介 入门简单,文档丰富 支持单元测试.功能测试 支持参数化 重复执行,部分执行,测试跳过 兼容其他测试框架(nose,unittest等) 支持生成html报告 可集成CI环境(Jenk ...

  8. python单元测试框架对比_Python单元测试框架pytest常用测试报告类型

    先前博客有介绍pytest测试框架的安装及使用,现在来聊聊pytest可以生成哪些测试报告 1.allure测试报告 2.生成resultlog文件 #!/usr/bin/python # -*- c ...

  9. python selenium po模式_Python+Selenium+Unittest实现PO模式web自动化框架

    1)效率高 :PO模式的逻辑层方法有具体定义,元素发生变化修改逻辑层,业务层不变.这样看来结构简单清晰,舒服更符合人类习惯, 普通方式就是继续堆case. 2) 复用多收益大: 同样这里如果逻辑复用越 ...

最新文章

  1. 监控haproxy的脚本
  2. 深度学习(DL)与卷积神经网络(CNN)学习随笔-05-基于Python的LeNet之CNN
  3. 微头条败走,多闪殿后,字节跳动的社交梦依旧难圆
  4. 【译】 Web Components 的高级工具
  5. Java集合(八) 迭代器Iterator、泛型、Map映射
  6. css --- [读书笔记] 盒模型(边框、内外边距)
  7. php页面防刷,PHP防止刷新重复提交页面的示例代码
  8. Linux 安装Redis单机版(使用Mac远程访问)
  9. power bi 雷达图_空天院研制的调频连续波激光雷达实现公里级成像
  10. 计算机原理课 如何在中小学课堂中变成有趣,在课堂中如何发挥电教辅助教学优势...
  11. 使用Gitee和Sourcetree进行Keil版本控制
  12. “华为杯”第十八届中国研究生数学建模竞赛一等奖经验分享
  13. 经典数据结构视频教程下载 (清华大学 严蔚敏)
  14. 数据流被提前关闭- connectionClosedException:premature end of chunk coded message body:closing chunk expected
  15. 英文论文评审意见_sci英文论文审稿意见怎么写(7)
  16. 常见时序算法集合【资源整理】
  17. 给IT新人的15点建议
  18. uniapp - APP判断是否开启位置信息服务判断是否授权位置信息权限
  19. 《乌合之众》中30句精华
  20. python-字符串 修改间隔符 and定义变量 交换变量

热门文章

  1. 自学篇之----html的所有input标签 以及post和get提交之间的区别
  2. 卸载各类顽固程序时的六个秘密小技巧
  3. mysql开窗函数_魔幻的SQL开窗函数,为您打开进阶高手的一扇天窗
  4. C站学习导航,想用CSDN学习看我这篇就行了!
  5. 在计算机中添加用户名和密码是多少,在win7系统中添加网络打印机提示输入用户名和密码的解决方案...
  6. 沈阳初级计算机职称,沈阳职称申报(附网址)
  7. html中el表达式遍历list,使用EL表达式访问集合
  8. php的数组操作,PHP的数组操作
  9. swarm部署mysql_「实战篇」开源项目docker化运维部署-借助dockerSwarm搭建集群部署(九)...
  10. 基于机器视觉的曼秀雷敦洗发水瓶印刷缺陷检测