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

聊聊 Python 的单元测试框架(二):nose 和它的继任者 nose2

ccwgpt 2024-10-25 10:48 32 浏览 0 评论


作者:HelloGitHub-Prodesire

一、nose

nose[1] 是一个第三方单元测试框架,它完全兼容 unittest,并且号称是一个更好用的测试框架。

那么 nose 除了具备 unittest 的所有功能外,还具有哪些优势呢?

1.1 用例编写

用例的编写方式除了编写继承于 unittest.TestCase[2] 的测试类外,还可以编写成没有继承的测试类。比如,写成如下形式也会被 nose 视作一个测试类:

from nose.tools import raises
?
class TestStringMethods:
?
 def test_upper(self):
 assert 'foo'.upper() == 'FOO'
?
 def test_isupper(self):
 assert 'FOO'.isupper()
 assert not 'Foo'.isupper()
?
 @raises(TypeError)
 def test_split(self):
 s = 'hello world'
 assert s.split() == ['hello', 'world']
 # check that s.split fails when the separator is not a string
 s.split(2)

当然,测试类并没有继承 unittest.TestCase,将不能使用其内置的各类 assertXXX 方法,进而导致用例出错时无法获得更加详细的上下文信息。

此外,nose 也支持定义函数来作为测试,这给许多简单的测试场景带来很大的便利:

def test_upper():
 assert 'foo'.upper() == 'FOO'

1.2 用例发现和执行

unittest 所支持的用例发现和执行能力,nose 均支持。nose 支持用例自动(递归)发现:

  • 默认发现当前目录下所有包含 test 的测试用例,但不包括以 _ 开头的用例
  • 使用 nosetests 命令
  • 通过 -w 参数指定要自动发现的目录, -m 参数指定用例文件、目录、函数、类的名称模式(正则匹配)
  • nosetests -w project_directory "test_.+"

nose 也支持执行指定用例:

  • 指定测试模块
  • nosetests test.module
  • 指定测试类
  • nosetests a.test:TestCase
  • 指定测试方法
  • nosetests another.test:TestCase.test_method
  • 指定测试文件路径
  • nosetests /path/to/test/file.py
  • 指定测试文件路径+测试类或测试函数(这是 unittest 所不支持的)
  • nosetests /path/to/test/file.py:TestCase
  • nosetests /path/to/test/file.py:TestCase.test_method
  • nosetests /path/to/test/file.py:test_function

1.3 测试夹具(Fixtures)

nose 除了支持 unittest 所支持的定义测试前置和清理方式,还支持一种更为简单的定义方式:

def setup_func():
 "set up test fixtures"
?
def teardown_func():
 "tear down test fixtures"
?
@with_setup(setup_func, teardown_func)
def test():
 "test ..."

只需定义两个函数用来表示前置和清理方法,通过 nose.tools.with_setup[3] 装饰器装饰测试函数,nose 便会在执行测试用例前后分别执行所定义的前置和清理函数。

1.4 子测试/测试生成器

nose 除了支持 unittest 中的 TestCase.subTest,还支持一种更为强大的子测试编写方式,也就是 测试生成器(Test generators),通过 yield 实现。

在下面的示例中,定义一个 test_evens 测试函数,里面生成了 5 个子测试 check_even:

def test_evens():
 for i in range(0, 5):
 yield check_even, i, i*3
?
def check_even(n, nn):
 assert n % 2 == 0 or nn % 2 == 0

此外,相较于 unittest.TestCase.subTest 多个子测试只能执行一次测试前置和清理,nose 的 测试生成器 可以支持每个子测试执行一次测试前置和清理,如:

def test_generator():
 # ...
 yield func, arg, arg # ...
?
@with_setup(setup_func, teardown_func)
def func(arg):
 assert something_about(arg)

1.5 插件体系

nose 相较于 unittest 一个最大的优势就是插件体系,自带了很多有用的插件,也有丰富的第三方插件。这样就能做更多的事情。

其中,自带插件如下:

  • AllModules[4]:在所有模块中收集用例
  • Attrib[5]:给用例打标签,并可运行含指定标签的用例
  • Capture[6]:捕获用例的标准输出
  • Collect[7]:快速收集用例
  • Cover[8]:统计代码覆盖率
  • Debug[9]:用例失败时进入 pdb 调试
  • Deprecated[10]:标记用例为弃用
  • Doctests[11]:运行文档用例
  • Failure Detail[12]:断言失败时提供上下文信息
  • Isolate[13]:保护用例避免受一些副作用的影响
  • Logcapture[14]:捕捉 logging 输出
  • Multiprocess[15]:并行执行用例
  • Prof[16]:使用热点分析器进行分析
  • Skip[17]:标记用例为跳过
  • Testid[18]:为输出的每个用例名称添加测试 ID
  • Xunit[19]:以 xunit 格式输出测试结果

而第三方库则多种多样,如用来生成 HTML 格式测试报告的 nose-htmloutput[20] 等,这里不再一一列出。

得益于 nose 丰富的插件生态,当 nose 本身不能够完全满足我们的测试需求时,可以通过安装插件,并在 nosetests 命令行指定该插件所提供的特定参数即可非常容易的使用插件。相较于 unittest,就能省去很多自己开发额外测试逻辑的精力。

二、nose2

nose2[21]nose[22] 的继任者。它们的理念都是让编写和运行测试用例变得更容易。

它们有很多相同点,比如都兼容 unittest,支持使用函数作为测试用例,支持子测试,拥有插件体系。但也有很多不同点,下面列出一些主要的不同点:

  • 发现和载入测试
  • nose 自行实现了模块加载功能,使用惰性方式加载测试模块,加载一个执行一个。
  • nose2 则借助内建的 **import**()[23] 导入模块,并且是先全部载入,再执行用例
  • nose2 并不支持 nose 所支持的所有测试用例项目结构,比如如下用例文件的结构在 nose2 中就不受支持:
.
`-- tests
 |-- more_tests
 | `-- test.py
 `-- test.py
  • 测试前置和清理函数级别
  • nose 支持方法、类、模块和包级别的测试前置和清理函数
  • nose2 则不支持包级别的测试前置和清理函数
  • 子测试
  • nose2 除了支持使用测试生成器来实现子测试外,还支持使用参数化测试(Parameterized tests)[24]来实现子测试
  • nose2 除了像 nose 一样支持在测试函数和测试类(不继承于 unittest.TestCase)中支持参数化测试和测试生成器外,还支持在继承于 unittest.TestCase 的测试类中使用
  • 配置化
  • nose 期望所有插件的配置通过命令行参数进行配置
  • nose2 则通过配置文件进行控制,以最小化命令行参数让人读得更舒服

更多对比详见 官方文档[25]

三、小结

nose 和 nose2 在做到兼容 unittest 上就足以看出它们的目标,那便是要吸引原来那些使用 unittest 的用户来使用它们。它们确实做到了!

nose 和 nose2 在用例编写、测试夹具、子测试上做出改进,已经能让日常用例编写工作变得更加容易和灵活。同时又引入插件体系,进一步将单元测试框架的能力提升了一个大大的台阶,这让很多在基础测试功能之上的高阶功能的实现和共享成为了可能。也难怪有众多开发者对它们情有独钟。

References

[1] nose: https://nose.readthedocs.io/en/latest/

[2] unittest.TestCase: https://docs.python.org/3/library/unittest.html#unittest.TestCase

[3]nose.tools.with_setup: https://nose.readthedocs.io/en/latest/testing_tools.html?highlight=with_setup#nose.tools.with_setup

[4] AllModules: https://nose.readthedocs.io/en/latest/plugins/allmodules.html

[5]Attrib: https://nose.readthedocs.io/en/latest/plugins/attrib.html

[6]Capture: https://nose.readthedocs.io/en/latest/plugins/capture.html

[7]Collect: https://nose.readthedocs.io/en/latest/plugins/collect.html

[8] Cover: https://nose.readthedocs.io/en/latest/plugins/cover.html

[9]Debug: https://nose.readthedocs.io/en/latest/plugins/debug.html

[10]Deprecated: https://nose.readthedocs.io/en/latest/plugins/deprecated.html

[11]Doctests: https://nose.readthedocs.io/en/latest/plugins/deprecated.html

[12]Failure Detail: https://nose.readthedocs.io/en/latest/plugins/failuredetail.html

[13]Isolate: https://nose.readthedocs.io/en/latest/plugins/isolate.html

[14]Logcapture: https://nose.readthedocs.io/en/latest/plugins/logcapture.html

[15] Multiprocess: https://nose.readthedocs.io/en/latest/plugins/multiprocess.html

[16]Prof: https://nose.readthedocs.io/en/latest/plugins/prof.html

[17]Skip: https://nose.readthedocs.io/en/latest/plugins/skip.html

[18]Testid: https://nose.readthedocs.io/en/latest/plugins/testid.html

[19]Xunit: https://nose.readthedocs.io/en/latest/plugins/xunit.html

[20]nose-htmloutput: https://github.com/ionelmc/nose-htmloutput

[21]nose2: https://github.com/nose-devs/nose2

[22]nose: https://nose.readthedocs.io/en/latest/

[23]import(): https://docs.python.org/3/library/functions.html#import

[24]参数化测试(Parameterized tests): https://docs.nose2.io/en/latest/params.html#parameterized-tests

[25] 官方文档: https://docs.nose2.io/en/latest/differences.html

『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源~

相关推荐

用Deepseek扩写土木工程毕业论文实操指南

用Deepseek扩写毕业论文实操指南一、前期准备整理现有论文初稿/提纲列清楚论文核心框架(背景、现状、意义、方法、数据、结论等)梳理好关键文献,明确核心技术路线二、Deepseek扩写核心思路...

985学霸亲授,DeepSeek也能绘6大科研图表,5分钟就出图

在实验数据处理中,高效可视化是每个科研人的必修课。传统绘图软件操作复杂、耗时费力,而智能工具DeepSeek的出现彻底改变了这一现状。本文将详解如何用DeepSeek一键生成六大科研常用图表,从思维导...

AI写论文刷屏?大学生正在丢掉的思考力

一、宿舍深夜:当论文变成"Ctrl+C+V"凌晨两点的大学宿舍,小王对着电脑屏幕叹气。本该三天前开始写的近代史论文,此刻还一片空白。他熟练打开某AI写作网站,输入"论五四运动的...

Grok在辅助论文写作上能不能既“聪明”又“可怕”?!

AcademicIdeas-学境思源AI初稿写作随着人工智能技术的飞速发展,论文写作这一学术任务正迎来新的助力。2025年2月18日,美国xAI公司推出了备受瞩目的Grok3模型,其创始人埃隆·...

大四论文沟通场景!音频转文字难题听脑AI来化解

大四学生都知道,写论文时和导师沟通修改意见,简直是“过关斩将”。电话、语音沟通完,想把导师说的修改方向、重点要求记下来,麻烦事儿可不少。手写记不全,用普通录音转文字工具,转完还得自己慢慢找重点,稍不注...

论文写作 | 技术路线图怎么画?(提供经典优秀模板参考)

技术路线图是一种图表或文字说明,用于描述研究目标、方法和实施计划。它展示了研究的整体框架和步骤,有助于读者理解研究的逻辑和进展。在课题及论文中,技术路线图是常见的一部分,甚至是一个类似心脏一样的中枢器...

25年信息系统项目管理师考试第2批论文题目写作建议思路框架

25年信息系统项目管理师考试第2批论文题目写作建议思路框架--马军老师

微信购物应尽快纳入法律框架(微信购物管辖)

符向军近日,甘肃省工商行政管理局发布《2016年上半年信息分析报告》。报告显示,微信网购纠纷迅猛增长,网络购物投诉呈上升趋势。投诉的主要问题有出售的商品质量不过关、消费者通过微信付款后对方不发货、购买...

泛珠三角区域网络媒体与腾讯微信签署《战略合作框架协议》

新海南客户端、南海网7月14日消息(记者任桐)7月14日上午,参加第四届泛珠三角区域合作网络媒体论坛的区域网络媒体负责人及嘉宾一行到腾讯微信总部座谈交流,并签署《战略合作框架协议》(以下简称《框架协...

离线使用、植入微信-看乐心Mambo手环如何打破框架

从2014年开始智能手环就成功进入人们的生活,至今已经演变出数据监测、信息推送、心率监测等诸多五花八门的功能,人们选择智能手环并不指望其能够改变身体健康情况,更多的是通过数据来正视自身运动情况和身体健...

微信私域电商运营策略与框架(微信私域怎么做)

...

华专网络:如何零基础制作一个网站出来?

#如何零基础制作一个网站出来?#你是不是觉得网站建设很复杂,觉得自己是小白,需求不明确、流程搞不懂、怕被外包公司坑……这些问题我都懂!今天华专网络就用大白话给你捋清楚建站的全流程,让你轻松get网站制...

WAIC2024丨明日上午9点,不见不散!共同探讨智能社会与全球治理框架

大咖云集,硕果闪耀WAIC2024世界人工智能大会智能社会论坛将于7月5日9:00-12:00与你相约直播间WAIC2024上海杨浦同济大学哔哩哔哩多平台同步直播探讨智能社会与全球治理框架WAIC...

约基奇:森林狼换来戈贝尔时大家都在嘲笑 他们的阵容框架很不错

直播吧5月4日讯西部季后赛半决赛,掘金将迎战森林狼,约基奇赛前接受采访。约基奇说道:“当蒂姆-康纳利(森林狼总经理、前掘金总经理&曾选中约基奇)做了那笔交易(换来戈贝尔)时,每个人都在嘲笑他...

视频号带货为什么一个流量都没有?顶级分析框架送给你

视频号带货为什么一个流量都没有?遇到问题,一定是步步来分析内容,视频号带货一个流量都没有,用另外一个意思来讲,就可以说是零播放。为什么视频号带货一个流量都没有?跟你说再多,都不如来个分析框架。1、是否...

取消回复欢迎 发表评论: