在编写用例的时候,我们可能会为用例添加一些描述信息以及使用标签用来区分冒烟测试和线上测试,或者在执行的时候获取用例名称、用例所在的模块等等。
unittest.TestCase
类已经为我们提供了一些可用的属性和方法,比如:
self._testMethodDoc
属性:获取测试用例的描述。unittest.TestCase自带属性。self.shortDescription()
方法:获取第一行描述。unittest.TestCase自带方法。self.id()
方法:用例完整路径,unittest.TestCase自带方法。
我们需要扩展一下,获取用例所在的模块、类名、用例所在类完整路劲以及类的docstring描述(后续可以增加开始时间、结束时间等属性)。
怎么做?
第一步:自定义一个测试类,包含所有所需要的属性。
第二步:自定义一个简单的TestResult类,继承unittest.TestResult
并重写startTest()
方法。
为什么重写startTest方法,就不能写其他的?
因为在执行TeatCase用例时,每条测试用例执行之前都会执行uniitest.TestResult类中的startTest方法,而我们只需要继承然后在重写就行了,会自动帮我们调用。
TestCase.run方法部分源码:
def run(self, result=None):
if result is None:
result = self.defaultTestResult()
startTestRun = getattr(result, 'startTestRun', None)
stopTestRun = getattr(result, 'stopTestRun', None)
if startTestRun is not None:
startTestRun()
else:
stopTestRun = None
result.startTest(self) # 在执行用例之前会执行startTest()方法,参数self表示当前测试用例。
1. 自定义TestCase测试类
实例化的时候需要把测试用例对象传递进来,不然怎么知道测试用例的相关内容。
class MyTestCase():
def __init__(self,test:unittest.TestCase) -> None:
self.test = test # 测试用例对象
self.testMethodDoc = test._testMethodDoc # 获取测试用例的描述
self.id = test.id() # 测试用例的路径
self.shortDescription = test.shortDescription() # 获取第一行描述
self.module_name = test.__module__ # 用例所在模块名
self.class_name = test.__class__.__name__ # 用例所在类名
self.class_id = f'{test.__module__}.{test.__class__.__name__}' # 用例所在类完整路径
self.class_doc = test.__class__.__doc__ # 用例所在类docstring描述
# 用于打印调试
def __str__(self):
return f"描述: {self.doc}\
id: {self.id}\
shortDescription: {self.shortDescription}\
模块名称:{self.module_name}\
类名:{self.class_name}\
类的描述:{self.class_doc}"
__str__
方法只是用于打印调试的,后续可以存为json或其他数据格式。
2. 自定义TestResult
需要继承uniitest.TestResult类并重写startTest方法。
class MyTestResult(unittest.TestResult):
# 重写startTest方法
def startTest(self,test):
result=MyTestCase(test=test) # 实例化自定义的MyTestCase,将测试用例传递过去
print(result) # 输出打印一下
# 线上最好是存放在result属性中,上面只适用于调试
# test.result=MyTestCase(test=test)
super().startTest(test) # 调用父类的startTest,保证其他功能不会丢失
参数test
表示当前测试用例实例对象。通过上面的TestCase.run()方法中的result.startTest(self)
这条语句传递。
3. 编写测试用例
class TestDemo(unittest.TestCase):
"""登录页面测试"""
def test_1(self):
"""输入正确用户名和密码登录系统
tag:冒烟测试
"""
print('登录测试用例')
运行代码:
if __name__ == '__main__':
test_load = unittest.defaultTestLoader
case = test_load.loadTestsFromTestCase(TestDemo) # 加载自己的测试用例的类
runner = unittest.TextTestRunner(resultclass=MyTestResult) # 使用自定义的报告
runner.run(case)
-------------------
# 输出
# 类的描述:登录页面测试
# 类名:TestDemo
# 模块名称:__main__
# 描述: 输入正确用户名和密码登录系统
# tag:冒烟测试
# tag:线上测试
# id: __main__.TestDemo.test_1
# shortDescription: 输入正确用户名和密码登录系统
全部测试代码:
import unittest
class TestDemo(unittest.TestCase):
def test_1(self):
"""输入正确用户名和密码登录系统
tag:冒烟测试
tag:线上测试
"""
print('第一个测试用例')
class MyTestCase():
def __init__(self,test:unittest.TestCase) -> None:
self.test = test # 测试用例对象
self.testMethodDoc = test._testMethodDoc # 获取测试用例的描述
self.id = test.id() # 测试用例的路径
self.shortDescription = test.shortDescription() # 获取第一行描述
self.module_name = test.__module__ # 用例所在模块名
self.class_name = test.__class__.__name__ # 用例所在类名
self.class_id = f'{test.__module__}.{test.__class__.__name__}' # 用例所在类完整路径
self.class_doc = test.__class__.__doc__ # 用例所在类docstring描述
# 用于打印调试
def __str__(self):
return f"id: {self.id}\
shortDescription: {self.shortDescription}\
模块名称:{self.module_name}\
类名:{self.class_name}\
类的描述:{self.class_doc}"
class MyTestResult(unittest.TestResult):
def startTest(self,test:unittest.TestCase):
result=MyTestCase(test=test)
print(result)
super().startTest(test)
if __name__ == '__main__':
test_load = unittest.defaultTestLoader
case = test_load.loadTestsFromTestCase(TestDemo)
runner = unittest.TextTestRunner(resultclass=MyTestResult)
runner.run(case)