用Python测试框架简化测试

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

Python测试框架最近出现了行业级的Python测试框架,这意味着Python测试可以编写得更简洁、更统一,能够产生更好的结果报告。本文介绍比较先进的测试框架并讨论它们的基本特性。Python测试领域的蛮荒时代结束了。仅仅在几年前,几乎每个用Python构建的项目在编写和运行测试方面都采用自己的习惯做法。但是现在,这种混乱局面终于要结束了。社区中已经出现了几种出色的测试解决方案,它们为数百个流行的项目的测试套件提供约定和通用标准。本文是三篇系列文章的第一篇,本系列要介绍新的测试框架。在本文中,将介绍三种流行的测试框架,讨论新一代工具鼓励的简单测试风格。第二篇文章发现和选择测试讨论更大的问题:这些框架如何自动地发现和分类项目的测试。最后一篇文章用Python测试框架生成测试报告讨论这些框架为查看测试结果提供的强大特性。通过学习这三种框架的通用习惯做法,您不但可以更好地理解其他程序员编写的Python包,还可以为自己的应用程序构建优雅、强大的测试套件。候选框架:三种Python测试框架有三种Python测试框架是目前使用最为广泛的。下面按时间次序简要介绍它们:zope.testing通常,从事Zope项目的开发人员就像是早期的拓荒者。他们需要以一种统一的方式在大型代码基上发现和运行测试,为此开发了zope.testing包,这个包现在仍然得到广泛使用。zope.testing包只支持unittest和doctest等传统Python测试风格,而不支持更现代的框架支持的简化风格。但是,它提供一个强大的分层系统,在这种系统中包含测试的目录可以依赖于通用的设置代码,设置代码为层(而不是每个测试)创建一个运行测试所需的环境。py.test2004年,HolgerKrekel把他的std包改名为‘py’,因为原来的名称常常与Python附带的标准库混淆。尽管这个包包含另外几个子包,但是现在最著名的部分只有它的py.test框架。py.test框架建立了Python测试的新标准,目前许多开发人员都采用这种标准。它为编写测试提供了优雅的符合Python风格的习惯做法,让开发人员能够以非常紧凑的风格编写测试套件。nosenose项目是于2005年发布的,也就是py.test改名后的一年。它是由JasonPellerin编写的,支持与py.test相同的测试习惯做法,但是这个包更容易安装和维护。尽管py.test在某些方面有所进步,目前也很容易安装,但是nose仍然保持了易用性方面的声誉。在Python大会上,常常会看到开发人员穿着黑色T恤衫,上面印着nosetests命令,后面是表示测试成功的点号。有意思的是,随着nose的发展,在项目邮件列表上常常看到开发人员向项目负责人询问他们的项目什么时候可以转换到nose。在这三种框架中,nose看起来会成为标准,py.test的用户群比较小,但是很忠诚,zope.testing只在基于Zope框架的项目中受欢迎。但是,这三种框架都得到积极的维护,各有一些独特的特性。建议您了解它们的特性和差异,选择适合自己项目的框架。测试演化py.test框架接受普通的Python函数作为测试,而不要求把测试放在更大更重型的测试类中,这开启了Python测试的新时代。因为nose框架支持相同的习惯做法,所以这些模式很可能越来越流行。假设希望检查Python真假值True和False是否真的等于布尔数字1和0。py.test或nose接受并运行以下代码行,作为回答此问题的有效测试:#test_new.py-simpletestsfunctionsdeftestTrue(self):assertTrue==1deftestFalse(self):assertFalse==0为了体会以上示例的简单性,可以对比过去的Python测试文档中复杂的示例测试,比如:#test_old.py-TheoldwayofdoingthingsimportunittestclassTruthTest(unittest.TestCase):deftestTrue(self):assertTrue==1deftestFalse(self):assertFalse==0if__name__=='__main__':unittest.main()看到了吗?这么多代码只是为了支持两行测试代码!首先,代码需要一个import语句,这与要测试的代码完全无关,因为测试本身简单地忽略模块,只使用内置的Python值,比如True和False。另外,要创建一个类,但是它不支持或增强测试,因为测试实际上没有使用它们的self参数做任何事情。最后,需要两行固定不变的代码,这样才能从命令行运行这个测试。有使用unittest经验的用户可能认为,上面的示例应该使用TruthTest类从TestCase类继承的测试方法。例如,他们会建议使用assertEqual(),而不是手工测试是否相等的assert语句,在这种情况下测试会使用self而不是忽略它:#alternateversionoftheTestTruemethod...deftestTrue(self):self.assertEqual(True,1)...对这个建议有三条反对意见。首先,调用方法会影响可读性。尽管assertEqual()方法名能够表明要测试两个值是否相等,但是代码看起来仍然不像是比较,对于熟悉Python语言的开发人员,不如Python==操作符那么明确。第二,正如在本系列的第三篇文章中将看到的,新的测试框架现在知道如何检查assert语句,从而查明造成测试失败的条件,这意味着简单的assert语句现在能够产生有意义的测试失败消息,它提供的信息与调用assertEqual()等老方法的结果差不多。最后,即使assertEqual()仍然是必要的,但是从测试模块导入这个函数(而不是通过类继承让函数可用)肯定更简单,更符合Python的风格。实际上,在下面会看到,当py.test和nose要提供更多用来支持测试的例程时,它们只需把这些例程定义为函数,然后用户可以把这些函数导入自己的代码。当然,如果作者确实需要通过例程缓存状态,以便以后在测试用例中使用,unittest子类仍然是有意义的,py.test和nose完全支持它们。另外,目前许多Python测试编写为Python标准库支持的doctest,它们不需要使用函数或类:DoctestForTheAboveExample-----------------------------ThetruthvaluesinPython,namedTrueandFalse,areequivalenttotheBooleannumbersoneandzero.True==1TrueFalse==0True但是,如果程序员希望编写简单的测试代码,不愿意考虑doctest涉及的乱七八糟的东西,那么测试函数是很好的方法。总之,测试函数可以极大地增强编写测试的简便性。程序员不需要记住、重写或复制以前编写的测试代码,新的约定让Python程序员能够像编写一般Python代码一样编写测试:只需打开一个空文件,然后输入!框架特有的约定py.test和nose框架都提供特殊的例程,这些例程可以简化测试的编写。可以认为它们分别提供一种方便的测试“方言”,可以用这些“方言”编写测试。这会简化测试的编写并减少错误,还会使测试更简短、可读性更好。但是,使用这些例程还会导致一个重要的后果:您的测试与提供函数的框架捆绑在一起了,丧失了兼容性。因此,要权衡考虑方便性和兼容性。如果只使用笨拙的标准Pythonunittest模块从头编写所有测试,那么它们能够在任何测试框架中运行。更进一步,如果采用简单的做法编写测试函数(如上所述),那么测试至少能够在py.test和nose中运行。但是,如果开始使用某个测试框架特有的特性,那么如果以后另一个框架开发出了新的重要特性,您决定进行框架迁移,就必须重写测试。py.test和nose都为TestCase的assertRaises()方法提供了替代品。py.test提供的版本比较新颖,它也可以接受要执行的字符串,这更强大,因为可以测试引发异常的表达式,而不只是函数调用:#conveniences.pyimportmathimportpy.testpy.test.raises(OverflowError,math.log,0)py.test.raises(ValueError,math.sqrt,-1)py.test.raises(ZeroDivisionError,1/0)importnose.toolsnose.tools.assert_raises(OverflowError,math.log,0)nose.tools.assert_raises(ValueError,math.sqrt,-1)#Noequivalentforthirdexample!但是,除了都能够测试异常之外,这两种框架的差异就比较大了。py.test只提供一个简便函数,它用来判断特定调用是否会触发DeprecationWarning:py.test.deprecated_call(my.old.function,arg1,arg2)另一方面,nose提供非常丰富的断言函数,适用于希望避免assert语句和需要进行比较复杂的测试的情况。详细信息请参考它的文档,下面列出nose提供的断言函数:#nose.toolssupportfunctionsforwritingtestsassert_almost_equal(first,second,places=7,msg=None)assert_almost_equals(first,second,places=7,msg=None)assert_equal(first,second,msg=None)assert_equals(first,second,msg=None)assert_false(expr,msg=None)assert_not_almost_equal(first,second,places=7,msg=None)assert_not_almost_equals(first,second,places=7,msg=None)assert_not_equal(first,second,msg=None)assert_not_equals(first,second,msg=None)assert_true(expr,msg=None)eq_(a,b,msg=None)ok_(expr,msg=None)在处理浮点数时,如果希望测试能够灵活地对待Python实现,允许对浮点数的处理有细小的误差,那么上面检查近似值的例程尤其有意义。分布式测试目前,测试的运行频率越来越高了。许多团队已经采用了连续测试,也就是对团队版本控制系统的每次签入(check-in)都要运行项目测试。随着测试驱动开发方法越来越流行,许多开发人员在开始编写新模块的代码之前先为模块编写和运行测试。如果测试的运行时间很长,就会严重影响开发人员的生产力。因此,用尽可能多的计算能力运行测试是很有益处的。对于小规模项目,这可能意味着使用计算机的所有CPU核运行多个测试进程。对于更大的项目,要配置完整的测试计算机群,要么使用专用服务器并行地运行测试,要么使用所有开发人员工作站的空闲时间。在并行和分布式测试方面,本文讨论的三种测试框架有非常显著的差异:zope.testing命令行有一个-j选项,它指定应该启动多个测试进程,而不是在同一进程中执行所有测试。因为每个进程可以在不同的CPU核上运行,所以如果在有四个CPU的计算机上运行-j4,就可以同时用四个CPU运行测试。nose项目报告说,他们已经把对并行测试的支持提交到项目trunk,但是一般用户要等到下一个版本才能试用这个特性。py.test工具支持一个多处理选项(-n),可以像zope.t

1 / 7
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功