Python:单元测试框架unittest
1、什么是单元测试
测试函数/方法或者一段代码,用于检验被测代码的一个很小的、很明确的功能是否正确,通常是开发做。
在Python中的单元测试框架有Unittest和Pytest,现在总结Unittest。
2、单元测试框架
1、Unittest框架的五个概念
test fixture:测试固件
test case:测试用例
test suit:测试套件
test runner:测试运行器
test loader:测试加载器
1) Test Case
一个TestCase 的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。单元测试(unittest)的本质也就在这里。一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证。
2) Test Suite
多个测试用例集合在一起,就是TestSuite,而且TestSuite也可以嵌套Test Suite。
3) Test runner
是用来执行测试用例的,其中的run(test)会执行TestSuite/TestCase 中的run(result) 方法。
4) Test Loader
是用来加载TestCase到Test Suite中的,其中几个 loadTestsFrom__() 方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite 实例。
5) Test fixture
对一个测试用例环境的搭建和销毁,是一个fixture,通过覆盖Test Case的setUp() 和tearDown() 方法来实现。
2、Unittest中的两个方法
方法1:setup 和teardown
1)结构:
测试基本setup方法:第一个测试开始之前只执行一次
多个类
类:
类setup方法:在当前类的第一个测试方法调用前执行,只执行一次 setup方法:在执行测试方法前的一些环境或者数据相关的准备
测试的方法:每个测试方法执行前,都会执行setup方法,然后执行teardown方法
teardown方法:在执行方法后的一些环境或者数据相关的清理 类teardown方法:在当前类的最后一个测试方法调用后执行,只执行一次 测试级别teardown方法:所有的测试结束之后只执行一次
2)说明
setUp:实现测试前的初始化工作
tearDown:实现测试结束后的清理工作
用例之间按用例ASCII码的顺序加载,数字和字母顺序为 0~9,A~Z,a~z。
方法2:断言方法

3、加载测试用例的四种方法
首先实例化:
suite = unittest.TestSuite()
loader = unittest.TestLoader()
方法一:通过测试用例类进行加载
suite.addTest(loader.loadTestsFromTestCase(MyTest1))
suite.addTest(loader.loadTestsFromTestCase(MyTest2))
方法二:通过测试用例模版去加载
suite.addTest(loader.loadTestsFromTestModule(MyTest1))
suite.addTest(loader.loadTestsFromTestModule(MyTest2))
方法三:通过路径加载
import os
path = os.path.dirname(os.path.abspath(__file__))
suite.addTest(loader.discover(path))
方法四:逐条加载 low
case1 = MyTest1("test1")
case2 = MyTest1("test2")
suite.addTest(case1)
suite.addTest(case2)
3、代码举例
举例1:
#encoding=utf-8
import unittest # 被测试类
class myclass(object):
@classmethod #可以不加,但是调用前需要实例化
def sum(self, a, b):
return a + b #将两个传入参数进行相加操作 @classmethod #可以不加,但是调用前需要实例化
def sub(self, a, b):
return a - b #将两个传入参数进行相减操作 class mytest(unittest.TestCase):
@classmethod #必须加
def setUpClass(cls):#每个测试类的setup方法,只会执行一次
"初始化类固件,固件是准备的意思"
print ( "----setUpClass") @classmethod #必须加
def tearDownClass(cls):#每个测试类的tearDown方法,只会执行一次
"重构类固件"
print ( "----tearDownClass") # 初始化工作
def setUp(self):#每个测试方法均会执行一次
self.a = 3
self.b = 1
print ( "--setUp") # 退出清理工作
def tearDown(self):#每个测试方法均会执行一次
print ( "--tearDown") # 具体的测试用例,一定要以test开头
def testsum(self): #每个测试用例执行成功一次,打印一个 .
# 断言两数之和的结果是否是4
self.assertEqual(myclass.sum(self.a, self.b), 4, 'test sum fail') def testsub(self):
# 断言两数之差的结果是否是2
self.assertEqual(myclass.sub(self.a, self.b), 2, 'test sub fail') if __name__ == '__main__':
unittest.main() # 启动单元测试
执行结果:

举例2:跳过指定的测试用例的三种方法
# coding=utf-8
import random
import unittest
import sys class TestSequenceFunctions(unittest.TestCase):
a = 6 def setUp(self):
self.seq = list(range(10)) @unittest.skip("skipping") # 无条件忽略该测试方法
def test_shuffle(self):
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, list(range(10)))
self.assertRaises(TypeError, random.shuffle, (1, 2, 3)) # 如果变量a > 5,则忽略该测试方法
@unittest.skipIf(a > 5, "condition is not satisfied!")
def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq) # 除非执行测试用例的平台是Linux平台,否则忽略该测试方法 win32是windows
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux") #被忽略时打印 第二个参数
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq) if __name__ == '__main__':
# unittest.main()
# 指定加载哪几个测试类,生成测试集合
suite = unittest.TestLoader().loadTestsFromTestCase(TestSequenceFunctions)
suite = unittest.TestSuite(suite)
unittest.TextTestRunner(verbosity = 2).run(suite)
结果:
D:\学习\自动化\单元测试>py -3 e4_unittest_skip.py
test_choice (__main__.TestSequenceFunctions) ... skipped 'condition is not satisfied!'
test_sample (__main__.TestSequenceFunctions) ... skipped 'requires Linux'
test_shuffle (__main__.TestSequenceFunctions) ... skipped 'skipping' ----------------------------------------------------------------------
Ran 3 tests in 0.003s OK (skipped=3)
举例3:常用断言举例
#encoding=utf-8
import unittest
import random # 被测试类
class MyClass(object):
@classmethod
def sum(self, a, b):
return a + b @classmethod
def div(self, a, b):
return a / b @classmethod
def retrun_None(self):
return None # 单元测试类
class MyTest(unittest.TestCase): # assertEqual()方法实例
def test_assertEqual(self):
# 断言两数之和的结果
# 一般不需要捕获异常,unittest会自动捕获异常
try:
a, b = 1, 2
sum = 3
self.assertEqual(a + b, sum, '断言失败,%s + %s != %s' %(a, b, sum))
except AssertionError as e:
print (e) # assertNotEqual()方法实例
def test_assertNotEqual(self):
# 断言两数之差的结果
try:
a, b = 5, 2
res = 1
self.assertNotEqual(a - b, res, '断言失败,%s - %s != %s' %(a, b, res))
except AssertionError as e:
print (e) # assertTrue()方法实例
def test_assertTrue(self):
# 断言表达式的为真
try:
self.assertTrue(1 == 1, "表达式为假")
except AssertionError as e:
print (e) # assertFalse()方法实例
def test_assertFalse(self):
# 断言表达式为假
try:
self.assertFalse(3 == 2, "表达式为真")
except AssertionError as e:
print (e) # assertIs()方法实例
def test_assertIs(self):
# 断言两变量类型属于同一对象
try:
a = 12
b = a
self.assertIs(a, b, "%s与%s不属于同一对象" %(a, b))
except AssertionError as e:
print (e) # test_assertIsNot()方法实例
def test_assertIsNot(self):
# 断言两变量类型不属于同一对象
try:
a = 12
b = "test"
self.assertIsNot(a, b, "%s与%s属于同一对象" %(a, b))
except AssertionError as e:
print (e) # assertIsNone()方法实例
def test_assertIsNone(self):
# 断言表达式结果为None
try:
result = MyClass.retrun_None()
self.assertIsNone(result, "not is None")
except AssertionError as e:
print (e) # assertIsNotNone()方法实例
def test_assertIsNotNone(self):
# 断言表达式结果不为None
try:
result = MyClass.sum(2, 5)
self.assertIsNotNone(result, "is None")
except AssertionError as e:
print (e) # assertIn()方法实例
def test_assertIn(self):
# 断言对象A是否包含在对象B中
try:
strA = "this is a test"
strB = "is"
self.assertIn(strB, strA, "%s不包含在%s中" %(strB, strA))
except AssertionError as e:
print (e) # assertNotIn()方法实例
def test_assertNotIn(self):
# 断言对象A不包含在对象B中
try:
strA = "this is a test"
strB = "Selenium"
self.assertNotIn(strB, strA, "%s包含在%s中" %(strB, strA))
except AssertionError as e:
print (e) # assertIsInstance()方法实例
def test_assertIsInstance(self):
# 测试对象A的类型是否值指定的类型
try:
x = MyClass
y = object
self.assertIsInstance(x, y, "%s的类型不是%s" %(x, y))
except AssertionError as e:
print (e) # assertNotIsInstance()方法实例
def test_assertNotIsInstance(self):
# 测试对象A的类型不是指定的类型
try:
a = 123
b = str
self.assertNotIsInstance(a, b, "%s的类型是%s" %(a, b))
except AssertionError as e:
print (e) # assertRaises()方法实例
def test_assertRaises(self):
# 测试抛出的指定的异常类型
# assertRaises(exception)
with self.assertRaises(TypeError) as cm:
random.sample([1,2,3,4,5], "j")
# 打印详细的异常信息
#print "===", cm.exception # assertRaises(exception, callable, *args, **kwds)
try:
self.assertRaises(ZeroDivisionError, MyClass.div, 3, 0)
except ZeroDivisionError as e:
print (e) # assertRaisesRegexp()方法实例
def test_assertRaisesRegexp(self):
# 测试抛出的指定异常类型,并用正则表达式具体验证
# assertRaisesRegexp(exception, regexp)
with self.assertRaisesRegex(ValueError, 'literal') as ar:
int("xyz")
# 打印详细的异常信息
#print ar.exception
# 打印正则表达式
#print "re:",ar.expected_regexp # assertRaisesRegexp(exception, regexp, callable, *args, **kwds)
try:
self.assertRaisesRegexp(ValueError, "invalid literal for.*XYZ'$", int, 'XYZ')
except AssertionError as e:
print (e) if __name__ == '__main__':
# 执行单元测试
unittest.main()
举例4:生成图形化测试报告
导入文件HTMLTestRunner.py ;放到python的安装目录下(D:\Python37-32\Lib\site-packages)
运行对应的主方法:
import unittest import HTMLTestRunner if __name__ == '__main__' :
# 加载当前目录下所有有效的测试模块(以test开头的文件),“.”表示当前目录
testSuite = unittest.TestLoader().discover('.')
filename = "test.html" # 定义个报告存放路径,支持相对路径。
# 以二进制方式打开文件,准备写
fp = open(filename, 'wb')
# 使用HTMLTestRunner配置参数,输出报告路径、报告标题、描述,均可以配
runner = HTMLTestRunner.HTMLTestRunner(stream = fp,
title = 'Report_title', description = 'Report_description')
# 运行测试集合
runner.run(testSuite)
结果:

举例5:单元测试框架跑UI测试
#encoding=utf-8
import unittest
from selenium import webdriver
import time class GloryRoad(unittest.TestCase):
def setUp(self):
# 启动Chrome浏览器
# 驱动文件位置要改,本地自己的驱动
self.driver = webdriver.Chrome() def testSoGou(self):
# 访问搜狗首页
self.driver.get("http://sogou.com")
# 清空搜索输入框默认内容
self.driver.find_element_by_id("query").clear()
# 在搜索输入框中输入“光荣之路自动化测试”
self.driver.find_element_by_id("query").send_keys(u"WebDriver实战宝典")
# 单击“搜索”按钮
self.driver.find_element_by_id("stb").click()
# 等待3秒
time.sleep(3)
assert u"吴晓华" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk") def testBing(self):
# 访问bing首页
self.driver.get("http://cn.bing.com")
# 清空搜索输入框默认内容
self.driver.find_element_by_id("sb_form_q").clear()
# 在搜索输入框中输入“光荣之路自动化测试”
self.driver.find_element_by_id("sb_form_q").send_keys(u"WebDriver实战宝典")
# 单击“搜索”按钮
self.driver.find_element_by_id("sb_form_go").click()
# 等待3秒
time.sleep(3)
assert u"吴晓华" in self.driver.page_source, u"页面中不存在要寻找的关键字!".encode("gbk") def tearDown(self):
# 退出浏览器
self.driver.quit() if __name__ == '__main__':
unittest.main()
举例6:单元测试和ddt数据驱动结合
安装包:pip3 install ddt
代码:
import unittest
import ddt @ddt.ddt
class Praddt(unittest.TestCase): def setUp(self):
print("my test start!") def tearDown(self):
print("my test complete!") @ddt.data(["admin", "1qaz", "OK"], #一组数据,每一行都会触发运行
["admin", "", "ERROR"], #另一组数据
["1", "1qaz", "ERROR"], #另一组数据..
["admin", "1234", "ERROR"],
["Admin", "1qaz", "ERROR"]) #实现了数据驱动,可以执行5次 @ddt.unpack
def test_ddt(self, user, passwd, expect_value):
print(user,passwd,expect_value)
self.assertTrue(len(user)>0) if __name__ == '__main__':
# 执行单元测试
unittest.main()
测试结果:

Python:单元测试框架unittest的更多相关文章
- Python单元测试框架unittest使用方法讲解
这篇文章主要介绍了Python单元测试框架unittest使用方法讲解,本文讲解了unittest概述.命令行接口.测试案例自动搜索.创建测试代码.构建测试套件方法等内容,需要的朋友可以参考下 概 ...
- Python单元测试框架unittest之深入学习
前言 前几篇文章该要地介绍了python单元测试框架unittest的使用,本篇文章系统介绍unittest框架. 一.unittest核心工作原理 unittest中最核心的四个概念是:test c ...
- Python单元测试框架unittest之单用例管理(一)
一.概述 本文介绍python的单元测试框架unittest,unittest原名为PyUnit,是由java的JUnit衍生而来,这是Python自带的标准模块unittest.unittest是基 ...
- Python单元测试框架unittest
学习接口自动化测试时接触了unittest单元测试框架,学习时参照了虫师编写的<selenium2自动化测试实战>,个人觉得里面讲的例子还比较容易理解的. 一.基础 1.main()和框架 ...
- Python单元测试框架unittest重要属性 与 用例编写思路
前言 本文为转载,原文地址作者列举python unittest这个测试框架的主要属性和 测试用例思路 unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行, ...
- python单元测试框架-unittest(一)
简介 unittest单元测试框架不仅可以适用于单元测试,还可以使用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果. ...
- Python单元测试框架——unittest
测试的常用规则 一个测试单元必须关注一个很小的功能函数,证明它是正确的: 每个测试单元必须是完全独立的,必须能单独运行.这样意味着每一个测试方法必须重新加载数据,执行完毕后做一些清理工作.通常通过se ...
- Python单元测试框架 unittest详解
一 整体结构概览 unittest原名为PyUnit,是由java的JUnit衍生而来.对于单元测试,需要设置预先条件,对比预期结果和实际结果. TestCase :通过继承TestCase类,我们可 ...
- python单元测试框架-unittest(四)之用例综合框架管理
简述为何如要框架? 前面测试用例与执行都是写在一个文件,当用例数量不断增加的时候,用例的执行与管理变得非常麻烦,因此需要对用例根据具体的功能模块来使用单独的模块来管理.就像一所学校要根据不同年级进行分 ...
- Python3 Selenium自动化web测试 ==> 第一节 起始点之Python单元测试框架 unittest
前置步骤 Python版本:3.6.4 selenium版本:3.11.0 >>> import selenium >>> help(selenium) IDE:P ...
随机推荐
- K8S集群中使用JD KMS服务对敏感数据安全加密
基本概念 KMS,Key Management Service,即密钥管理服务,在K8S集群中,以驱动和插件的形式启用对Secret,Configmap进行加密.以保护敏感数据, 驱动和插件需要使用者 ...
- 虾皮shopee根据ID取商品详情 API 返回值说明
item_get-根据ID取商品详情 注册开通 shopee.item_get 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中) secr ...
- api接口对接如何实现商品数据采集的
在当前互联网行业中,快速准确地采集和处理大量数据是非常重要的一项任务.而实现商品数据采集则是许多企业和电商平台必须完成的任务之一.使用API接口对接进行商品数据采集可以大大提高数据采集效率和准确性.下 ...
- C++ 重载运算符在HotSpot VM中的应用
C++支持运算符重载,对于Java开发者来说,这个可能比较陌生一些,因为Java不支持运算符重载.运算符重载本质上来说就是函数重载.下面介绍一下HotSpot VM中的运算符重载. 1.内存分配与释放 ...
- git Failed to connect to 127.0.0.1 port xxxx: Connection refused 的问题。
问题描述在使用 git 拉取.提交代码的时候,会出现 git Failed to connect to 127.0.0.1 port xxxx: Connection refused 的问题. 原因: ...
- Android news Display Owner Info on Your Android Device in Case It Gets Lost
Display Owner Info on Your Android Device in Case It Gets Lost The latest versions of Android includ ...
- Java 位运算的解读 & | ^ ~ << >>
Java中的位运算包括以下几种: 按位与(&):对应位上,如果两个数都是1,则结果为1,否则为0. int a = 3; // 二进制 0011 int b = 5; // 二进制 0101 ...
- Meteors 题解
Meteors 蒟蒻初学整体二分,写一篇题解记录一下思考与看法. 题目大意 在一个环形的轨道上分别着若干国家的空间站,在接下来的一段时间内会出现若干次陨石,每次出现在环形的某一段轨道,每个国家都想收集 ...
- 两台实体机器4个虚拟机节点的Hadoop集群搭建(Ubuntu版)
安装Ubuntu Linux元信息 两台机器,每台机器两台Ubuntu Ubuntu版本:ubuntu-22.04.3-desktop-amd64.iso 处理器数量2,每个处理器的核心数量2,总处理 ...
- Kubernetes跨StorageClass迁移,切换Rainbond默认SC
基于主机安装或基于Kubernetes安装的 Rainbond 集群(均使用默认参数安装),默认使用的共享文件存储是 NFS ,以 Pod 方式运行在 Kubernetes 中,但这种方式也有一些无法 ...