python 单元测试中处理用例失败的情况
今天有一个需求, 在单元测试失败的时候打印一些日志, 我们管他叫 dosomething 吧 ,反正就是做一些操作
查了下并没有查到相关的方法, 于是研究了一波unittest
的源码
发现了这个东西
try:
self._outcome = outcome
with outcome.testPartExecutor(self):
self.setUp()
if outcome.success:
outcome.expecting_failure = expecting_failure
with outcome.testPartExecutor(self, isTest=True):
testMethod()
outcome.expecting_failure = False
with outcome.testPartExecutor(self):
self.tearDown()
self.doCleanups()
for test, reason in outcome.skipped:
self._addSkip(result, test, reason)
self._feedErrorsToResult(result, outcome.errors)
if outcome.success:
if expecting_failure:
if outcome.expectedFailure:
self._addExpectedFailure(result, outcome.expectedFailure)
else:
self._addUnexpectedSuccess(result)
else:
result.addSuccess(self)
return result
finally:
result.stopTest(self)
if orig_result is None:
stopTestRun = getattr(result, 'stopTestRun', None)
if stopTestRun is not None:
stopTestRun()
# explicitly break reference cycles:
# outcome.errors -> frame -> outcome -> outcome.errors
# outcome.expectedFailure -> frame -> outcome -> outcome.expectedFailure
outcome.errors.clear()
outcome.expectedFailure = None
# clear the outcome, no more needed
self._outcome = None
其中重点关注下testMethod()
这个正是我们执行的用例
于是去看了下testPartExecutor
用例失败的处理是在这里进行处理的
def testPartExecutor(self, test_case, isTest=False):
old_success = self.success
self.success = True
try:
yield
except KeyboardInterrupt:
raise
except SkipTest as e:
self.success = False
self.skipped.append((test_case, str(e)))
except _ShouldStop:
pass
except:
exc_info = sys.exc_info()
if self.expecting_failure:
self.expectedFailure = exc_info
else:
self.success = False
self.errors.append((test_case, exc_info))
# explicitly break a reference cycle:
# exc_info -> frame -> exc_info
exc_info = None
else:
if self.result_supports_subtests and self.success:
self.errors.append((test_case, None))
finally:
self.success = self.success and old_success
奈何, 他只是在self.errors
(其中self为我们测试类的一个实例)中加了点东西
于是对self.errors
进行观察,发现及时用例是正常的,他依然由内容.
这..............于是我想到他最终是怎么打出来失败的log的
看到 上面代码中的 self._feedErrorsToResult(result, outcome.errors)
于是找到了这个东西
def _feedErrorsToResult(self, result, errors):
for test, exc_info in errors:
if isinstance(test, _SubTest):
result.addSubTest(test.test_case, test, exc_info)
elif exc_info is not None:
if issubclass(exc_info[0], self.failureException):
result.addFailure(test, exc_info)
else:
result.addError(test, exc_info)
从上面的代码我们可以知道 如果 error
的第二项是None
那么就是一个执行成功的用例,经过实验并确认了这个事情
现在知道了 unittest
是如何处理 失败用例的了
于是便有了下面这种方法
def tearDown(self):
errors = self._outcome.errors
for test, exc_info in errors:
if exc_info:
# dosomething
pass
上面这种方法尽量少的改变原来的逻辑, 想到一种新的方法解决问题
既然unittest
没有处理这个事情,那我们魔改之
于是有了下面这种方法
注意: 不建议魔改代码
import sys
import contextlib
import unittest
from unittest.case import SkipTest, _ShouldStop, _Outcome
@contextlib.contextmanager
def testPartExecutor(self, test_case, isTest=False):
old_success = self.success
self.success = True
try:
yield
except Exception:
try:
# if error
getattr(test_case, test_case._testMethodName).__func__._error = True
raise
except KeyboardInterrupt:
raise
except SkipTest as e:
self.success = False
self.skipped.append((test_case, str(e)))
except _ShouldStop:
pass
except:
exc_info = sys.exc_info()
if self.expecting_failure:
self.expectedFailure = exc_info
else:
self.success = False
self.errors.append((test_case, exc_info))
# explicitly break a reference cycle:
# exc_info -> frame -> exc_info
exc_info = None
else:
if self.result_supports_subtests and self.success:
self.errors.append((test_case, None))
finally:
self.success = self.success and old_success
_Outcome.testPartExecutor = testPartExecutor
class MyTest(unittest.TestCase):
def test_1(self):
print("test_1")
def test_2(self):
print("test_2")
raise ValueError
def tearDown(self):
if hasattr(getattr(self, self._testMethodName), "_error"):
# dosomething
pass
# def tearDown(self):
# 推荐这种方法
# errors = self._outcome.errors
# for test, exc_info in errors:
# if exc_info:
# # dosomething
# pass
if __name__ == '__main__':
unittest.main()
这样我们就可以在用例执行失败后在tearDown
的时候做一些操作
python 单元测试中处理用例失败的情况的更多相关文章
- unittest+HtmlTestRunner+python接口自动化测试:用例失败发送邮件
一点啰嗦:发送邮件python中有另一个支持的第三方库yagmail更轻量级,代码参考可移步至此:https://www.cnblogs.com/princessironfan/p/13220601. ...
- c#调用python脚本实现排序(适用于python脚本中不包含第三方模块的情况)
引用:https://www.cnblogs.com/zoe-yan/p/10374757.html 利用vs2017c#调用python脚本需要安装IronPython.我是通过vs2017的工具- ...
- QTP场景恢复之用例失败自动截图
以下代码是在QC里运行QTP来执行脚本过程,当执行过程中发现用例失败后就会自动截图,然后把用例返回到最初始的状态,模拟了场景恢复的机制 Class QCImageErrorCapture Dim qt ...
- Python单元测试框架unittest重要属性 与 用例编写思路
前言 本文为转载,原文地址作者列举python unittest这个测试框架的主要属性和 测试用例思路 unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行, ...
- day11_单元测试_读取yaml文件中的用例,自动获取多个yaml文件内容执行生成报告
一.使用.yaml格式的文件直接可以存放字典类型数据,如下图,其中如果有-下一行有缩进代表这是个list,截图中是整体是一个list,其中有两部分,第二部分又包含另外一个list 二.单元测试:开发自 ...
- hanlp在Python环境中的安装失败后的解决方法
Hanlp是由一系列模型与算法组成的javag工具包,目标是普及自然语言处理再生环境中的应用.有很多人在安装hanlp的时候会遇到安装失败的情况,下面就是某大神的分享的在python环境中安装失败的解 ...
- Python中的单例设计
01. 单例设计模式 设计模式 设计模式 是 前人工作的总结和提炼,通常,被人们广泛流传的设计模式都是针对 某一特定问题 的成熟的解决方案 使用 设计模式 是为了可重用代码.让代码更容易被他人理解.保 ...
- Python单元测试简介及Django中的单元测试
Python单元测试简介及Django中的单元测试 单元测试负责对最小的软件设计单元(模块)进行验证,unittest是Python自带的单元测试框架. 单元测试与功能测试都是日常开发中必不可少的部分 ...
- Python单元测试框架之pytest -- 断言
对于测试来讲,不管是功能测试,自动化测试,还是单元测试.一般都会预设一个正确的预期结果,而在测试执行的过程中会得到一个实际的结果.测试的成功与否就是拿实际的结果与预期的结果进行比较.这个比的过程实际就 ...
随机推荐
- jQuery鼠标悬停显示提示信息窗体
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- C#反射发出System.Reflection.Emit学习
一.System.Reflection.Emit概述 Emit,可以称为发出或者产生.与Emit相关的类基本都存在于System.Reflection.Emit命名空间下.反射,我们可以取得形如程序集 ...
- objc_setAssociatedObject
学习笔记:通过 objc_setAssociatedObject alert 和 button关联 及传值 标签: ios 2013-11-22 16:25 7924人阅读 评论(1) 收藏 举报 ...
- 细数MQ那些不得不说的8大好处
消息队列(MQ)是目前系统架构中主流方式,在大型系统及大数据中广泛采用.对任何架构或应用来说, MQ都是一个至关重要的组件.今天我们就来细数MQ那些不得不说的好处. 好处一:解耦 在项目启动之初来预测 ...
- cookie domain and cookie path
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie Domain=<domain-value> Opt ...
- Windows虚拟机中无法传输Arduino程序的问题
现象 最近儿子在学习机器人编程,其中有一步需要把板子和电脑用USB线相连接,然后把在电脑中编辑好的程序传输到Arduino板子上.在Windows笔记本上能正常工作,但在我的Mac笔记本的Window ...
- redis过期策略和内存淘汰机制
目录 常见的删除策略 redis使用的过期策略:定期删除+惰性删除 定期删除 惰性删除 为什么要采用定期删除+惰性删除2种策略呢? redis内存淘汰机制 常见的删除策略 1.定时删除:在设置键的过期 ...
- 小HY的四元组
4.7 比赛T1,然而这题爆零了 其实很简单的...其实哈希都不用 所以首先记录每组的差值,按其sort一下再暴力找即可 #include<cstdio> #include<iost ...
- python自动化测试学习笔记-2-字典、元组、字符串方法
一.字典 Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型. 字典的每个键值(key=>value)对用冒号(:)分割,每个对之间用逗号(,)分割, ...
- Android布局属性LayoutParams的理解
在一次笔试中搞混LayoutParams的用法,特来总结一番: LayoutParams继承于Android.View.ViewGroup.LayoutParams.LayoutParams相当于一个 ...