第16章 测试基础
1.先测试再编码
为程序的各个部分编写测试很重要(单元测试)。
“测试一点点,编写一点点”。
1.准确的需求说明
有爱阐述程序的目标,可编写需求说明。
2.做好应对变化的准备
3.测试四步曲
1.确定要实现的功能,记录下来,为之编写测试
2.编写实现功能的框架代码,让程序能够运行,但测试仍无法通过,确保代码不正确时,测试能够报错。
3.编写让测试能通过的代码,无需实现全部,只要能通过测试即可。
4.改进(重构)代码以全面而准确地实现所需的功能,同时确保测试能通过。
2.测试工具
有2个模块可帮助自动完成测试过程。
unittest:通用的测试框架
doctest:为检查文档设计的,也可用来单元测试
1.doctest
实例:
def square(x):
'''
计算平方并返回结果
>>> square(2)
4
>>> square(3)
9
'''
return x ** x
if __name__ == '__main__':
import doctest, my_math
doctest.testmod(my_math)
保存为my_math.py
然后在命令行运行 python my_math.py
什么都不会输出。
使用 python my_math.py -v
输出详细信息
2.unittest
实例:
#使用unittest测试 my_math
import unittest, my_math
class ProductTestCase(unittest.TestCase):
def test_integers(self):
for x in range(-10, 10):
for y in range(-10, 10):
p = my_math.product(x, y)
self.assertEqual(p, x * y, 'Integer multiplication failed')
def test_float(self):
for x in range(-10, 10):
for y in range(-10, 10):
x = x / 10
y = y / 10
p = my_math.product(x, y)
self.assertEqual(p, x * y, 'Float multiplication failed')
if __name__ == '__main__': unittest.main()
#被测试的my_math 模块
def product(x, y):
#这句是故意出错来看看测试是不是有用
if x == 7 and y == 9:
return 'An insidious bug has surfaced!'
return x * y
3. 超越单元测试
1.使用PyChecker和PyLint检查源代码
PyChecker是检查python源代码的工具,
PyLint支持PyChecker的大部分功能,还有其他功能,如变量名是否规范。。。
由于PyChecker有很多年没有更新了,所以就使用PyLint
直接使用 pip install pylint 安装
使用PyLint 检查文件时,将模块(或包)名作为参数:
pylint module
实例:
#使用模块subprocess调用外部检查器
import unittest, my_math
from subprocess import Popen, PIPE
class ProductTestCase(unittest.TestCase):
#测试.
def test_integers(self):
for x in range(-10, 10):
for y in range(-10, 10):
p = my_math.product(x, y)
self.assertEqual(p, x * y, 'Integer multiplication failed')
def test_float(self):
for x in range(-10, 10):
for y in range(-10, 10):
x = x / 10
y = y / 10
p = my_math.product(x, y)
self.assertEqual(p, x * y, 'Float multiplication failed')
def test_with_PyLint(self):
cmd = 'pylint', '-rn', 'my_math'
pylint = Popen(cmd,stdout=PIPE, stderr=PIPE)
self.assertEqual(pylint.stdout.read(), '')
if __name__ == '__main__': unittest.main()
#不知道为什么用不了这个方法,所以就直接在命令行用pylint module 了
2.性能分析
通常不需要过分追求速度。但是速度很慢时,就必须优化。性能分析帮助找到运行慢的地方。
标准库模块profile(C语言版本cProfile)
使用时只需调用其方法run并提供一个字符串参数。
>>> import cProfile
>>> from my_math import product
>>> cProfile.run('product(1, 2)')
将输出函数调用次数和花费时间
如果向run提供第二个参数('my_math.profile')将分析结果保存到这个文件中,然后就可以使用模块psats分析结果