在Pytest中,通过使用 @pytest.mark.xxx 标记测试用例,在运行时,通过标记名来过滤测试用例。例如:只执行冒烟测试、只执行线上测试。
那在unittest中如何做呢?好像只能自己重写了。
1. 思路
我觉得解决思路有很多种(用装饰器、重写TestLoad、重写TestSuite等),但我只想到了一种,就是重写TestSuite。
为什么重写TestSuit ?
先看看unittest的基本流程
TestLoad
匹配并加载TestCase
中以test
开头的测试用例,然后添加到测试套件TestSuite
中,通过TextTestRunner
中的run()
方法接收 测试用例集
执行用例。
所以我们可以在测试套件TestSuit
传递给TextTestRunner
的之前,通过每个用例描述的tag内容过滤筛选测试用例。
1. 测试用例
class TestDemo(unittest.TestCase):
def test_1(self):
"""输入正确用户名和密码登录系统
tag:冒烟测试
"""
print('第一个测试用例')
def test_2(self):
"""输入错误用户名登录系统
tag:线上测试
"""
print('第二个测试用例')
def test_3(self):
"""输入错误密码登录系统
tag:冒烟测试
"""
print('第三个测试用例')
在每个用例之中,添加一个描述标签tag
用来区分“冒烟测试” 还是 “线上测试”。
2. 编写获取标签的方法
通过正则的方法获取,返回标签内容
import re
def get_case_tag(test:unittest.TestCase):
tag = None
test_doc = test._testMethodDoc
if test_doc and 'tag' in test_doc:
pattern = re.compile('tag:(\w+)')
tag = re.findall(pattern, test_doc)
return tag
3. 重写TestSuite
class MyTestSuit(unittest.TestSuite):
def __init__(self, tests=(),*,tag) -> None:
self.tag = tag # 通过tag控制
super().__init__(tests)
def addTests(self, tests) -> None:
if isinstance(tests, str):
raise TypeError("tests must be an iterable of tests, not a string")
for test in tests:
tag = get_case_tag(test)
if tag[0] == self.tag:
self.addTest(test)
4. 执行用例
if __name__ == '__main__':
suit = MyTestSuit(tag='线上测试')
suit.addTests([TestDemo('test_1'),TestDemo('test_2'),TestDemo('test_3')])
runner = unittest.TextTestRunner(resultclass=MyTestResult)
runner.run(suit)
结果:
只会执行第二个用例,tag为‘线上测试’。
第二个测试用例
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
总结:当然这只是简单的一个思路,还可进行优化,比如:通过命令的方法来执行冒烟测试还是线上测试、整合模块进行过滤。
全部测试代码:
class TestDemo(unittest.TestCase):
def test_1(self):
"""输入正确用户名和密码登录系统
tag:冒烟测试
"""
print('第一个测试用例')
def test_2(self):
"""输入错误用户名登录系统
tag:线上测试
"""
print('第二个测试用例')
def test_3(self):
"""输入错误密码登录系统
tag:冒烟测试
"""
print('第三个测试用例')
import re
def get_case_tag(test:unittest.TestCase):
# 这个方法主要用于获取用例中的描述tag信息
tag = None
test_doc = test._testMethodDoc
if test_doc and 'tag' in test_doc:
pattern = re.compile('tag:(\w+)')
tag = re.findall(pattern, test_doc)
return tag
class MyTestSuit(unittest.TestSuite):
def __init__(self, tests=(),*,tag) -> None:
self.tag = tag # 通过tag控制
super().__init__(tests)
def addTests(self, tests) -> None:
if isinstance(tests, str):
raise TypeError("tests must be an iterable of tests, not a string")
for test in tests:
tag = get_case_tag(test)
if tag[0] == self.tag:
self.addTest(test)
if __name__ == '__main__':
suit = MyTestSuit(tag='线上测试')
suit.addTests([TestDemo('test_1'),TestDemo('test_2'),TestDemo('test_3')])
runner = unittest.TextTestRunner(resultclass=MyTestResult)
runner.run(suit)