unittest用例模块测试
空闲时间,回过头来再看看python基础的东西,今天回味一下unittest用例测试。 首先创建一个测试模块yooutk_math.py
#coding: UTF-8
class Math:
def add(self,num_a,num_b):
return num_a + num_b
def sub(self,num_a,num_b):
return num_a - num_b
接下来定义测试类:
#coding: UTF-8
from yootk import Math
import unittest
class TestMath(unittest.TestCase):
@classmethod
def setUpClass(self):
print("'[unittest]程序测试开始")
@classmethod
def tearDownClass(self):
print('[unittest]程序测试结束')
@classmethod
def SetUp(self):
print("'[%s]测试开始。‘" % self.id())
def tearDown(self):
print('[%s]测试结束。' % self.id())
def test_add(self):
self.assertEqual(Math().add(7,2),9)
def test_sub(self):
self.assertEqual(Math().sub(1,7),-6)
if __name__ == "__main__":
unittest.main()
unitest
python自带的测试框架,
一、一般的使用流程:
1、从unitest.TestCase派生一个子类
2、定义setUp和tearDown方法,分别在执行前和执行后执行
3、在类中定义test_头的方法
4、通过unittest.main()函数来启动测试
二:跳过单个testcase和testclass的方法
在unittest中也支持类似junit中的跳过单个测试case或者测试class的方法,如下:
@unittest.skip(reason)
无条件的跳过被修饰的testcase或者testclass,reason描述为何跳过该测试,为一个字符串;
@unittest.skipIf(condition,reason)
如果条件condition为真,则跳过该testcase或者testclass;
@unittest.skipUnless(condition,reason)
除非条件condition为真,否则跳过被修饰的testcase或者testclass;
@unittest.expectedFailure
标记测试为一个预期失败的测试,但不会作为失败测试统计在结果中;
三:断言
在unittest中用断言来判断是pass还是fail,常见的断言方法如下:
assertEqual(a, b) a == b
assertNotEqual(a, b) a != b
assertTrue(x) bool(x) is True
assertFalse(x) bool(x) is False
assertIs(a, b) a is b
assertIsNot(a, b) a is not b
assertIsNone(x) x is None
assertIsNotNone(x) x is not None
assertIn(a, b) a in b
assertNotIn(a, b) a not in b
assertIsInstance(a, b) isinstance(a, b)
assertNotIsInstance(a, b) not isinstance(a, b)
assertAlmostEqual(a, b) round(a-b, 7) == 0
assertNotAlmostEqual(a, b) round(a-b, 7) != 0
assertGreater(a, b) a > b 2.7
assertGreaterEqual(a, b) a >= b 2.7
assertLess(a, b) a < b 2.7
assertLessEqual(a, b) a <= b 2.7
assertRegexpMatches(s, re) regex.search(s) 2.7
assertNotRegexpMatches(s, re) not regex.search(s) 2.7
assertItemsEqual(a, b) sorted(a) == sorted(b) and works with unhashable objs 2.7
assertDictContainsSubset(a, b) all the key/value pairs in a exist in b 2.7
assertMultiLineEqual(a, b) strings 2.7
assertSequenceEqual(a, b) sequences 2.7
assertListEqual(a, b) lists 2.7
assertTupleEqual(a, b) tuples 2.7
assertSetEqual(a, b) sets or frozensets 2.7
assertDictEqual(a, b) dicts 2.7
assertMultiLineEqual(a, b) strings 2.7
assertSequenceEqual(a, b) sequences 2.7
assertListEqual(a, b) lists 2.7
assertTupleEqual(a, b) tuples 2.7
assertSetEqual(a, b) sets or frozensets 2.7
assertDictEqual(a, b) dicts 2.7
其他断言方法请查阅官方文档
四:组成测试套件
1.添加数量较少的测试case,可以用如下方法:
suite=unittest.Testsuite()
suite.addTest(testclass(testcase))
这里testclass为测试类的名称,testcase为该测试类下的测试case的名称,为字符串。
2.对于有多个测试类的情况,可以用如下方法:
def createsuite(): testunit=unittest.TestSuite() discover=unittest.defaultTestLoader.discover(testdir,pattern='test_*.py', top_level_dir=None) print discover for test_suite in discover: for testsuit in test_suite: testunit.addTest(testsuit) return testunit alltestnames = createsuite()
如此便可以将一个目录下多个测试文件中的testcase导入。
五、setUP、tearDown扩展
1、当类里面定义了 setUp() 方法的时候,测试程序会在执行每条测试项前先调用此方法;同样地,在全部测试项执行完毕后,tearDown() 方法也会被调用。
2、如果我们想全程只调用一次 setUp/tearDown 该怎么办呢?就是用 setUpClass() 和 tearDownClass() 类方法啦。注意使用这两个方法的时候一定要用 @classmethod 装饰器装饰起来:
lang:python import unittest classsimple_test(unittest.TestCase): @classmethoddefsetUpClass(self): self.foo = list(range(10)) deftest_1st(self): self.assertEqual(self.foo.pop(),9) deftest_2nd(self): self.assertEqual(self.foo.pop(),8) if __name__ == '__main__': unittest.main()
这个例子里我们使用了一个类级别的 setUpClass() 类方法,并修改了第二次 pop() 调用的预期返回值。运行结果显示依然是全部通过,即说明这次在全部测试项被调用前只调用了一次 setUpClass()。
3、再往上一级,我们希望在整个文件级别上只调用一次 setUp/tearDown,这时候就要用 setUpModule() 和tearDownModule() 这两个函数了,注意是函数,与 TestCase 类同级:
lang:python import unittest defsetUpModule(): passclasssimple_test(inittest.TestCase): ...
一般 assert*() 方法如果抛出了未被捕获的异常,那么这条测试用例会被记为 fail,测试继续进行。但如果异常发生在 setUp() 里,就会认为测试程序自身存在错误,后面的测试用例和 tearDown() 都不会再执行。即,tearDown()仅在 setUp() 成功执行的情况下才会执行,并一定会被执行。
最后,这两个方法的默认实现都是什么都不做(只有一句 pass),所以覆盖的时候直接写新内容就可以了,不必再调用父类的此方法。
学而不思则罔,思而不学则殆