当前位置:网站首页>unittest 如何知道每个测试用例的执行时间
unittest 如何知道每个测试用例的执行时间
2022-06-11 16:21:00 【qq_37668510】
unittest在执行完所有用例时,控制台会输出所有用例的执行的时间。
具体是如何实现的,直接看源码:unittest.TextTestRunner类中的run方法。
class TextTestRunner(object):
# ....省略部分代码
def run(self, test):
"Run the given test case or test suite."
result = self._makeResult()
registerResult(result)
result.failfast = self.failfast
result.buffer = self.buffer
result.tb_locals = self.tb_locals
with warnings.catch_warnings():
if self.warnings:
warnings.simplefilter(self.warnings)
if self.warnings in ['default', 'always']:
warnings.filterwarnings('module',
category=DeprecationWarning,
message=r'Please use assert\w+ instead.')
# 获取时间主要代码:获取开始时间
startTime = time.perf_counter()
startTestRun = getattr(result, 'startTestRun', None)
if startTestRun is not None:
startTestRun()
try:
test(result) # 这里是执行用例的地方
finally:
stopTestRun = getattr(result, 'stopTestRun', None)
if stopTestRun is not None:
stopTestRun()
# 用例执行结束
stopTime = time.perf_counter()
# 运行测试用例的总时间
timeTaken = stopTime - startTime
result.printErrors()
if hasattr(result, 'separator2'):
self.stream.writeln(result.separator2)
run = result.testsRun
# 通过这段代码输出到控制台
self.stream.writeln("Ran %d test%s in %.3fs" %
(run, run != 1 and "s" or "", timeTaken))
self.stream.writeln()
# ....省略部分代码
return result
源码中只提供了获取用例总的运行时间,那么如何才能获取每个用例的时间?
思路
我想到了几种方式可以获取:
- 第一种:使用
setUp和tearDown钩子函数实现(不推荐)。 - 第二种:使用装饰器(不推荐)。
- 第三种:重新
TextTestResult类(推荐)。
1. 使用钩子函数实现(不推荐)
缺点:每一个测试类都需要写重复的代码,所以不推荐。
import unittest
import time
class TestDemo(unittest.TestCase):
def setUp(self):
self.startTime = time.perf_counter()
def test_01(self):
time.sleep(1)
print('this is testcase one')
def test_02(self):
print('this is testcase two')
def tearDown(self):
self.timeTaken = time.perf_counter() - self.startTime
print('当前用例执行时间:{:.10f}s'.format(self.timeTaken))
if __name__ == "__main__":
unittest.main()
结果:
this is testcase one
当前用例执行时间:1.0053873200s
.this is testcase two
当前用例执行时间:0.0000630220s
.
----------------------------------------------------------------------
Ran 2 tests in 1.006s
2. 使用装饰器方式实现(不推荐)
使用装饰器,看似比钩子函数解决了写很多重复代码的问题,但是还不够完美,不推荐。
from re import L
import re
import unittest
import time
import functools
def CustomTimes(func):
@functools.wraps(func)
def wrapps(self):
start_time = time.perf_counter()
func(self) # 执行测试用例
timeTaken = time.perf_counter() - start_time
print('当前用例执行时间:{:.10f}s'.format(timeTaken))
return wrapps
class TestDemo(unittest.TestCase):
@CustomTimes
def test_01(self):
time.sleep(1)
print('this is testcase one')
@CustomTimes
def test_02(self):
print('this is testcase two')
if __name__ == "__main__":
unittest.main()
结果:
this is testcase one
当前用例执行时间:1.0051255180s
.this is testcase two
当前用例执行时间:0.0000147200s
.
----------------------------------------------------------------------
Ran 2 tests in 1.006s
3. 重新TextTestResult类(推荐)
TextTestResult的继承关系:TextTestResult–>继承–>TestResult,在TestResult 中,有两个方法需要重写,这些方法都会在用例执行是自动运行
TestResult部分源码:
这是一个我们需要重新的方法,需要记录测试用例开始执行的时间。
def startTest(self, test):
"Called when the given test is about to be run"
self.testsRun += 1
self._mirrorOutput = False
self._setupStdout()
还有一个是用例执行成功的方法addSuccess,用例执行成功时会调用这个方法,所以我准备用例记录用例的结束时间。
def addSuccess(self, test):
"测试成功完成时调用"
pass
代码:
import unittest
import time
from unittest import TextTestResult as _TestTestResult, TextTestRunner as _TextTestRunner
class CTextTestResult(_TestTestResult):
def __init__(self,*args, **kwargs):
super(CTextTestResult,self).__init__(*args, **kwargs)
self.times = [] # 用于记录测试时间
def startTest(self, test: unittest.case.TestCase) -> None:
# 测试开始执行之前调用
self.start_time = time.time()
super(CTextTestResult,self).startTest(test)
def addSuccess(self, test: unittest.case.TestCase) -> None:
# 测试完成时调用
total_time = time.time() - self.start_time
test_name = self.getDescription(test)
self.times.append((test_name,total_time))
super(CTextTestResult,self).addSuccess(test)
def getTestTimeing(self):
# 返回记录的所有用例的时间
return self.times
super(CTextTestResult,self).startTest(test) super(CTextTestResult,self).addSuccess(test)
这两句非常重要,super用于调用父类的方法,在某个方法中添加新的功能,也不能把旧的功能丢了,所以之前的功能也需要保留。
最后一步:重写TextTestRunner,TextTestRunner记录了所有信息,可以获取我们自定义的属性和方法。
class CTextTestRunner(_TextTestRunner):
def run(self, test):
result = super(CTextTestRunner,self).run(test)
for test_name, total_time in result.getTestTimeing():
print("({:.10}s) {}".format(format(total_time, 'f'), test_name))
return result
我们自定义的东西都存在result 中了。
4.完整代码
import unittest
import time
from unittest import TextTestResult as _TestTestResult, TextTestRunner as _TextTestRunner
class TestDemo(unittest.TestCase):
def test_01(self):
time.sleep(1)
print('this is testcase one')
def test_02(self):
print('this is testcase two')
def tearDown(self) -> None:
return super().tearDown()
class CTextTestResult(_TestTestResult):
def __init__(self,*args, **kwargs):
super(CTextTestResult,self).__init__(*args, **kwargs)
self.times = []
def startTest(self, test: unittest.case.TestCase) -> None:
self.start_time = time.time()
super(CTextTestResult,self).startTest(test)
def addSuccess(self, test: unittest.case.TestCase) -> None:
total_time = time.time() - self.start_time
test_name = self.getDescription(test)
self.times.append((test_name,total_time))
super(CTextTestResult,self).addSuccess(test)
def getTestTimeing(self):
return self.times
class CTextTestRunner(_TextTestRunner):
def run(self, test):
result = super(CTextTestRunner,self).run(test)
for test_name, total_time in result.getTestTimeing():
print("({:.10}s) {}".format(format(total_time, 'f'), test_name))
return result
if __name__ == "__main__":
test_load = unittest.defaultTestLoader
case = test_load.loadTestsFromTestCase(TestDemo)
runner = CTextTestRunner(resultclass=CTextTestResult)
result = runner.run(case)
边栏推荐
- leetcode785. 判断二分图(中等)
- Implementation of VGA protocol based on FPGA
- If you want to learn ArrayList well, it is enough to read this article
- 【剑指Offer】21.调整数组顺序使奇数位于偶数前面
- RDKit 安装
- [sword finger offer] 22 The penultimate node in the linked list
- What if the win10 security center cannot be closed
- 项目经理如何击退被工作汇报支配的恐惧感?
- WGet command use
- Laravel8 implementation of sign in function
猜你喜欢

Laravel 2020-01-01t00:00:00.000000z date conversion

为什么芯片设计也需要「匠人精神」?

Toolbar details of user interface - autorunner automated test tool

面试经典题目:怎么做的性能测试?【杭州多测师】【杭州多测师_王sir】

What is a generic? Why use generics? How do I use generics? What about packaging?

2022安全员-C证特种作业证考试题库及答案

After reading the book reading methods

Differences between list and set access elements

MySQL快速入门实例篇(入内不亏)

大龄码农从北京到荷兰的躺平生活
随机推荐
Zhenxiang, Huawei gives n+1 for voluntary resignation
leetcode-141. Circular linked list
leetcode417. Pacific Atlantic current problems (medium)
Laravel 8 realizes database backup through task scheduling
2022年安全员-B证国家题库及模拟考试
Complete test process [Hangzhou multi tester] [Hangzhou multi tester \wang Sir]
TC8:UDP_MessageFormat_01-02
[从零开始学习FPGA编程-17]:快速入门篇 - 操作步骤2-5- VerilogHDL硬件描述语言符号系统与程序框架(软件程序员和硬件工程师都能看懂)
JVM 的组成
Project workspace creation steps - Zezhong ar automated test tool
回归预测 | MATLAB实现RBF径向基神经网络多输入单输出
Pytest test framework Basics
用户界面之工具栏详解-AutoRunner自动化测试工具
CLP information - No. 1 central document on Strengthening Rural Revitalization financial services
[ISITDTU 2019]EasyPHP
瑞吉外卖项目(三)员工管理业务开发
项目无法加载nacos配置中心的配置文件问题
Can I eat meat during weight loss? Will you get fat?
If you want to learn ArrayList well, it is enough to read this article
Go quick start of go language (I): the first go program