- Pytest:帮助您编写更好的程序
- 完整的 Pytest 文档
- 安装和入门
- 使用和调用
- 在现有测试套件中使用 pytest
- 测试中断言的编写和报告
- Pytest 夹具:显式、模块化、可扩展
- 用属性标记测试函数
- MonkeyPatching / Mocking 模块和环境
- 临时目录和文件
- 捕获 stdout/stderr 输出
- 捕获警告
- 模块和测试文件的 Doctest 集成
- 跳过和 xfail:处理无法成功的测试
- 参数化夹具和测试功能
- 缓存:使用交叉测试运行状态
- UnitTest.TestCase 支持
- 运行为鼻子编写的测试
- 经典的 Xunit 风格设置
- 安装和使用插件
- 编写插件
- 登录
- 良好的集成实践
- 古怪的测试
- Pytest 导入机制和 sys.path/PYTHONPATH
- 设置 bash 完成
- API 引用
- _pytest.hookspec
- _pytest.python_api
- _pytest.outcomes
- _pytest.config
- _pytest.mark
- _pytest.recwarn
- _pytest.assertion
- _pytest.freeze_support
- _pytest.fixtures
- _pytest.cacheprovider
- _pytest.capture
- _pytest.doctest
- _pytest.junitxml
- _pytest.logging
- _pytest.monkeypatch
- _pytest.pytester
- _pytest.tmpdir
- _pytest.python
- _pytest.nodes
- _pytest.reports
- _pytest._code.code
- _pytest.config.argparsing
- _pytest.main
- pluggy.callers
- _pytest.config.exceptions
- py.test 2.0.0:断言++、UnitTest++、Reporting++、Config++、Docs++
- 示例和自定义技巧
- 配置
- 贡献开始
- 向后兼容策略
- Python 2.7 和 3.4 支持
- 企业版 pytest
- 项目实例
- 历史笔记
- 弃用和移除
- 发展指南
- 演讲和辅导
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
pluggy.callers
""" Call loop machinery """ import sys import warnings _py3 = sys.version_info > (3, 0) if not _py3: exec( """ def _reraise(cls, val, tb): raise cls, val, tb """ ) def _raise_wrapfail(wrap_controller, msg): co = wrap_controller.gi_code raise RuntimeError( "wrap_controller at %r %s:%d %s" % (co.co_name, co.co_filename, co.co_firstlineno, msg) ) class HookCallError(Exception): """ Hook was called wrongly. """ [文档]class _Result(object): def __init__(self, result, excinfo): self._result = result self._excinfo = excinfo @property def excinfo(self): return self._excinfo @property def result(self): """Get the result(s) for this hook call (DEPRECATED in favor of ``get_result()``).""" msg = "Use get_result() which forces correct exception handling" warnings.warn(DeprecationWarning(msg), stacklevel=2) return self._result @classmethod def from_call(cls, func): __tracebackhide__ = True result = excinfo = None try: result = func() except BaseException: excinfo = sys.exc_info() return cls(result, excinfo) [文档] def force_result(self, result): """Force the result(s) to ``result``. If the hook was marked as a ``firstresult`` a single value should be set otherwise set a (modified) list of results. Any exceptions found during invocation will be deleted. """ self._result = result self._excinfo = None [文档] def get_result(self): """Get the result(s) for this hook call. If the hook was marked as a ``firstresult`` only a single value will be returned otherwise a list of results. """ __tracebackhide__ = True if self._excinfo is None: return self._result else: ex = self._excinfo if _py3: raise ex[1].with_traceback(ex[2]) _reraise(*ex) # noqa def _wrapped_call(wrap_controller, func): """ Wrap calling to a function with a generator which needs to yield exactly once. The yield point will trigger calling the wrapped function and return its ``_Result`` to the yield point. The generator then needs to finish (raise StopIteration) in order for the wrapped call to complete. """ try: next(wrap_controller) # first yield except StopIteration: _raise_wrapfail(wrap_controller, "did not yield") call_outcome = _Result.from_call(func) try: wrap_controller.send(call_outcome) _raise_wrapfail(wrap_controller, "has second yield") except StopIteration: pass return call_outcome.get_result() class _LegacyMultiCall(object): """ execute a call into multiple python functions/methods. """ # XXX note that the __multicall__ argument is supported only # for pytest compatibility reasons. It was never officially # supported there and is explicitely deprecated since 2.8 # so we can remove it soon, allowing to avoid the below recursion # in execute() and simplify/speed up the execute loop. def __init__(self, hook_impls, kwargs, firstresult=False): self.hook_impls = hook_impls self.caller_kwargs = kwargs # come from _HookCaller.__call__() self.caller_kwargs["__multicall__"] = self self.firstresult = firstresult def execute(self): caller_kwargs = self.caller_kwargs self.results = results = [] firstresult = self.firstresult while self.hook_impls: hook_impl = self.hook_impls.pop() try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,) ) if hook_impl.hookwrapper: return _wrapped_call(hook_impl.function(*args), self.execute) res = hook_impl.function(*args) if res is not None: if firstresult: return res results.append(res) if not firstresult: return results def __repr__(self): status = "%d meths" % (len(self.hook_impls),) if hasattr(self, "results"): status = ("%d results, " % len(self.results)) + status return "<_MultiCall %s, kwargs=%r>" % (status, self.caller_kwargs) def _legacymulticall(hook_impls, caller_kwargs, firstresult=False): return _LegacyMultiCall( hook_impls, caller_kwargs, firstresult=firstresult ).execute() def _multicall(hook_impls, caller_kwargs, firstresult=False): """Execute a call into multiple python functions/methods and return the result(s). ``caller_kwargs`` comes from _HookCaller.__call__(). """ __tracebackhide__ = True results = [] excinfo = None try: # run impl and wrapper setup functions in a loop teardowns = [] try: for hook_impl in reversed(hook_impls): try: args = [caller_kwargs[argname] for argname in hook_impl.argnames] except KeyError: for argname in hook_impl.argnames: if argname not in caller_kwargs: raise HookCallError( "hook call must provide argument %r" % (argname,) ) if hook_impl.hookwrapper: try: gen = hook_impl.function(*args) next(gen) # first yield teardowns.append(gen) except StopIteration: _raise_wrapfail(gen, "did not yield") else: res = hook_impl.function(*args) if res is not None: results.append(res) if firstresult: # halt further impl calls break except BaseException: excinfo = sys.exc_info() finally: if firstresult: # first result hooks return a single value outcome = _Result(results[0] if results else None, excinfo) else: outcome = _Result(results, excinfo) # run all wrapper post-yield blocks for gen in reversed(teardowns): try: gen.send(outcome) _raise_wrapfail(gen, "has second yield") except StopIteration: pass return outcome.get_result()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论