李落 2010年11月25日 星期四 18:02 | 3408次浏览 | 0条评论
清风老师提到的第2点——单元测试,总结一下。
其实我的主要目的是想Django的单元测试,由于Django使用了Python的标准模块doctest和unittest,所以我觉得有必要了解一下Python的单元测试。另外还有就是比较欣赏的PyLons框架的单元测试内容。
1 、 doctest 框架
在Python中doctest就是把程序中的docstring作为范例来运行的一个框架,docstring可以由普通部分和执行部分组成,普通部分等同于原来的文字说明,执行部分由'>>>'(python shell提示符)或'...'提示符区分。程序员可以通过手工编写可预测的执行部分,也可以通过拷贝复制python交互式shell中的输入和输出简单的形成执行部分,doctest搜寻存在与各个模块,类和函数中的docstring,把每个可执行部分当成一次范例运行,再把实际运行值和期望值的对照作为一次运行结果。
我大致看了一下doctest,感觉还是比较容易上手的,另外还有一个优点就是可以很方便的生成文档。由于比较简单,就不多作介绍,具体可参考:
http://docs.python.org/library/doctest.html
2 、 unittest(PyUnit 框架 )
unittest模块,也就是PyUnit(全称:The Python unit testing framework)是Kent Beck和Erich Gamma这两位聪明的家伙所设计的 JUnit 的Python版本,自从Python2.1版本以后,PyUnit已经被加入到Python标准库(也就是unittest)。
简单实例:
import unittest # 导入单元测试模块
from demo import Demo
class DemoTests(unittest.TestCase): # 由TestCase派生类
def setUp(self): # 开始单元测试准备工作,初始化环境
pass
def tearDown(self): # 完成单元测试收尾,清除环境
pass
def testAdd(self): # 完成单元测试收尾,清除环境
pass
def suite():
suite = unittest.TestSuite()
suite.addTest(Demo('testAdd'))
return suite
if __name__ == "__main__":
unittest.TextTestRunner().run(suite())
参考:
http://docs.python.org/library/unittest.html
http://pyunit.sourceforge.net/pyunit_cn.html
当然了,Python还有一个叫作doctest的模块,可以
Django中的单元测试有2种:Doctests、Unit tests,分别对应Python标准库doctest和unittest,可想而知其用法也是大同小异。
1 、 Doctests
对于一个Django应用程序,它会在应用程序目录下的models.py和tests.py两个文件去寻找可运行的doctests。需要注意的是,在models.py的doctest当中,test runner自己会建立单独的测试用数据库。也就是说,任何涉及数据库访问的测试——如创建并保存了模型的实例——都不会对你实际使用的数据库产生影响,因为测试时会使用它自己创建的单独的数据库。同时,在doctests运行期间,你实际使用的数据库也不会刷新。所以,如果你的测试依赖于一些特定的状态,那么你就应该考虑显式操作你实际使用的数据库,或者读取一个fixture(伪造的可用数据)。(后面会有关于fixtures更详细的介绍。)请注意,要使用此功能,作为数据库用户的Django必须要有可 CREATE DATABASE 的权限。
如果感觉 doctest 更显得 “pythonic”(它的设计目的本来就是使编写测试尽可能的简单化,而不用专门去写一些类,函数之类的东西。你只需要像写注释一样把测试功能写在docstrings里就可以了。这种做法的一个额外好处,就是测试可以直接作为文档的一部分)或者如果是刚刚接触测试工作的人,那么使用doctests会更快地入门单元测试。
关于doctest细节,同样可参考 http://docs.python.org/library/doctest.html
2 、 Unit tests
相较于doctests,unit tests使用了另外一种方式定义测试,一种基于“类”的实现。像doctests一样,对于一个Django应用程序,test runner会在两个地方寻找unit tests:应用程序目录下的models.py和tests.py。运行测试 时,测试工具默认的行为是在 models.py 和 tests.py 中找到所有的测试用例( unittest.TestCase 的所有子类),然后自动将这些测试用例构建成一个测试集,然后开始跑这个测试集。
如果在 models.py 或 tests.py 中定义了一个名为 suite() 的函数,那么Django的test runner将会调用此函数来构建本模块的测试集。这也是被 推荐使用 的测试用例的组织方法。
关于unit tests细节,参考 http://docs.python.org/library/unittest.html
进行单元测试时,可以选择 doctests 或者 unit tests 中的 1 种或者同时使用 2 种,取决于个人或者团队中的喜好和习惯。
运行测试
当写好了测试用例后,你可以使用项目的 manage.py 工具中的 test 子命令来运行你写的这些测试:
manage.py test
默认情况下,这将运行列在 INSTALLED_APPS 中的所有应用的全部测试。如果仅仅是想运行个别应用的测试,那就把它的应用名作为参数写在命令后。比如, INSTALLED_APPS 中包含了 'myproject.polls' 和 'myproject.animals' 可以通过下面的命令来运行 myproject.animals 这个应用中的所有测试:
manage.py test animals
注意,使用的是 animals ,而不是 myproject.animals 。
只运行某个应用中的个别测试用例。要实现这点,你只需要在命令中,在应用名后接着指明测试用例的名字:
manage.py test animals.AnimalTestCase
更精细地指明只运行某个测试用例中的 一个 测试方法,紧跟着测试用例名后写上方法名:
manage.py test animals.AnimalTestCase.testFluffyAnimals
如果使用的是doctests,可以使用同样的方法来运行个别测试。Django会将命令行中的参数,看成是希望测试的相关的方法或类。如果在 models.py 或者 tests.py 中有具备doctest的函数或类,你可以在命令行中指定运行这些测试,方法和前面介绍过的一样:
manage.py test animals.classify
如果你需要运行某个类中的某个方法的doctest,只需要把方法名写在类名之后:
manage.py test animals.classifier.run
如果使用了 __test__ 字典来专门保存某个模块的doctests,那么对于定义在 models.py 和 tests.py 中的这些字典来说,Django将会把命令中的那些标识作为这些字典的键来处理。
退出测试
在测试正在进行时按下了 Ctrl-C ,test runner会等到当前测试完成,然后再退出。当你正常友好地退出后,test runner会给出测试结果报告,包括运行了多少个测试,其中错误的有多少,失败有多少,失败的细节信息,以及删除了哪些测试用数据库。因为,在忘记使用 --failfast 选项的情况下,使用 Ctrl-C 友好地退出测试是直接有用的,特别当一些测试因为意外情况而失败,你在整个测试未结束之前就想看到详细的失败输出信息。
如果想马上终止测试,等不到当前测试跑完了,那么你可以连接按两次 Ctrl-C ,不过,这种做法比较暴力。因为这样做看不到已经跑完的测试的详细报告,同时那些在测试中创建的数据库也还没有删除。
*另外需要注意的是,在测试时一定要把 DEBUG设置为False。
其他像模拟测试客户端、测试用例以及email发送等内容可查阅 http://docs.djangoproject.com/en/1.2/topics/testing/
Pylons需要安装nose,进行单元测试是比较简单的。
官方文档 http://pylonshq.com/docs/en/1.0/testing/
有看到啄木鸟社区的文章 http://wiki.woodpecker.org.cn/moin/PyLons/UnitTest
Webtest模块 http://pylonshq.com/docs/en/1.0/thirdparty/webtest/
软件的测试是一件非常乏味的事情,在测试别人编写的软件时尤其如此,程序员通常都只对编写代码感兴趣,而不喜欢文档编写和软件测试这类"没有创新"的工作。既然如此,为什么不让程序员在编写软件时自己加入一些用于测试的代码,使测试过程自动化呢?在软件工程中,这一技术称为自动单元测试。测试是一个贯穿于整个开发过程的连续过程,从某个意义上说,软件开发的过程实际上就是测试过程。正如Martin Fowler所说的"在你不知道如何测试代码之前,就不该编写程序。而一旦你完成了程序,测试代码也应该完成。除非测试成功,你不能认为你编写出了可以工作的程序。测试最基本的原理就是比较预期结果是否与实际执行结果相同,如果相同则测试成功,否则测试失败。
Zeuux © 2024
京ICP备05028076号
暂时没有评论