一、介绍
- unittest模块是python进行单元测试的框架;
- unittest的概念:
- test case:测试用例;
- test fixture:测试固定装置(常用的为:用例执行前的操作setUp()和用例执行后的操作tearDown());
- test suite:测试套件,即测试用例的集合,可通过addTest()的方法添加TestCase或通过TestLoader自动添加TestCase;
- test runner:测试执行器,可执行测试套件,也可执行测试用例;
测试执行最简单的方法是使用unittest.main(),它会搜索所有以test开头的测试用例,按ASCII的顺序依次执行;
使用test runner的方法执行执行,它可通过TextTestRunner()方法初始化一个测试执行器,再使用run()函数执行测试套件;
- 使用方法
- 导入unittest模块:import unittest
- 定义一个测试类,继承unittest.TestCase:class ClassName(unittest.TestCase)
- 测试类中每个测试用例的函数,函数名必须要test开头(若函数没有以test开头,则不会执行该条用例)
- 使用unittest.TestCase自带的断言函数assert*判断测试结果是否相同
- 运行主函数
unittest常用工作流程:
TestLoader将测试用例TestCase添加到TestSuite中,TextTestRunner调用TestSuite的run方法,按测试用例的函数名ASCII的排列顺序依次执行用例,最后获得测试结果TestResult。
执行TestCase的过程:先执行setUp()方法,若执行成功,则继续执行测试用例函数,无论测试用例是否执行成功均会执行tearDown()方法;若setUp()方法执行失败,则整个测试项目执行失败;断言的使用
使用assert*方法来检查测试结果,若assert检查失败,则抛出异常,unittest将其作为一个失败用例(即类型为failure); 非assert导致的异常,unittest会将其作为一个错误(即类型为error)。
failure一般表示实际结果与预期结果不一致,表示测试用例执行失败;
error一般表示测试代码有bug;
二、setUp、tearDown与setUpClass、tearDownClass操作
- setUp与tearDown操作:
- def setUp(self):每个测试用例执行之前,使用setUP函数进行初始化,相当于用例执行前的准备工作;
若setUp函数中出现任何异常,则会终止当前测试用例;
除unittest.SkipTest和AssertionError异常外,所有的异常类型均为ERROR;否则为FAIL; - def tearDown(self):每个测试用例执行后,使用tearDown函数进行退出操作,相当于用例执行后的清除工作;
无论测试用例是否执行成功,均会执行tearDown()方法;
若tearDown函数中出现任何异常,除unittest.SkipTest和AssertionError异常外,所有的异常类型均为ERROR;否则为FAIL;
- setUpClass与tearDownClass操作:
- def setUpClass(cls):所有用例执行前,整个类开始执行的函数,必须使用装饰器@classmethod;
- def tearDownClass(cls):所有用例执行结束后,整个类结束执行的函数,必须使用装饰器@classmethod;
class Sample1(unittest.TestCase):
def setUp(self):
print("start")
def tearDown(self):
print("end")
def testAdd(self):
self.assertEqual(2 + 3, 5)
def testReduce(self):
self.assertEqual(7 - 5, 2)
if __name__ == '__main__':
unittest.main()
"""结果
..
start
end
start
end
----------------------------------------------------------------------
Ran 2 tests in 0.001s
OK
"""
class Sample2(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("start")
@classmethod
def tearDownClass(cls):
print("end")
def testAdd(self):
self.assertEqual(2 + 3, 5)
def testReduce(self):
self.assertEqual(7 - 5, 2)
if __name__ == '__main__':
unittest.main()
"""结果
..
start
end
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
"""
三、断言函数介绍
unittest.TestCase自带的有多种断言函数的方法,可用来判断自动化测试的结果是否正确。
- assertEqual(first, second, msg=None):判断first == second;
若相等,则执行成功;若不等,则执行FAIL,同时输出错误信息msg; - assertNotEqual(first, second, msg=None):判断first != second;
- assertAlmostEqual(first, second, places=None, msg=None,delta=None):判断first与second是否约等于,places为小数点后精确的位数,delta为比较两个变量的差值的绝对值是否在delta范围内(places与delta不可同时存在);
- assertNotAlmostEqual(first, second, places=None, msg=None,delta=None):判断first与second是否不约等于;
- assertIs(expr1, expr2, msg=None):判断expr1 is expr2;
- assertIsNot(expr1, expr2, msg=None):判断expr1 is not expr2;
- assertIsNone(obj, msg=None):判断obj is None;
- assertIsNotNone(obj, msg=None):判断obj is not None;
- assertIn(member, container, msg=None):判断member in container;
- assertNotIn(member, container, msg=None):判断member not in container;
- assertIsInstance(obj, cls, msg=None):判断obj是cls实例, isinstance(obj, cls);
- assertNotIsInstance(obj, cls, msg=None):判断obj不是cls的实例, not isinstance(obj, cls);
obj和cls必须是一个类型或一个类型元组 - assertGreater(a, b, msg=None):判断a > b;
- assertGreaterEqual(a, b, msg=None):判断a >= b;
- assertLess(a, b, msg=None):判断a < b;
- assertLessEqual(a, b, msg=None):判断a <= b;
- assertTrue(expr, msg=None):判断bool(expr)为True;
- assertFalse(expr, msg=None):判断bool(expr)为False;
- assertRaises(expected_exception, *args, **kwargs):验证程序应抛出的异常信息
import unittest
class Assertion(unittest.TestCase):
"""断言函数的使用"""
def setUp(self):
self.driver = "0123456789ABC"
def test_01(self):
"""测试用例"""
# 判断两值是否相等
self.assertEqual("0123456789ABC", self.driver, msg="设备相同")
# 判断两值是否约等于
self.assertAlmostEqual(3.141, 3.145, places=2)
self.assertAlmostEqual(3.15, 3.17, delta=0.03)
def tearDown(self):
pass
if __name__ == '__main__':
unittest.main()
四、忽略测试用例操作
可通过unittest.skip装饰器跳过测试用例或测试类
- @unittest.skip(reason):无条件中跳过测试用例或测试类,reason为跳过此测试的原因;
- @unittest.skipIf(condition, reason):当测试条件condintion为true时跳过测试用例或测试类,reason为跳过此测试的原因;
- @unittest.skipUnless(condition, reason):当测试条件condintion为false时跳过测试用例或测试类,reason为跳过此测试的原因;
- @unittest.expectedFailure:表示当测试失败时,这条测试不计入失败的case数目,而是计入expected_failure中;
import unittest
test_version = (0, 1, 2, 3)
class SkipTestCase(unittest.TestCase):
"""忽略测试用例方法"""
@classmethod
def setUpClass(cls):
print("start")
@classmethod
def tearDownClass(cls):
print("end")
def test_01(self):
print("test1")
@unittest.skip('skipping when demo is running')
def test_02(self):
"""程序运行时无条件跳过此条用例"""
print("test2")
@unittest.skipIf(test_version < (5,), "test condition don't support")
def test_03(self):
"""test_version满足小于5时,跳过此用例"""
print("test3")
@unittest.skipUnless(test_version > (5,), "test condition don't support")
def test_04(self):
"""test_version不满足大于5时,跳过此用例"""
print("test4")
@unittest.expectedFailure
def test_05(self):
print(1 > 2)
@unittest.skip("skip this test class")
class SkipTestClass(unittest.TestCase):
"""忽略测试类"""
@classmethod
def setUpClass(cls):
print("start")
@classmethod
def tearDownClass(cls):
print("end")
def test_07(self):
print("test7")
if __name__ == '__main__':
unittest.main()
五、unittest.main()介绍
用于将一个单元测试模块变为可直接运行的测试脚本,main()方法使用TestLoader来搜索所有包含在此模块下的以test命名开头的测试方法,并依次执行用例;
执行用例的默认顺序是按ASCII码的顺序加载测试用例(即0-9,A-Z,a-z)
---此为最简单的执行unittest用例的方法,但若需按自己的顺序执行用例或添加保存测试报告可通过测试套件的方法,见如下。