工作原理:
unittest中最核心的四个概念是:test case, test suite, test runner, test fixture。

一个TestCase的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),
执行测试代码(run),以及测试后环境的还原(tearDown)。元测试(unit test)的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。 而多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套TestSuite。 TestLoader是用来加载TestCase到TestSuite中的,其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例。 TextTestRunner是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase中的run(result)方法。
测试的结果会保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息。 而对一个测试用例环境的搭建和销毁,是一个fixture。

三个模块:
1、程序或基础类:

def add(a, b):
return a+b def minus(a, b):
return a-b def multi(a, b):
return a*b def divide(a, b):
return a/b

2、测试用例

class TestMathFunc(unittest.TestCase):# 一个class继承了unittest.TestCase,便是一个测试用例,但如果其中有多个以 test 开头的方法,那么每有一个这样的方法,在load的时候便会生成一个TestCase实例

    def test_add(self):  # 每个测试方法都需要以test开头,否则是不会被unittest识别到
"""Test method add(a, b)"""
self.assertEqual(3, add(1, 2)) # 判断相等
self.assertNotEqual(3, add(2, 2)) # 判断不相等
   def test_minus(self):
"""Test method minus(a, b)"""
self.assertEqual(1, minus(3, 2))    def test_multi(self):
"""Test method multi(a, b)"""
self.assertEqual(6, multi(2, 3)) def test_divide(self):
"""Test method divide(a, b)"""
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2)) if __name__ == '__main__':
unittest.main() #main传参控制报告详细程度 verbosity = ,默认是1,不输出每一条测试用例的结果是0,输出详细的测试用例执行结果是2

3、执行测试

import unittest
from test_mathfunc import TestMathFunc #传入测试用例, if __name__=='__main__':
suite = unittest.TestSuite() #按指定顺序执行
tests = [TestMathFunc("test_add"),TestMathFunc("test_minus"),TestMathFunc('test_divide')]
suite.addTests(tests) # 直接用addTest方法添加单个TestCase
# suite.addTest(TestMathFunc("test_multi")) # 用addTests + TestLoader
# loadTestsFromName(),传入'模块名.TestCase名'
# suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
# suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc'])) # loadTestsFromNames(),类似,传入列表 # loadTestsFromTestCase(),传入类TestCase
# suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc)) runner = unittest.TextTestRunner(verbosity=2) #测试结果展示内容
runner.run(suite) #执行测试

测试用例的保存:

修改执行测试文件:

import unittest
from test_mathfunc import TestMathFunc if __name__=='__main__':
suite = unittest.TestSuite() # tests = [TestMathFunc("test_add"),TestMathFunc("test_minus"),TestMathFunc('test_divide')]
# suite.addTests(tests) # 直接用addTest方法添加单个TestCase
# suite.addTest(TestMathFunc("test_multi")) # 用addTests + TestLoader
# loadTestsFromName(),传入'模块名.TestCase名'
# suite.addTests(unittest.TestLoader().loadTestsFromName('test_mathfunc.TestMathFunc'))
# suite.addTests(unittest.TestLoader().loadTestsFromNames(['test_mathfunc.TestMathFunc'])) # loadTestsFromNames(),类似,传入列表 # loadTestsFromTestCase(),传入leiTestCase
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc)) with open('test_Report.txt','a') as f: #打开要保存结果的文件
runner = unittest.TextTestRunner(stream=f,verbosity=2)#stream 写入内容
runner.run(suite)

准备环境、清理环境:

test fixture之setUp() 和tearDown()

这两个方法在每个测试方法执行前以及执行后执行一次

修改测试用例文件

import unittest
from mathfunc import * class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py""" def setUp(self): #setUp用来为测试准备环境
print "do something before test.Prepare environment." def tearDown(self): #tearDown 用来清理测试环境
print "do something after test.Clean up." def test_add(self):
"""Test method add(a, b)"""
print "add"
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2)) def test_minus(self):
"""Test method minus(a, b)"""
print "minus"
self.assertEqual(1, minus(3, 2)) def test_multi(self):
"""Test method multi(a, b)"""
print "multi"
self.assertEqual(6, multi(2, 3)) def test_divide(self):
"""Test method divide(a, b)"""
print "divide"
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))

如果想要在所有case执行之前准备一次环境,并在所有case执行结束之后再清理环境,我们可以用 setUpClass() 与 tearDownClass():

class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py""" @classmethod
def setUpClass(cls): #执行测试前运行
print ("This setUpClass() method only called once.")
@classmethod
def tearDownClass(cls): #所有测试用例执行完毕后运行
print ("This tearDownClass() method only called once too.") def test_add(self):
"""Test method add(a, b)"""
print ("add")
self.assertEqual(3, add(1, 2))
self.assertNotEqual(3, add(2, 2))

跳过当前用例:

1.skip装饰器:

class TestMathFunc(unittest.TestCase):
"""Test mathfuc.py""" ... @unittest.skip("I don't want to run this case.")
def test_divide(self):
"""Test method divide(a, b)"""
print "divide"
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))

unittet可以分无条件忽略和有条件忽略,通过装饰器实现
@unittest.skip(reason): skip(reason)装饰器:无条件跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipIf(reason): skipIf(condition,reason)装饰器:条件为真时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.skipUnless(reason): skipUnless(condition,reason)装饰器:条件为假时,跳过装饰的测试,并说明跳过测试的原因。
@unittest.expectedFailure(): expectedFailure()测试标记为失败。

@self.skipTest :函数体内使用,

class MyTestCase(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def test_nothing(self):
self.fail("shouldn't happen")
@unittest.skipIf(mylib.__version__ < (1, 3),
"not supported in this library version")
def test_format(self):
# Tests that work for only a certain version of the library.
pass
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_windows_support(self):
# windows specific testing code
pass
@unittest.expectedFailure()
def test_windows_support(self):
# windows specific testing code
pass
def test_divide(self):
"""Test method divide(a, b)"""
self.skipTest('Do not run this.')
print "divide"
self.assertEqual(2, divide(6, 3))
self.assertEqual(2.5, divide(5, 2))

忽略测试类:

@unittest.skip("showing class skipping")
class MySkippedTestCase(unittest.TestCase):
def test_not_run(self):
pass

用例结果断言:

assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
assertAlmostEqual(a, b) round(a-b, 7) == 0
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b
assertGreaterEqual(a, b) a >= b
assertLess(a, b) a < b
assertLessEqual(a, b) a <= b
assertRegexpMatches(s, r) r.search(s)
assertNotRegexpMatches(s, r) not r.search(s)
assertItemsEqual(a, b) sorted(a) == sorted(b) and works with unhashable objs
 
   
'''
unittest条件断言
tester: cc
此文仅做翻译只用,不介绍具体使用 '''
Skiptest() # 在测试中引发此异常以跳过该异常。
_ShouldStop() # 停止测试
_UnexpectedSuccess() # 测试本来应该是失败的,但是没有失败
Skip() # 无条件跳过测试。
skipIf(condition, reason) # 条件为真时跳过测试
skipUnless(condition, reason) # 条件为假时跳过测试
expectedFailure(test_item) # 标记该测试预期就是失败,如果运行失败时,不算作失败用例。
_is_subtype(expected, basetype) # 判断类型是否符合预期,暂时不知道干什么用的
addTypeEqualityFunc(typeobj, function) # 为自定义检查类提供检查方法
addCleanup( function , *args , **kwargs ) #添加针对每个测试用例执行完tearDown()方法之后的清理方法,添加进去的函数按照后进先出(LIFO)的顺序执行,当然,如果setUp()方法执行失败,那么不会执行tearDown()方法,自然也不会执行addCleanup()里添加的函数。
setUp()#在执行每个测试用例之前被执行,任何异常(除了unittest.SkipTest和AssertionError异常以外)都会当做是error而不是failure,且会终止当前测试用例的执行。
tearDown()#执行了setUp()方法后,不论测试用例执行是否成功,都执行tearDown()方法。如果tearDown()的代码有异常(除了unittest.SkipTest和AssertionError异常以外),会多算一个error。
setUpClass( cls )与tearDownClass( cls )#测试用例们被执行前、后执行的方法,定义时必须加上classmethod装饰符
countTestCases()#返回测试用例的个数,对于TestCase实例来说,这个返回值一直是1.
defaultTestResult()#如果在run()方法中未提供result参数,该函数返回一个包含本用例测试结果的TestResult对象。
shortDescription()#返回测试用例的描述,即函数的docstring,如果没有,返回None。可以用于测试结果输出中描述测试内容。
id()#返回测试用例的编号,通常是如下格式:模块名.类名.函数名。可以用于测试结果的输出。
subTest( msg=_subtest_msg_sentinel, **params)#返回一个上下文管理器,它将返回由可选消息和关键字参数标识的子测试中的封闭代码块。子测试中的失败标志着测试用例失败,但在封闭块结束时恢复执行,允许执行进一步的测试代码。
run( result =None)#运行一个测试用例,将测试结果收集到result变量中,测试结果不返回给调用者。如果result参数的值为None,则测试结果在下面提到的defaultTestResult()方法的返回值中
doCleanups()#无条件强制调用addCleanup()添加的函数,适用于setUp()方法执行失败但是需要执行清理函数的场景,或者希望在tearDown()方法之前执行这些清理函数。
debug()#与run方法将测试结果存储到result变量中不同,debug方法运行测试用例将异常信息上报给调用者。
fail( msg =None)#无条件声明一个测试用例失败,msg是失败信息。
assertFalse( expr, msg=None) #检查表达式是否为假
assertTrue( expr, msg=None) #检查表达式是否为真
assertAlmostEqual与assertNotAlmostEqual(, first, second, places=None, msg=None,delta=None) #判断两个值是否约等于或者不约等于,places表示小数点后精确的位数
assertSequenceEqual(seq1, seq2, msg=None, seq_type=None) #有序序列的相等断言,如元组、列表
assertListEqual( list1, list2, msg=None) #列表相等的特定断言
assertTupleEqual(tuple1, tuple2, msg=None) #元组相等的特定断言
assertSetEqual( set1, set2, msg=None) #集合相等的特定断言
assertIn与assertNotIn( member, container, msg=None) #判断a 是否存在b中
assertIs与assertIsNot( expr1, expr2, msg=None) #判断a是不是b
assertDictEqual( d1, d2, msg=None) #检查两个字典是否相等
assertDictContainsSubset( subset, dictionary, msg=None) #检查字典是否是子集的超集。
assertCountEqual(first, second, msg=None) #判断两个无序列表内所出现的内容是否相等
assertMultiLineEqual( first, second, msg=None) #断言两个多行字符串相等
assertLess( a, b, msg=None) #断言a<b
assertLessEqual( a, b, msg=None) #断言a<=b
assertGreater( a, b, msg=None) #断言a>b
assertGreaterEqual(a, b, msg=None) #断言a>=b
assertIsNone与assertIsNotNone( obj, msg=None) #判断obj是否为空
assertIsInstance(a, b)与assertNotIsInstance(a, b)# 与assertTrue相同,其中的类型b,既可以是一个类型,也可以是类型组成的元组。
assertRaisesRegex( expected_exception, expected_regex,*args, **kwargs)#断言在引发异常中的消息与正则表达式匹配。
assertWarnsRegex( expected_warning, expected_regex,*args, **kwargs)#断言触发警告中的消息与ReGEXP匹配。基本功能类似于AdvestWr.NS.()只有消息与正则表达式匹配的警告。被认为是成功的匹配
assertRegex与assertNotRegex(text, expected_regex, msg=None) #判断文本与正则表达式是否匹配
shortDescription()#返回测试用例的描述,即函数的docstring,如果没有,返回None。可以用于测试结果输出中描述测试内容。

输出测试HTML报告 :HTMLTestRunner

修改执行测试文件:
# -*- coding: utf-8 -*- import unittest
from test_mathfunc import TestMathFunc
from HTMLTestRunner import HTMLTestRunner #引入HTMLtestrunner if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTests(unittest.TestLoader().loadTestsFromTestCase(TestMathFunc)) # 执行testmathfunc with open('HTMLReport.html', 'w') as f:
runner = HTMLTestRunner(stream=f, #写入HTML文件
title='MathFunc Test Report', #运行状况
description='generated by HTMLTestRunner.', #执行结果
verbosity=2
)
runner.run(suite)

另一种输出方式:

# -*- coding: utf-8 -*-
import unittest,time
from HTMLTestRunner import HTMLTestRunner
from email.mime.text import MIMEText
from email.header import Header
import smtplib
test_dir='./test_jb/' #目录路径
discover=unittest.defaultTestLoader.discover(test_dir,pattern='test_*.py') #查找当前目录下的所有以test_开头的文件,并执行 if __name__=='__main__':
now=time.strftime('%Y-%m-%d %H_%M_%S')#当前日期
filename=test_dir+now+'result.html' #名称后缀
fp=open(filename,'wb') #写入内容
runner=HTMLTestRunner(stream=fp,title='测试报告',description='用例执行情况') #执行测试方式
runner.run(discover)# 执行测试
fp.close() #关闭测试

原文地址:https://blog.csdn.net/huilan_same/article/details/52944782

 
 
 
 
 
 

单元测试模块unittest使用学习的更多相关文章

  1. Python中的单元测试模块Unittest快速入门

    前言 为什么需要单元测试? 如果没有单元测试,我们会遇到这种情况:已有的健康运行的代码在经过改动之后,我们无法得知改动之后是否引入了Bug.如果有单元测试的话,只要单元测试全部通过,我们就可以保证没有 ...

  2. 三言两语聊Python模块–单元测试模块unittest

    实际上unittest模块才是真正意义上的用于测试的模块,功能强大的单元测试模块. 继续使用前面的例子: # splitter.py def split(line, types=None, delim ...

  3. Python3+Selenium2完整的自动化测试实现之旅(六):Python单元测试模块Unittest运用

    一.Unittest单元测试框架简介 Unitest是Python下的一个单元测试模块,是Python标准库模块之一,安装完Python后就可以直接import该模块,能在单元测试下编写具体的测试用例 ...

  4. python单元测试模块unittest

    1.unittest_demo.py # coding=utf-8 import time import unittest from HtmlTestRunner import HTMLTestRun ...

  5. python中的单元测试模块unittest

    unittest的属性: 该文以思维导图的形式描述unittest的重要属性. 其中前四个是unittest最核心的三个属性. testcase:测试用例: testsuite:测试套件,多个测试用例 ...

  6. Python单元测试框架unittest之深入学习

    前言 前几篇文章该要地介绍了python单元测试框架unittest的使用,本篇文章系统介绍unittest框架. 一.unittest核心工作原理 unittest中最核心的四个概念是:test c ...

  7. Python单元测试框架unittest

    学习接口自动化测试时接触了unittest单元测试框架,学习时参照了虫师编写的<selenium2自动化测试实战>,个人觉得里面讲的例子还比较容易理解的. 一.基础 1.main()和框架 ...

  8. selenium + python自动化测试unittest框架学习(二)

    1.unittest单元测试框架文件结构 unittest是python单元测试框架之一,unittest测试框架的主要文件结构: File >report >all_case.py &g ...

  9. Python单元测试:unittest使用简介

    一.概述 本文介绍python的单元测试框架unittest,这是Python自带的标准模块unittest.unittest是基于java中的流行单元测试框架junit设计的,其功能强大且灵活,对于 ...

随机推荐

  1. 使用nuget 打包并上传 nuget.org

    一. 准备工作 1 下载  Download NuGet.exe 2  windows 系统下设置环境变量 path中 或者 在dos 命令窗口下转到 nuget.exe 所在目录 3 在www.nu ...

  2. latex 字母上面加符号

    加^号 输入\hat  或 \widehat 加横线 输入 \overline 加波浪线 输入 \widetilde 加一个点 \dot{要加点的字母} 加两个点\ddot{要加点的字母} 加箭头 输 ...

  3. Oracle 缓存命中率问题一则(里面有个问题咨询大佬们)

    近日,核心数据库频繁抱出数据库缓存命中率过低,于是开始进行排查. 1.监控软件告警信息 2.抓取告警时间段内的awr报告进行分析 3.execute与parse命中率过低,说明分析(硬解析与软解析)的 ...

  4. 解决最新版 mac os sierra usb网卡不能使用的问题

    解决最新版 mac os sierra usb网卡不能使用的问题 解决最新版 mac os sierra usb网卡不能使用 无法使用未签名第三驱动的问题 我的情况是 mac os sierra 使用 ...

  5. Matlab 编程入门(一):编程基础

    上学期学了一些matlab的知识,这学期再用时竟然发现已经忘得差不多了(┬_┬) 于是决定重新开始并将它们记录下来,也方便自己以后查漏补缺! M文件编程 脚本文件 matlab有自己的命令行窗口,对于 ...

  6. kali linux 安装TIM or QQ(CrossOver 安装 QQ)

    需要文件 http://www.crossoverchina.com/xiazai.html dpkg --add-architecture i386 apt-get update apt-get i ...

  7. 谈个人对avascript面向对象的理解

    javascript,不但是javascript或者是别的语音,大多数都有一句经典的话:一切皆对象. 下面谈谈我个人对面向对象的理解,为什么要用面向对象来写js,这话我思考了很久,最后得出的结论就是: ...

  8. 解决 LLVM 错误 fatal error: ‘csignal’ file not found

    /Users/exchen/Downloads/Unity-iPhone/Classes/main.mm:3:10: fatal error: ‘csignal’ file not found#inc ...

  9. 微信小程序车牌号码模拟键盘输入

    微信小程序车牌号码模拟键盘输入练习, 未经允许,禁止转载,抄袭,如需借鉴参考等,请附上该文章连接. 相关资料参考:https://blog.csdn.net/littlerboss/article/d ...

  10. nginx的docker化部署

    nginx的docker化有一个隐藏的坑,就是其默认的配置目录(/etc/nginx)需要先从容器中拷贝出来. 拉取镜像 docker pull nginx 启动容器 docker run -d -- ...