单元测试
单元测试是用来对一个模块,一个函数或者一个类来进行正确性检验的测试工作;
eg:对函数abs()进行单元测试:
1.输入一个0 or 正数,期待返回值与输入相同
2.输入负数,期待返回值与输入相反
3.输入非数字类型,期待抛出异常 typeError
当 所有结果都符号期待情况 ,就认为通过测试.
把上面的测试用例放在一个测试模块中,就是一个完整的单元测试.python可以使用标准库unittest模块
- 测试方法必须是以test开头,不然被执行
- 每一类测试都需要编写一个test_xxx()方法.
- unittest.TestCase提供了很多内置的条件判断,调用这些方法就可以断言输出是否是我们所期望的.
常用的断言:
self.assertEqual(a,b) # 断言a和b结果是否相等 是则通过; with self.assertRaises(KeyError): # 断言下面执行的代码能否触发抛出KeyError的异常 能则通过 value = d['empty']
运行单元测试
直接在最后加上两行代码,然后直接运行python xxx_test.py
if __name__="__main__": unittest.main()
在命令行运行单元测试 python -m unittest xxx_test 推荐
eg:
student.py
"""待测试用例""" class Student(object): def __init__(self, name, score): self.name = name self.score = score def get_grade(self): if self.score > 100: raise ValueError('Than 100') if self.score < 0: raise ValueError('less 0') if self.score >= 80: return 'A' if self.score >= 60: return 'B' return 'C' if __name__ == '__main__': s1 = Student('a',-1) print(s1.get_grade())
test_student.py
""" 测试用例""" import unittest from student import Student class TestStudent(unittest.TestCase): def test_80_to_100(self): """测试分数输入80到100的结果是否正确 取边界值""" # 期待结果是80:A 100:A 正确则测试通过 s1 = Student('Bart', 80) s2 = Student('Lisa', 100) self.assertEqual(s1.get_grade(), 'A') self.assertEqual(s2.get_grade(), 'A') def test_60_to_80(self): """测试分数输入60到80的结果是否正确 取边界值""" # 期待结果是60:B 79:B 正确则测试通过 s1 = Student('Bart', 60) s2 = Student('Lisa', 79) self.assertEqual(s1.get_grade(), 'B') self.assertEqual(s2.get_grade(), 'B') def test_0_to_60(self): """测试分数输入0到60的结果是否正确 取边界值""" # 期待结果是0:C 59:C 正确则测试通过 s1 = Student('Bart', 0) s2 = Student('Lisa', 59) self.assertEqual(s1.get_grade(), 'C') self.assertEqual(s2.get_grade(), 'C') def test_invalid(self): """测试分数输入不在0到100的数字的结果是否正确 取两个特殊值""" # 期待结果是-1:抛出异常 101:抛出异常 正确则测试通过 s1 = Student('Bart', -1) s2 = Student('Lisa', 101) with self.assertRaises(ValueError): s1.get_grade() with self.assertRaises(ValueError): s2.get_grade() if __name__ == '__main__': unittest.main()
setUp 与 tearDown
可以在单元测试中写两个特殊的setUp()
和tearDown()
方法.这两个方法分别在每个调用一个测试方法的前后分别被执行.
场景:测试需要启动一个数据库,这时,可以在setUp()
方法中连接数据库,在tearDown()
方法中关闭数据库,可以避免重复代码.class Testxx(unittest.TestCase): def setUp(self): print('setUp....') def tearDown(self): print('tearDown....')