# 错误 异常 调试 测试
## 调试
### 单元测试 unittest模块
> 作用 :确保开发/修改后 一个程序模块的行为符合我们设计的测试用例
# mydict_test.py
class TestDict(unittest.TestCase):
def test_init(self):
d = Dict(a=1, b='test')
self.assertEquals(d.a, 1)
self.assertEquals(d.b, 'test')
self.assertTrue(isinstance(d, dict))
def test_key(self):
d = Dict()
d['key'] = 'value'
self.assertEquals(d.key, 'value')
def test_attr(self):
d = Dict()
d.key = 'value'
self.assertTrue('key' in d)
self.assertEquals(d['key'], 'value')
def test_keyerror(self):
d = Dict()
with self.assertRaises(KeyError):
value = d['empty']
def test_attrerror(self):
d = Dict()
with self.assertRaises(AttributeError):
value = d.empty
def setUp(self): # 每调用一个测试方法前执行 比如连接数据库
print 'setUp...'
def tearDown(self): # 后执行
print 'tearDown...'
if __name__ == '__main__':
unittest.main()
运行测试脚本
python mydict_test.py
另一种更常见的方法是在命令行通过参
python -m unittest mydict_test # 可以批量运行很多单元测试
test开头的方法是测试方法
判断条件:
assertEquals 是否相等
assertRaises 异常类型判断
> note: 测试用例要覆盖常用的输入组合 边界条件和异常;测试程序要简单 否则测试代码本身就可能有bug;测试通过也可能有bug 但不通过肯定有bug
### 单步调试 pdb
python -m pdb err.py
l #查看代码
n #单步执行
p 变量名 #查看变量
q 结束调试
pdb.set_trace() # 设置断点 运行到这里会自动暂停(不需要命令行指定pdb)
c 继续运行
### 日志 logging
logging.basicConfig(level=logging.INFO)
logging.info()
debug info warning error # level 向后兼容
### 断言 python -o xxx.py 关闭断言
> 想打印变量看看是否符合预期? 用断言
> 如果断言失败 抛出 *AssertionError* 异常
assert n != 0, 'n is zero!'
assert 条件(应该为True),错误信息
## 异常处理
### 各种错误
1. 程序错误 是bug (只能修改程序)
2. 用户输入等因素造成的错误 (可以做相应检查处理)
3. 磁盘满了 网络断了等无法预测的错误 称之为**异常** (可以做相应处理)
所有错误类型都继承自 BaseException
try:
pass
except IndexError,e:
pass
except Exception,e:
logging.exception(3) # 可以记录错误信息
else: # 没有发生错误是会执行
pass
finally: # 无聊是否有错误 都要执行
pass
发生错误后根据调用栈 一直向上抛出异常 可以在上层捕获
如果没有捕获解释器就会打印错误信息并退出
当程序/数据不符合预期的时候 你可以选择**抛出异常**
raise FooError('invalid value: %s' % s) # class FooError(StandardError) 自定义错误
### 内置类型错误
* StandardError
* ValueError
* TypeError