目录
9, 用例结果校验
10, 跳过用例
11,Test Discovery
12, 加载用例
unittest 官方文档
本篇随笔承接:
Python3+unitest 自动化测试初探(中篇)
Python3+unitest 自动化测试初探(上篇)
9, 用例结果校验
用 unittest 来完成自动化测试时, 结果校验无疑是非常重要的. 用例校验不完整或者校验过于简单, 是无法发现产品的缺陷或 Bug 的. 就自动化测试来而言, 其目的是代替部分手动测试, 将测试人员从繁重重复的功能测试中解放出来. 试想一下, 一些缺少校验或简单校验的用例运行完后通过率即使达到 100%, 这能说明产品或版本没有任何问题吗? 能够增强版本发布的信心吗? unittest 提供了很多断言方法用于测试结果的校验. 常用的断言方法如下:
所有的断言方法都提供一个可选参数 msg, 用于在测试失败时显示.
assertEqual(a, b,msg=None): 校验 a 是否等于 b, 如果相等, 测试通过, 反之则测试失败. msg 为可选参数, 如果传入了该参数, 在测试失败时会打印.
- >>> class assertTest(unittest.TestCase):
- ... pass
- ...
- >>> ast1 = assertTest()
- >>> ast1.assertEqual(1,2,msg="1 is not equal to 2")
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- File "/usr/local/lib/python3.7/unittest/case.py", line 839, in assertEqual
- assertion_func(first, second, msg=msg)
- File "/usr/local/lib/python3.7/unittest/case.py", line 832, in _baseAssertEqual
- raise self.failureException(msg)
- AssertionError: 1 != 2 : 1 is not equal to 2
assertNotEqual(a, b, msg=None): 校验 a 是否不等于 b, 如果不相等, 测试通过. 反之则测试失败.
assertTrue(x,msg=None): 验证 x 是否为 True,x 可以为值或表达式, x 为 True 则测试通过. 反之, 则测试失败, msg 为可选参数, 如果传入了该参数, 在测试失败时会打印.
- >>> ast1.assertTrue(1=2,msg="1=2,False")
- File "<stdin>", line 1
- SyntaxError: keyword can't be an expression
- >>> ast1.assertTrue(1==2,msg="1=2,False")
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- File "/usr/local/lib/python3.7/unittest/case.py", line 692, in assertTrue
- raise self.failureException(msg)
- AssertionError: False is not true : 1=2,False
assertIs(a, b): 判断 a is b 是是否成立. 等价于判断 id(a) == id(b)是否成立, 如果成立, 则测试通过. 反之, 测试失败.
assertIsNone(x): 判断 x 是否为 None. 如果为 None 则测试通过, 反之, 测试失败.
assertIn(a, b): 判断 a 是否在 b 中. 如果在, 则测试通过, 反之, 测试失败.
assertIsInstance(a, b): 判断 a 是否为 b 的实例. 如果是, 则测试通过, 反之, 测试失败.
unittest 还提供了如下方法用于检查异常, 警告, 日志信息. 图片来自 unittest 官方文档.
检查异常, 警告, 日志的使用方法大同小异. 在此不一一说明了, 下面举例说明 assertRaises(exc, fun, *args, **kwds)和 assertRaises(exc, fun, *args, **kwds)的用法.
[ 示例 1 ] assertRaises()的用法
- #coding:utf-8
- '''
- 定义一个除法的函数
- 当 y==0 时, 会抛出错误 ZeroDivisionError
- '''
- import unittest
- def div(x,y):
- return x/y
- # 定义一个测试类 assertTest, 继承于 unittest.TestCase
- class assertTest(unittest.TestCase):
- #pass 表示什么也不做
- pass
- ast2 = assertTest()
- '''
- 第一个参数为异常的类型
- 第二个为方法名称
- 后面为方法的参数
- '''
- ast2.assertRaises(ZeroDivisionError,div,1,0)
- print("---------------------------------------")
- ast2.assertRaises(ZeroDivisionError,div,1,1)
调用 div(1,1)不会抛出异常 ZeroDivisionError, 所以 assertRaises()测试失败, 上述代码运行结果如下:
如果只传入了 expetion 或 msg 参数, 就可以在 with 上下文管理器中测试一段代码而不仅仅是测试函数, 就像下面这样.
- with ast2.assertRaises(ZeroDivisionError):
- div(1,1)
- with ast2.assertRaises(ZeroDivisionError):
- div(1,0)
运行结果如下:
[ 示例 2 ] assertRaises()的用法
- # 导入 warnings 模块
- import warnings
- # 定义一个简单的函数, 打印级别为 UserWarning 的告警
- def warnTest():
- warnings.warn("This is warning test")
- ast2.assertWarns(UserWarning,warnTest)
- print("--------------------------------")
- with ast2.assertWarns(UnicodeWarning):
- warnTest()
warnTest()函数不会打印 UnicodeWarning 级别的告警, 所以第二个告警校验会失败, 运行结果如下:
点击这里返回本篇目录
10, 跳过用例
在一些场景下并不会执行所有的用例, 而是选择性跳过一部分用例. unittest 支持跳过单个用例或整个测试类. 跳过用例需要用到 unittest.skip()装饰器.
@unittest.skip(reason): 无条件跳过单个用例或测试类, reason 是跳过的原因.
@unittest.skipIf(condition, reason):if 条件成立则跳过单个用例或测试类, reason 是跳过的原因.
@unittest.skipUnless(condition, reason): 条件为 False 则跳过单个用例或测试类, reason 是跳过的原因.
@unittest.expectedFailure: 标记测试用例为失败, 不会出现在统计结果中.
exception unittest.SkipTest(reason): 跳过用例并抛出异常.
[ 示例 3 ]: 直接跳过注册功能的用例
对 userRegTest.py 做如下修改, 并执行 userRegTest.py:
- @unittest.skip("skip test case of user reg")
- def test_pwdlenerr_L1(self):
- print("test case:test_pwdlenerr_L1")
- res = self.user1.userReg()
- self.assertEqual(res,"passwordLenError")
- #测试场景: 正常注册
- @unittest.skipIf(2>1,"skip if condiction")
- def test_regsucess_L0(self):
- print("test case:test_regsucess_L0")
- res = self.user2.userReg()
- self.assertEqual(res,"regSucess")
- #测试场景: 用户名重名
- @unittest.skipUnless(1<0,"skip unless.")
- def test_regagain_L1(self):
- print("test case:test_regagain_L1")
- res = self.user3.userReg()
- self.assertEqual(res,"SameNameError")
执行结果如下:
11,Test Discovery
unittest 支持用例发现功能, 在 unittest.defaultTestLoader 中实现. 使用的时候需要传入两个参数: 寻找的起始目录, 匹配的测试文件的格式(默认 test*.py). 用例发现也支持命令行模式.
[ 示例 4 ]:testDiscover
- startPath = './testCases'
- discover = unittest.defaultTestLoader.discover(start_dir=startPath,pattern='*Test.py')
- print(discover)
运行结果:
12, 加载用例
unittest 支持从模块和测试类中提取测试用例创建测试套. 在 class unittest.TestLoader 中实现. TestLoader 常见的加载方法如下:
loadTestsFromTestCase(testCaseClass): 从 unittest.TestCase 的子类即测试类中加载用例并返回测试套.
loadTestsFromName(name,module=None): 从特定的字符串说明符中加载用例并返回测试套.
loadTestsFromNames(names,module=None): 用法和 loadTestsFromName(name,module=None)类似, 不同的是它可以接受字符串说明符列表, 而不是一个.
loadTestsFromModule(module, pattern=None): 从模块中加载所有测试用例, 返回一个测试套件.
getTestCaseName(testCaseClass): 返回一个有序的包含在 testCaseClass 中的方法名列表.
[示例 5 ] :TestLoader 用法举例
- #coding:utf-8
- import unittest
- import testCases.userLoginTest,testCases.userRegTest
- from testCases.userRegTest import regTest
- from testCases.userLoginTest import loginTest
- loader = unittest.TestLoader()
- print("从测试类 loginTest 加载所有的用例:")
- caseInLoginTest = loader.getTestCaseNames(loginTest)
- print(caseInLoginTest)
- print("从测试模块中加载用例:")
- loadByModule = loader.loadTestsFromModule(testCases.userLoginTest)
- print(loadByModule)
- print("从测试类中加载用例:")
- loadByTestClass = loader.loadTestsFromTestCase(regTest)
- print(loadByTestClass)
- print("从特定的字符串标识符中加载用例")
- loadBySpecifier = loader.loadTestsFromName("regTest.test_regagain_L1")
- print(loadBySpecifier)
- print("从字符符标识符列表中加载用例")
- specStrs = ["regTest.test_regagain_L1","test_regsucess_L0"]
- loadBySpecifiers = loader.loadTestsFromNames(specStrs)
- print(loadBySpecifiers)
运行结果如下:
在发布时间紧张, 产品迭代频繁的情况下, 很多时候上线一个新特性, 对已发布的老特性采用的回归策略是: 只执行 L0 即 (Level 0) 级别的测试用例. 这个在 unittest 里面怎么实现呢? 解决方案是:
规范特性 L0 用例的格式, 比如: test_xxx_L0.
加载用例
通过正则表达式匹配出 L0 级别的用例集合, 然后交给 test runner 执行.
(完)
点击这里返回本篇目录
来源: https://www.cnblogs.com/webDepOfQWS/p/10732345.html