当前位置: 首页 > 后端技术 > Python

浅谈Python的单元测试框架(二):nose及其继承者nose2

时间:2023-03-26 12:52:27 Python

作者:HelloGitHub-Prodesire本文涉及的示例代码已更新至HelloGitHub-Team仓库1.Nosenose是第三方单元测试框架,它与unittest完全兼容,并声称是一个更好的测试框架。那么nose除了拥有unittest的所有功能外,还有哪些优势呢?1.1用例编写除了编写继承自unittest.TestCase的测试类外,用例编写还可以编写为不继承的测试类。例如下面的形式也会被nose认为是一个测试类:assert'FOO'.isupper()断言不是'Foo'.isupper()@raises(TypeError)deftest_split(self):s='helloworld'asserts.split()==['hello','world']#当分隔符不是字符串时检查s.split是否失败s.split(2)当然,测试类没有继承unittest.TestCase,将无法使用其内置的assertXXX方法,这将导致无法获得更详细的上下文信息。此外,nose还支持将函数定义为测试,这为很多简单的测试场景带来了极大的便利:deftest_upper():assert'foo'.upper()=='FOO'1.2unittest的Usecasediscoveryandexecution支持的使用nose支持案例发现和执行功能。nose支持自动(递归)发现用例:默认情况下会发现当前目录下所有包含test的测试用例,但不包括以_开头的测试用例。使用nosetests命令通过-w参数指定自动发现的目录,-m参数指定测试用例文件、目录、函数、类的命名模式(正则匹配)nosetests-wproject_directory"test_.+》nose也支持指定用例的执行:指定测试模块noseteststest.module指定测试类nosetestsa.test:TestCase指定测试方法nosetestsanother。test:TestCase.test_method指定测试文件路径nosetests/path/to/test/file.py指定测试文件路径+测试类或测试函数(unittest不支持)nosetests/path/to/test/file.py:TestCasenosetests/path/to/test/file.py:TestCase.test_methodnosetests/path/to/test/file.py:test_function1.3测试夹具(Fixtures)nose除了支持定义测试前和清除方法unittest支持,也支持更简单的定义:defsetup_func():"setuptestfixtures"defteardown_fixture():"teardowntestfixtures"@with_setup(setup_func,teardown_func)deftest():"test..."只需定义两个函数来表示pre-和clean-up方法,用nose.tools.with_setup装饰器装饰测试函数,nose就会在执行测试用例前后执行定义的pre-和clean-up函数。1.4子测试/测试生成器nose除了在unittest中支持TestCase.subTest,还支持更强大的子测试编写方式,即测试生成器(Testgenerators),通过yield实现。下面的例子中,定义了一个test_evens测试函数,生成5个子测试check_even:deftest_evens():foriinrange(0,5):yieldcheck_even,i,i*3defcheck_even(n,nn):assertn%2==0ornn%2==0另外,相对于unittest.TestCase.subTest多个子测试只能执行一次测试准备和清理,nose的测试生成器可以支持每个子测试执行一次测试前置和清理,比如:deftest_generator():#...yieldfunc,arg,arg#...@with_setup(setup_func,teardown_func)deffunc(arg):assertsomething_about(arg)1.5插件系统nose比较最大的优势之一unittest的是插件系统,自带很多好用的插件,还有丰富的第三方插件。还有很多事情可以做。其中,内置插件如下:AllModules:收集所有模块中的用例Attrib:标注用例并使用指定标签运行用例Capture:捕获用例的标准输出Collect:快速收集用例Cover:统计代码覆盖率调试:当用例失败时输入pdb调试弃用:将用例标记为已弃用Doctests:运行文档用例失败详细信息:在断言失败时提供上下文信息Isolate:保护用例免受某些副作用捕获日志输出Multiprocess:并行执行用例Prof:使用热点分析器分析Skip:将用例标记为跳过Testid:为每个输出用例名称添加测试IDXunit:以xunit格式输出测试结果,有各种第三方用于生成HTML格式测试报告的nose-htmloutput等库,这里就不一一列举了。得益于nose丰富的插件生态,当nose本身不能完全满足我们的测试需求时,通过安装插件并指定插件提供的具体参数即可非常方便地使用插件。鼻子测试命令行。与unittest相比,自己开发额外的测试逻辑可以节省很多精力。2.nose2nose2是nose的继承者。它们背后的想法是让编写和运行测试用例变得更容易。它们有很多相似之处,比如兼容unittest、支持使用函数作为测试用例、支持子测试、有插件系统等。但是也有很多区别,下面列举一些主要区别:discoveryandloadingtestnose自己实现了模块加载功能,惰性加载测试模块,加载一个执行一个。nose2使用内置的import()导入模块,并首先加载所有模块,然后执行测试用例。nose2不支持nose支持的所有测试用例项目结构。比如下面的测试用例文件的结构在nose2中是不支持的:.`--tests|--more_tests|`--test.py`--test.py测试前置和清除函数级nose支持方法、类、模块和包级测试前置和清除函数nose2不支持包级测试前置测试和清理函数子测试nose2除了支持使用测试生成器实现子测试外,还支持使用参数化测试(Parameterizedtests)实现子测试nose2除了支持测试函数和测试类likenose(不是继承自unittest.TestCase)除了支持参数化测试和测试生成器外,还支持在继承自unittest.TestCase的测试类中使用可配置的nose。希望所有的插件配置都是通过命令行参数来配置的。nose2通过配置文件进行控制,尽量减少命令行参数,让人阅读起来更舒服。有关更多详细信息,请参阅官方文档。3.总结nose和nose2兼容unittest就足以看出他们的目的,就是吸引原本使用unittest的用户来使用。他们是这样!nose和nose2在用例编写、测试夹具、子测试等方面做了改进,让日常用例编写变得更简单、更灵活。同时引入了插件系统,进一步提升了单元测试框架的能力,使得在基本测试功能之上的许多高级功能的实现和共享成为可能。难怪那么多开发者对其情有独钟。《讲解开源项目系列》——让对开源项目感兴趣的人不再害怕,让开源项目的发起者不再孤单。关注我们的文章,您将发现编程的乐趣,使用并发现参与开源项目是多么容易。欢迎留言联系我们,加入我们,让更多人爱上开源,为开源做贡献~