Python调试与测试
调试与断言
调试的一种方法是打印中间结果
print(...)
,但是这么做缺点在于调试完成后必须删除这些
语句
也可以用断言
assert
来代替
print()
。
def foo(s):
n = int(s)
assert n != 0, 'n is zeor!'
return 10 / n
def main():
foo('0')
main()
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
in
5 def main():
6 foo('0')
----> 7 main()
in main()
4 return 10 / n
5 def main():
----> 6 foo('0')
7 main()
in foo(s)
1 def foo(s):
2 n = int(s)
----> 3 assert n != 0, 'n is zeor!'
4 return 10 / n
5 def main():
AssertionError: n is zeor!
返回一个
AssertionError
,用
python -O err.py
来关闭
assert
语句。
logging
logging
不会抛出错误,而且可以输出到文件
import logging
logging.basicConfig(level=logging.INFO)
s = '0'
n = int(s)
logging.info('n = %d' % n) # INFO:root:n = 0
logging
的好处在于,它允许你指定记录信息的级别,有
debug
,
info
,
warning
,
error
等几个级别,当我们指定
level=INFO
时,
logging.debug
就不起作用了。同理,指定
level=WARNING
后,
debug
和
info
就不起作用了。这样一来,你可以放心地输出不同级别的信息,也不用删除,最后统一控制输出哪个级别的信息。
logging
的另一个好处是通过简单的配置,一条语句可以同时输出到不同的地方,比如console和文件。
pdb
pdb
启动方式
python -m pdb err.py
l
查看代码
n
单步执行
p 变量名
查看变量
q
结束调试
pdb.set_trace()
可以用来设置断点
# err.py
import pdb
s = '0'
n = int(s)
pdb.set_trace() # 运行到这里会自动暂停
print(10 / n)
IDE
集成开发环境调试。
虽然用IDE调试起来比较方便,但是最后你会发现,logging才是终极武器。
单元测试
Python中单元测试,需要import
unittest
包,
assertEqual, assertTrue
用法和Java的JUnit基本一样。另一种重要的断言就是期待抛出指定类型的异常
assertRaises
。
运行单元测试,最简单的方法是在
test.py
的最后一行加上
if __name__ == '__main__':
unittest.main()
单元测试中两个特殊的方法
setUp()
和
tearDown()
,分别在每调用一个测试方法的前后被分别执行。例如,可以把数据库的连接与关闭写在这两个方法里。
文档测试
在文档的注释中告诉函数调用者该函数期望的输入和输出。
使用
doctest
包提取文档注释中的代码,用来测试
def abs2(n):
'''
Function to get absolute value of number.
Example:
>>> abs(1)
1
>>> abs(-1)
1
>>> abs(0)
0
'''
return n if n >= 0 else (-n)
if __name__ == '__main__':
import doctest
doctest.testmod()
程序没有任何输出,表明测试通过。
如果对注释文档稍作修改,让测试不通过
def abs2(n):
'''
Function to get absolute value of number.
Example:
>>> abs(1)
1
>>> abs(-1)
2
>>> abs(0)
0
'''
return n if n >= 0 else (-n)
if __name__ == '__main__':
import doctest
doctest.testmod()
**********************************************************************
File "__main__", line 9, in __main__.abs2
Failed example:
abs(-1)
Expected:
2
Got:
1
**********************************************************************
1 items had failures:
1 of 3 in __main__.abs2
***Test Failed*** 1 failures.
doctest非常有用,不但可以用来测试,还可以直接作为示例代码。通过某些文档生成工具,就可以自动把包含doctest的注释提取出来。用户看文档的时候,同时也看到了doctest。