Python学习笔记_第十六张:测试
先测试后编码
精确的需求说明
现在可以在Python内明确需求,让解释器检查程序是否满足需求,这无疑是个好消息。
测试的四个步骤
- 指出新特性
- 编写特性的骨架代码
- 为特性的骨架代码编写哑代码
- 现在重写代码,使它完成工作
测试工具
- unittest:通用测试框架
- doctest:简单一些的模块,是检查文档用的,但是对于编写单元测试很在行。
doctest
def square(x):
'''
Squares a number and returns the result.
>>> square(2)
4
>>> square(3)
9
'''
return x * x
if __name__ == '__main__':
import doctest, doctest_test
doctest.testmod(doctest_test)
运行结果图
如上,执行doctest_test.py,什么都没发生,但是这是好事,doctest.testmod函数从一个模块读取所有的文档字符串,找出所有看起来像是在交互式解释器中输入的例子的文本,之后检查例子是否符合实际要求。
为了获取更多的信息,可以执行如下:
详细结果
有关doctest的更多信息,请查看库参考(http://python.org/doc/lib/module-doctest.html)。
unittest
尽管doctest简单易用,但是unittest(基于java的流行框架JUnit)则更灵活和强大,利用它可以结构化编写大型且周详的测试集。请参考:http://python.org/doc/lib/module-unittest.html
其他测试工具有pytest和nose
下面是unittest的一个例子
import unittest, my_math
class ProductTestCase(unittest.TestCase):
def testIntegers(self):
for x in xrange(-10, 10):
for y in xrange(-10, 10):
p = my_math.product(x, y)
self.failUnless(p == x * y, 'Integer multiplication failed')
def testFloats(self):
for x in xrange(-10, 10):
for y in xrange(-10, 10):
x = x / 10.0
y = y / 10.0
p = my_math.product(x, y)
self.failUnless(p == x * y, 'Float multiplication failed')
if __name = '__main__':unittest.main()
运行以上代码会出现关键字my_math不存在异常,类似于failUnless其他的方法还有:failIf、failUnlessEqual、failIfEqual等,查看库参考http://python.org/doc/lic/testcase-objests.html获取更多信息。
unittest会区分由异常引发的错误和由调用failUnless等函数导致的错误。
也有针对unittest的GUI。请参见PyUnit(unittest的另一个名字)获取更多信息。
单元测试以外
源代码检查是一种寻找代码中普通错误的方法,有点像但不局限与编译器处理静态语言。
性能分析是查明程序到底有多快的方法
编程有一条黄金法则:“使其工作、使其更好、使其更快”。
使用PyChecker和PyLint检查源代码
PyChecker:jiancha Python源代码、寻找提供的参数不满足函数参数要求等错误的重要工具。
tabnanny:只能检查缩进格式。
PyLint:支持PyChecker的大多数功能和其他功能,可以提示使用的短变量名。
Pychecker安装:
- Pychecker下载地址:http://sourceforge.net/projects/pychecker/
- 进入解压后的文件夹,运行命令python setup.py install
- 在python的安装目录\Scripts下出现pychecker.bat文件,将Scripts目录加到Path环境变量中
PyLint的安装:
pip install pylint
PyLint还需要Logilab Common库,需要从PyLint网站(https://www.pylint.org/)下载。(这步没做)
安装完成后这两个工具就可以作为命令行脚本或者作为Python模块导入,名字为pychecker和pylint。
导入pychecker.checker后,它会检查之后的代码(包括导入的模块)
pylint.lint有一个叫Run的非文档记型函数(带有命令行选项的函数)可以在pylint脚本本身中使用。
没有break、raise或者return语句的while True,一般情况下是无法检测的。
性能分析
标准库中已经包含了一个叫做profile的分析模块(还有一个更快的嵌入式c语言版本,叫hotshot)。使用分析程序非常简单,只要使用字符串参数调用它的run方法就行。
>>> import profile
>>> from my_math import product
>>> profile.run('product(1, 2)')
在Linux的某些发布版本中可能需要安装单独的包让profile模块可以工作。
如果用文件名设置了第二个参数,分析结果会保存在文件中,可以使用pstats模块检查结果。
>>> import pstats
>>> p = pstats.Stats('file_name')
标准库中还包括一个timeit模块,它是测定Python小代码段运行时间的简单方法。可以参考http://python.org/doc/lib/module-timeit.html