百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

unittest 单元测试框架(unittest框架缺点)

ccwgpt 2024-10-04 13:50 54 浏览 0 评论

unittest 单元测试框架

Unittest 单元测试框架简介

Unittest 是python内置的单元测试框架,具备编写用例、组织用例、执行用例、功能,可以结合selenium 进行UI自动化测试,也可以结合appium、requests 等模块做其它自动化测试。

使用unittest 前需要熟悉该框架的五个概念:

test case : 一个完整的测试单元,执行该测试单元可以完成对某一个问题的验证,完整提现在测试前环境准备(setUp),执行测试代码(run),一级测试后环境还原(tearDown)‘

test suit :多个测试用例的集合,测试套件或测试计划;

testLoader : 加载TestCase 到TestSuite 中的,其中loadTestsFrom__() 方法用于寻找TestCase,并创建它们的实例,然后添加到TestSuite中。

test runner : 执行多个测试用例,并将测试结果保存到TestTestResults 实例中,包括允许多少测试用例,成功了多少,失败了多少等信息;

test fixture : 一个测试用例的初始化准备环境及环境还原,主要是setUp() 和setDown() 方法

Unittest 基础框架

unittest 基础使用步骤:

  1. 用import 语句引入unittest 模块
  2. 让所执行的测试的类都基础于TestCase类,可以将TestCase看出是对特定类进程测试的方法的集合
  3. setUp() 方法中进行测试前的初始化工作, teardown() 方法中执行测试后的清理工作,它们都是TestCase 中的方法
  4. 编写测试的方法最好以test 开头(可以直接运行)

def test_add(self)、def test_sub(self)等,可以编写多个测试用例对被测对象进行测试

  1. 在编写测试方法过程中,使用TestCase class提供的方法测试功能点,比如:assertEqual等
  2. 调用 unittest.main() 方法运行所有以test开头的方法。

unittest 代码示例

import unittest
class test_cases(unittest.TestCase): # 继承TestCase类
def setUp(self): # 测试用例执行之前初始化
print('setUp')
def tearDown(self): # 测试用例执行之后还原、清理
print('tearDown')
def testcase01(self):
print('execute case01')
self.assertEqual(3,3) # 断言
if __name__ == '__main__':
unittest.main()

unittest 常用断言介绍:

断言即进行预期结果和实际结果对比。

assertEqual(a,b) a == b # a,b 是否相等

assertNotEqual(a,b) a != b # a,b 是否不相等

assertTrue(x) bool(x) is True # x 是否为True

assertFalse(x) bool(x) is False # x 是否为False

assertIn(a,b) a in b # a是否包含 b

assertGreater(a,b) a>b # a大于b

assertGreaterEqual(a,b) a>=b # a 大于等于b

assertLess(a,b) a<b # a 小于 b

assertLessEqual(a,b) a<=b # a 小于等于b

可以在断言最后一个参数中加入自定义的测试失败信息,如:

assertEqual(10,20,”10!=20 测试失败”) 当断言失败时,显示该信息。

unittest用例执行顺序:

当在一个测试类或多个测试模块下,用例数量较多时,unittest在执行用例(test_xxx)时,并不是从上到下的顺序执行,有特定的顺序。

unittest框架默认根据ACSII码的顺序加载测试用例,数字与字母的顺序为0~9,A~Z,a~z。

对于类来说,class TestAxx 会优先于class TestBxx被执行,对于方法来说,test_aaa()方法会优先于test_bbb()被执行。对于测试目录与测试文件来说,unittest同样时按照这个规则来加载测试用例的。

Unittest 用例执行顺序代码示例:

import unittest
class test_cases_01(unittest.TestCase):
def setUp(self) -> None:
print('setup')
def tearDown(self) -> None:
print('tearDown')
def test_ccc(self):
print('execute test_ccc')
self.assertEqual(3,3)
def test_aaa(self):
print('execute test_aaa')
self.assertEqual(3,3)
if __name__ == '__main__':
unittest.main()

Unittest 控制测试用例执行顺序:

如需要unittest自行控制测试方法的执行顺序,可以通过如下两种方法;

方法一:通过addTest()添加用例的顺序控制用例执行

if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(test_cases_01(
'test_ccc'))
suite.addTest(test_cases_01(
'test_aaa'))
unittest.main(
defaultTest='suite')

方法二:顺应unittest的默认执行顺序,通过设置测试类或者测试方法方法名字来实现。

Unittest 忽略用例:

在执行测试脚本的时候,可能会有某几条用例本次不想执行,但又不想删也不想注释,unittest通过忽略部分测试用例不执行的方式,分无条件忽略和有条件忽略,通过装饰器实现所描述的场景。提供的装饰器如下:

@unittest.skip(reason): 强制跳转。reason是跳转原因

@unittest.skipIf(condition,reason):condition为True的时候跳转

@unittest.skipUnless(condition,reason):condition为False的时候跳转

@unittest.expectedFailure:标记该测试预期为失败,如果该测试方法运行失败,则该测试不算做失败。

Unittest忽略用例示例代码:

import unittest
class test_cases_01(unittest.TestCase):
def setUp(self) -> None:
print('setup')
def tearDown(self) -> None:
print('tearDown')
@unittest.skip('无条件跳过')
def test_ccc(self):
print('execute test_ccc')
self.assertEqual(3, 3)
@unittest.skipIf(True, '条件为真时跳过')
def test_aaa(self):
print('execute test_aaa')
self.assertEqual(3, 3)
@unittest.skipUnless(False, '条件为假跳过')
def test_bbb(self):
print('execute test_bbb')
self.assertEqual(3, 3)
@unittest.expectedFailure # 预期结果为断言失败
def test_ddd(self):
print('execute test_ddd')
self.assertEqual(3, 3)
def test_fff(self):
print('execute test_fff')
self.assertEqual(3, 3)
if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(test_cases_01(
'test_ccc'))
suite.addTest(test_cases_01(
'test_aaa'))
suite.addTest(test_cases_01(
'test_bbb'))
suite.addTest(test_cases_01(
'test_ddd'))
suite.addTest(test_cases_01(
'test_fff'))
unittest.main(
defaultTest='suite')

构建测试套件

在实际项目中,随着项目进度的开展,测试类会越来越多,可是直到现在我们还只会一个一个单独运行测试类,这在实际项目实践中肯定是不可行的,在unittest中可以通过测试套件来解决该问题。

测试套件(Test Suits)是由多个测试用例(Test Case)组成的,当然也可以由多个子套件组成。

在unittest中,把测试用例加载到测试套件的方法由如下方法:

方法一:

用unittest.TestSuite()实例化测试套件对象后,内部的addTest() 方法对测试类颞部的测试案例逐一添加:

if __name__ == '__main__':
suite = unittest.TestSuite()
suite.addTest(test_cases_01(
'test_ccc')) # 增加单个测试用例
suite.addTest(test_cases_01(
'test_aaa'))
unittest.main(
defaultTest='suite')

方式二:

Unitttest提供一个TestLoader类用于自动创建一个测试集并把单个测试放入到测试集中。TestLoader自动运行以test开头的测试方法。可以通过如下方法加载用例:

if __name__ == '__main__':
# 增加类下的所有用例
suite01 = unittest.TestLoader().loadTestsFromTestCase('TestCase02')
# 增加模块下所有用例
suite02 = unittest.TestLoader().loadTestsFromModule('test_case_02')
suite02.run()

在导入类及模块下的测试用例之前,如果用例实在其它模块,需要先进行import导入操作。

方式三:

用unittest.TestSuite()实例化测试套件对象后,内部的addTests()方法可以把多个子测试集合进行整合到一个大的测试集合中

if __name__ == '__main__':
allsuite = unittest.TestSuite()
# 增加单个测试用例
testsuite01 = unittest.TestSuite()
testsuite01.addTest(
'test_dddd')
testsuite01.addTest(
'test_eee')
testsuite02 = unittest.TestLoader().loadTestsFromModule(
'TestCases03') # 增加模块下的所有用例?
allsuite.addTests(testsuite01) # 把testsuite01集合的用例加载到allsuite测试集合
allsuite.addTests(testsuite02) # 把testsuite02 集合的用例加载到allsuite测试集合
unittest.main(defaultTest='allsuite')

方式四:

当测试用例存放在多个不同目录下,我们能用之气那把用例加载到测试集合中的方式是不太方便,需要不断去导入和添加用例模块,如此可以通过discover()方法实现,实现如下:

Discover(start_dir,pattern = ‘test*.py’,top_level_dir = None)

Start_dir : 要测试的模块名或测试用例目录;

Pattern=’test*.py’ :表示用例文件名的匹配原子,例子中匹配文件名以“test”开头的“.py”文件,星号“*”表示任意多个字符。

Top_level_dir=None :测试模块的顶层目录,如果没有顶层目录,默认是None。

该方法通过从指定的开始目录递归到子目录中查找所有测试模块,并返回包含它们的TestSuite对象,只要与模式匹配测试文件和可导入的模块名称才会被加载。

如果一个测试文件的名称符合pattern,会自动查找该文件中派生自TestCase的类包含的test开头的方法作为测试方法。

代码示例:


import unittest,os
case_path = os.path.join(os.path.dirname(__file__))
print(case_path)
def get_all_cases():
discover = unittest.defaultTestLoader.discover(case_path,
pattern='test*.py',top_level_dir=None) # 加载不同模块下的用例
suit = unittest.TestSuite()
suit.addTest(discover)
return suit
if __name__ == '__main__':
suite = unittest.TestSuite()
suite = get_all_cases()
unittest.main(
defaultTest='suite')

Unittest 生成测试报告

测试报告为测试结果的统计即展示,是自动化测试不可或缺的一部分,利用unittest生成测试报告方式如下:

方式一:

用unittest.main()执行测试集

if __name__ == '__main__':
suite = unittest.TestSuite()
unittest.main()
# 执行当前模块下所有类的测试用例
unittest.main(verbosity=2) # 执行当前模块下所有类的测试用例
unittest.main(defaultTest='suite') # 执行suite测试集合下所有的测试用例

这里的verbosity是一个选项,表示测试结果的信息复杂度,有三个值:

0 (静默模式) :你只能获得总的测试用例数和总的结果,比如100个,失败20个,成功80个

1 (默认模式) :非常类似静默模式,只是再每个成功的用力前面有个“.”,每个失败的用例前面有个“F”。

2 (详细模式) :测试结果会显示每个测试用例的所有相关的信息

方式二:

使用TextTestRunner 执行测试用例集,TextTestRunner有三个参数,它们都哦有静默参数:

  1. Verbosity 分别三个级别:0,1,2它们输出的测试报告详细程度不同,2 最详细
  2. Stream 关系着测试报告的位置,如果默认为None的话,测试报告会输出到控制台
  3. descriptions 测试报告的描述

mport unittest,os
case_path = os.path.join(os.path.dirname(__file__))
print(case_path)
def get_all_cases():
discover = unittest.defaultTestLoader.discover(case_path,
pattern='test*.py',top_level_dir=None) # 加载不同模块下的用例
suit = unittest.TestSuite()
suit.addTest(discover)
return suit
if __name__ == '__main__':
# 方式一:
# suite = unittest.TestSuite()
# suite = get_all_cases()
# unittest.main(defaultTest='suite')
# 方式二:
# suite = unittest.TestSuite()
# unittest.main() # 执行当前模块下所有类的测试用例
# unittest.main(verbosity=2) # 执行当前模块下所有类的测试用例
# unittest.main(defaultTest='suite') # 执行suite测试集合下所有的测试用例
# 方式三:
from sample.test_02.test_cases_01 import test_cases_01
suite = unittest.TestSuite()
suite = get_all_cases()
test_runner = unittest.TextTestRunner(
stream=None,descriptions=None,verbosity=2)
test_runner = unittest.TextTestRunner(
stream=None,descriptions=None,verbosity=0)
with open('test_result.txt','w',encoding='utf-8') as file:
runner = unittest.TextTestRunner(
stream=file, descriptions='执行用例的测试报告', verbosity=2)
runner.run(suite)

生成的txt报告:

方式三:

使用第三方HTMLRunner 执行用例集,它可以输出网页版本测试报告

HTMLTestRunner 是Python标准库的unittest模块的一个扩展,在使用该模块之前要下载HTMLTestRunner.py文件,并将该文件保存在python安装路径下的lib文件夹或者是项目的子包中,在python代码中通过import HTMLTestRunner导入,即可使用。

import unittest,os
case_path = os.path.join(os.path.dirname(__file__))
print(case_path)
def get_all_cases():
discover = unittest.defaultTestLoader.discover(case_path,
pattern='test*.py',top_level_dir=None) # 加载不同模块下的用例
suit = unittest.TestSuite()
suit.addTest(discover)
return suit

if __name__ == '__main__':
import HTMLTestRunner
suite = unittest.TestSuite()
suite = get_all_cases()
html_obj =
open('result.html','w+',encoding='utf-8') # 创建
runner = HTMLTestRunner.HTMLTestRunner(stream=html_obj,
title='测试报告',
description='测试报告')
runner.run(suite)

HTMLTestRunner常用参数:

stream : 配置测试报告要保存的文件路径

title : 测试报告标题

description : 测试报告的描述信息

生成的简易的html报告:

测试用例信息在报告中显示:

一:在测试用例中加上注释西悉尼,即可在html报告中体现,能更好的展示每个用例的信息。

import unittest,os
class TestCases03(unittest.TestCase):
'''测试类的详细信息'''
def setUp(self) -> None:
print('setUp')
def tearDown(self) -> None:
print('tearDown')
def test_aaa(self):
'''测试用例test_aaa的详细信息'''
print('execute test_aaa')
self.assertEqual(3,3)
def test_ccc(self):
'''测试用例test_ccc的详细信息'''
print('execute test_ccc')
self.assertEqual(3,3)
def test_dddd(self):
'''测试用例test_dddd的详细信息'''
print('execute test_ccc')
self.assertEqual(3,3)
def test_eee(self):
'''测试用例test_eee的详细信息'''
print('execute test_eee')
self.assertEqual(3, 3)

测试用例信息在报告中显示:

二:在测试方法中通过:

self._testMethodName = ‘设置测试用例的名称’

self._testMethodDoc = ‘设置测试用例详情’

def test_aaa(self):
'''测试用例test_aaa的详细信息'''
self._testMethodName = 'test_aaa'
self._testMethodDoc = '测试用例test_aaa详细信息'
print('execute test_aaa')
self.assertEqual(3,3)

生成的报告如下图:

方式四:

使用第三方HTMLTest ReportCN 执行测试用例集,它可以输出网页版测试报告。

在使用该模块之前下载HTMLReportCN.py文件,并将该文件保存在python安装路径下的lib文件夹或项目的子包中,在python代码中通过

import HTMLTestReportCN 导入,即可使用。


from sample.test_02.comm import HTMLTestReportCN
suite = unittest.TestSuite()
suite = get_all_cases()
report_dir =
'./html_report/' # 测试报告路径,必须以 / 结尾
report_path_obj = HTMLTestReportCN.ReportDirectory(report_dir) # 创建测试报告路径对象
report_path_obj.create_dir('UI 自动化测试_') # 创建测试报告存放目录
html_path = HTMLTestReportCN.GlobalMsg.get_value('report_path') # 获取测试报告文件对象
html_file = open(html_path,'wb') # 创建html测试报告
html_runner = HTMLTestReportCN.HTMLTestRunner(stream=html_file,
title='UI 测试报告',
tester='YangShiYu',
description='20221013')
html_runner.run(suite)

生成的测试报告展示如下:

相关推荐

自己动手写Android数据库框架_android开发数据库搭建

http://blog.csdn.net/feiduclear_up/article/details/50557590推荐理由关于Android数据库操作,由于每次都要自己写数据库操作,每次还得去...

谷歌开源大模型评测工具LMEval,打通谷歌、OpenAI、Anthropic

智东西编译|金碧辉编辑|程茜智东西5月28日消息,据科技媒体TheDecoder5月26日报道,当天,谷歌正式发布开源大模型评测框架LMEval,支持对GPT-4o、Claude3.7...

工信部:着力推动大模型算法、框架等基础性原创性的技术突破

工信部新闻发言人今日在发布会上表示,下一步,我们将坚持突出重点领域,大力推动制造业数字化转型,推动人工智能创新应用。主要从以下四个方面着力。一是夯实人工智能技术底座。通过科技创新重大项目,着力推动大模...

乒乓反复纠结“框架不稳定”的三个小误区

很多球友由于对框架的认知不清晰,往往会把“框架不稳定”当成一种心理负担,从而影响学球进度,其典型状态就是训练中有模有样,一旦进入实战,就像被捆住了手脚。通过训练和学习,结合“基本功打卡群”球友们交流发...

前AMD、英特尔显卡架构师Raja再战GPU,号称要全面重构堆栈

IT之家8月5日消息,知名GPU架构师拉贾科杜里(RajaKoduri)此前曾先后在AMD和英特尔的显卡部门担任要职。而在今日,由Raja创立的GPU软件与IP初创企...

三种必须掌握的嵌入式开发程序架构

前言在嵌入式软件开发,包括单片机开发中,软件架构对于开发人员是一个必须认真考虑的问题。软件架构对于系统整体的稳定性和可靠性是非常重要的,一个合适的软件架构不仅结构清晰,并且便于开发。我相...

怪不得别人3秒就知道软考案例怎么做能50+

软考高级统一合格标准必须三科都达到45分,案例分析也一直是考生头疼的一门,但是掌握到得分点,案例能不能50+还不是你们说了算吗?今天就结合架构案例考点,分享实用的备考攻略~一、吃透考点,搭建知识框架从...

UML统一建模常用图有哪些,各自的作用是什么?一篇文章彻底讲透

10万+爆款解析:9大UML图实战案例,小白也能秒懂!为什么需要UML?UML(统一建模语言)是软件开发的“蓝图”,用图形化语言描述系统结构、行为和交互,让复杂需求一目了然。它能:降低沟通成本避...

勒索软件转向云原生架构,直指备份基础设施

勒索软件组织和其他网络犯罪分子正越来越多地将目标对准基于云的备份系统,对久已确立的灾难恢复方法构成了挑战。谷歌安全研究人员在一份关于云安全威胁演变的报告中警告称,随着攻击者不断改进数据窃取、身份泄露和...

ConceptDraw DIAGRAM:释放创意,绘就高效办公新未来

在当今数字化时代,可视化工具已成为提升工作效率和激发创意的关键。ConceptDrawDIAGRAM,作为一款世界顶级的商业绘图软件,凭借其强大的功能和用户友好的界面,正逐渐成为众多专业人士的首选绘...

APP 制作界面设计教程:一步到位_app界面设计模板一套

想让APP界面设计高效落地,无需繁琐流程,掌握“框架搭建—细节填充—体验优化”三步法,即可一步到位完成专业级设计。黄金框架搭建是基础。采用“三三制布局”:将屏幕横向三等分,纵向保留三...

MCP 的工作原理:关键组件_mcp部件

以下是MCP架构的关键组件:MCP主机:像ClaudeDesktop、GitHubCopilot或旅行助手这样的AI智能体,它们希望通过MCP协议访问工具、资源等。MCP主机会...

软件架构_软件架构师工资一般多少

软件架构师自身需要是程序员,并且必须一直坚持做一线程序员。软件架构应该是能力最强的一群程序员,他们通常会在自身承接编程任务的同时,逐渐引导整个团队向一个能够最大化生产力的系统设计方向前进。软件系统的架...

不知不觉将手机字体调大!老花眼是因为“老了吗”?

现在不管是联系、交友,还是购物,都离不开手机。中老年人使用手机的时间也在逐渐加长,刷抖音、看短视频、发朋友圈……看手机的同时,人们也不得不面对“视力危机”——老花眼,习惯眯眼看、凑近看、瞪眼看,不少人...

8000通用汉字学习系列讲座(第046讲)

[表声母字]加(续)[从声汉字]伽茄泇迦枷痂袈笳嘉驾架咖贺瘸(计14字)嘉[正音]标准音读jiā。[辨形]上下结构,十四画。会意形声字,从壴从加,加也表声。注:从壴,字义与鼓乐有关;从加,字义与...

取消回复欢迎 发表评论: