返回: Pytest权威教程

断言的编写和报告

使用assert语句进行断言

pytest允许你使用标准的Pythonassert断言语句来验证测试中的期望结果和实际结果。 例如,你可以编写以下内容:

# test_assert1.py文件内容
def f():
return 3 def test_function():
assert f() == 4

来断言你的函数返回一个特定的值。 如果此断言失败,你将看到函数调用的返回值:

$ pytest test_assert1.py
=========================== test session starts ============================
platform linux -- Python 3.x.y,pytest-3.x.y,py-1.x.y,pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR,inifile:
collected 1 item test_assert1.py F [100%] ================================= FAILURES =================================
______________________________ test_function _______________________________ def test_function():
> assert f() == 4
E assert 3 == 4
E + where 3 = f() test_assert1.py:5: AssertionError
========================= 1 failed in 0.12 seconds =========================

Pytest支持显示常见的包括调用,属性,比较以及二元和一元运算符子表达式的值 (参考: pytest执行Python测试失败报告示例)。 你可以在不使用繁琐的Python惯用构造样板代码的同时,不丢失断言失败的对比信息(内省信息)。

当然,你也可以像下面所示,指定断言失败的返回消息:

assert a % 2 == 0,"值为奇数,应为偶数"

这样将不会断言失败对比信息(内省信息),而只简单地在追溯信息中显示你指定的失败返回信息。

有关断言内省的更多信息,请参阅高级断言内省

异常断言

你可以像如下所示,使用pytest.raises作为上下文管理器来进行异常断言:

import pytest

def test_zero_division():
with pytest.raises(ZeroDivisionError):
1 / 0

如果需要访问实际的异常信息,你可以使用:

def test_recursion_depth():
with pytest.raises(RuntimeError) as excinfo:
def f():
f()
f()
assert 'maximum recursion' in str(excinfo.value)

excinfo是一个ExceptionInfo实例,它是实际异常的装饰器。 其主要属性有.type,.value.traceback三种

版本3.0已修改

在上下文管理器中,你可以使用参数message来指定自定义失败信息:

>>> with raises(ZeroDivisionError,message="Expecting ZeroDivisionError"):
... pass
... Failed: Expecting ZeroDivisionError

如果你想编写适用于Python 2.4的测试代码,你还可以使用其他两种方法来测试预期的异常:

pytest.raises(ExpectedException,func,*args,**kwargs)
pytest.raises(ExpectedException,"func(*args,**kwargs)")

两者都可以对带任意参数的函数,断言是否出现了期望的异常:ExpectedException。 即使没有异常或出现了不同的异常,报告生成器也能输出一些有用的断言信息。

注意,也可以为pytest.mark.xfail指定一个“raises”参数,当引发异常时标记用例失败:

@pytest.mark.xfail(raises=IndexError)
def test_f():
f()

对于你在代码中故意设置的异常,使用pytest.raises断言更加好用,而将@ pytest.mark.xfail与check函数一起使用对于已知未修复或依赖中的bug会更好。

此外,上下文管理器表单接受match关键字参数来测试正则表达式匹配中的异常(如unittest中的TestCase.assertRaisesRegexp方法):

import pytest

def myfunc():
raise ValueError("Exception 123 raised") def test_match():
with pytest.raises(ValueError,match=r'.* 123 .*'):
myfunc()

match变量后的正则表达式与使用re.search函数来进行匹配一致。 因此在上面的例子中,match ='123'不会引发异常。

警示断言

2.8版本新增

你可以使用pytest.warns检查代码是否引发了特定警告。

使用上下文对比

2.0版本新增

Pytest可以在断言的比较中提供丰富的上下文信息。 例如:

# test_assert2.py文件内容

def test_set_comparison():
set1 = set("1308")
set2 = set("8035")
assert set1 == set2

当你运行这个模块后

$ pytest test_assert2.py
=========================== test session starts ============================
platform linux -- Python 3.x.y,pytest-3.x.y,py-1.x.y,pluggy-0.x.y
rootdir: $REGENDOC_TMPDIR,inifile:
collected 1 item test_assert2.py F [100%] ================================= FAILURES =================================
___________________________ test_set_comparison ____________________________ def test_set_comparison():
set1 = set("1308")
set2 = set("8035")
> assert set1 == set2
E AssertionError: assert {'0','1','3','8'} == {'0','3','5','8'}
E Extra items in the left set:
E '1'
E Extra items in the right set:
E '5'
E Use -v to get the full diff test_assert2.py:5: AssertionError
========================= 1 failed in 0.12 seconds =========================

对大量用例进行了特定对比:

  • 长字符串断言:显示上下文差异
  • 长序列断言:显示第一个失败的索引
  • 字典断言:显示不同的key-value对

有关更多示例,请参阅 报告样例。

自定义断言对比信息

可以通过实现hook方法pytest_assertrepr_compare来在断言结果中添加你自己的详细说明信息。

**pytest_assertrepr_compare(config,op,left,right)*- [源码]

返回失败断言表达式中的对比信息。

如果没有自定义对比信息,则返回None,否则返回一列字符串。 字符串将由换行符连接,但字符串中的任何换行符都将被转义。 请注意,除第一行外的所有行都将略微缩进,目的是将第一行作为摘要。

参数: config(pytest.config.Config* - pytest config 对象

例如,在conftest.py文件中添加以下钩子(Hook)方法,可以为Foo对象提供了附加对比信息:

# conftest.py内容
from test_foocompare import Foo
def pytest_assertrepr_compare(op,left,right):
if isinstance(left,Foo) and isinstance(right,Foo) and op == "==":
return ['Foo实例对比:',
' 值: %s != %s' % (left.val,right.val)]

现在,在测试模块使用

# test_foocompare.py内容
class Foo(object):
def __init__(self,val):
self.val = val def __eq__(self,other):
return self.val == other.val def test_compare():
f1 = Foo(1)
f2 = Foo(2)
assert f1 == f2

运行这个测试模块你可以看到conftest.py文件中定义的自定义输出:

$ pytest -q test_foocompare.py
F [100%]
================================= FAILURES =================================
_______________________________ test_compare _______________________________ def test_compare():
f1 = Foo(1)
f2 = Foo(2)
> assert f1 == f2
E assert Foo实例对比:
E 值: 1 != 2 test_foocompare.py:11: AssertionError
1 failed in 0.12 seconds

高级断言内省

2.1版本新函数

报告有关失败断言的详细信息是通过在运行之前重写assert语句来实现的。 重写的断言语句将内省信息放入断言失败消息中。 Pytest只重写测试收集过程直接发现的测试模块中的assert断言,因此在支持模块(非测试模块)中的断言,不会被重写

你可以在导入模块前通过调用register_assert_rewrite手动启用断言重写(比如可以在conftest.py这样使用)。

注意

Pytest通过使用导入hook方法写入新的pyc文件来重写测试模块。 通常这种结构比较清晰。 但是,如果你混乱导入,导入的hook方法可能会受到干扰。

如果是这种情况,你有两种选择:

通过将字符串PYTEST_DONT_REWRITE添加到其docstring来禁用特定模块的重写。

使用--assert = plain禁用所有模块的重写。

此外,如果无法写入新的.pyc文件(如在只读文件系统或zip文件中),重写将无提示失败。

有关进一步的信息,课参阅:本杰明彼得森写的[pytest的新断言改写的幕后故事。

版本2.1新函数:添加断言重写作为备用内省技术。

版本2.1更改:引入--assert选项。 弃用--no-assert--nomagic

版本3.0版更改:删除--no-assert和--nomagic选项。 删除--assert = reinterp`选项。

Pytest权威教程04-断言的编写和报告的更多相关文章

  1. Pytest权威教程(官方教程翻译)

    Pytest权威教程01-安装及入门 Pytest权威教程02-Pytest 使用及调用方法 Pytest权威教程03-原有TestSuite的执行方法 Pytest权威教程04-断言的编写和报告 P ...

  2. Pytest权威教程21-API参考-04-钩子(Hooks)

    目录 钩子(Hooks) 引导时的Hook方法 初始化时的Hook方法 测试运行时的Hook方法 收集用例时的Hook方法 生成测试结果时的Hook方法 调试/交互Hook方法 返回: Pytest权 ...

  3. Pytest权威教程18-插件编写

    [TOC] 返回: Pytest权威教程 插件编写 很容易为你自己的项目实现[本地conftest插件或可以在许多项目中使用的可[安装的插件,包括第三方项目.如果你只想使用但不能编写插件,请参阅[安装 ...

  4. Pytest权威教程21-API参考-03-夹具(Fixtures)

    目录 夹具(Fixtures) @ pytest.fixture config.cache的 capsys capsysbinary capfd capfdbinary doctest_namespa ...

  5. Pytest权威教程01-安装及入门

    目录 安装及入门 安装 Pytest 创建你的第一个测试用例 执行多条测试用例 断言抛出了指定异常 使用类组织多条测试用例 函数测试中请求使用独立的临时目录 进一步阅读 返回: Pytest权威教程 ...

  6. Pytest权威教程14-缓存:使用跨执行状态

    目录 缓存:使用跨执行状态 使用方法 首先只重新运行故障或故障 上次运行中没有测试失败时的行为 新的config.cache对象 检查缓存内容 清除缓存内容 逐步修复失败用例 unittest.Tes ...

  7. Pytest权威教程21-API参考-01-函数(Functions)

    目录 函数(Functions) pytest.approx pytest.fail pytest.skip pytest.importorskip pytest.xfail pytest.exit ...

  8. Pytest权威教程26-示例和自定义技巧

    目录 示例和自定义技巧 返回: Pytest权威教程 示例和自定义技巧 这是一个(不断增长的)示例列表.如果你需要更多示例或有疑问,请联系我们.另请参阅包含许多示例代码段的 综合文档.此外,stack ...

  9. Pytest权威教程19-编写钩子(Hooks)方法函数

    目录 编写钩子(Hooks)函数 钩子函数验证和执行 firstresult: 遇到第一个有效(非None)结果返回 hookwrapper:在其他钩子函数周围执行 钩子(Hooks)函数排序/调用示 ...

随机推荐

  1. K8S conul部署

    官网有Helm方式的安装文档(https://www.consul.io/docs/platform/k8s/index.html) 一,准备工作: 1,k8s环境 2,nfs服务器 二,创建PV n ...

  2. 11.15java实习生面试总结

    坐了两个小时的车,到了面试地点面了十五分钟左右就结束了,心里有一点难受,不过这也是刚开始,后面的路还长着呢,所以先把面试官问的题目记录下来. 1.C语言能否跨平台? 虽然我面的是java实习生,但是因 ...

  3. Sqlite in flutter, how database assets work

    First off, you will need to construct a sqlite database from your csv. This can be done in the follo ...

  4. react之高阶组件(二)

    高阶组件的使用 接上文———— 一.像函数一样直接调用 import React, { Component } from 'react' import A from './A' class C ext ...

  5. mysql 表关系 与 修改表结构

    目录 mysql 表关系 与 修改表结构 两张表关系 分析步骤 修改表结构 mysql 表关系 与 修改表结构 两张表关系 多对一 以员工和部门举例 多个员工对应一个部门 foreign key 永远 ...

  6. Redis 学习-Redis 的其他功能

    一.慢查询 找到 系统中瓶颈的命令 1. 客户端请求的生命周期: ①. 慢查询通常发生在第三阶段. ②. 客户端超时不一定是慢查询,但慢查询是客户端超时的一个可能因素. 2. 相关配置 慢查询命令会存 ...

  7. MySQL 空事务

    问题描述;    研发同事反应MySQL数据库有锁,检查innodb_trx时,发现有很多长时间未结束的空事务.    这些事务的trx_mysql_thread_id都为0,因此不能通过kill   ...

  8. Docker——概念学习

    百度百科概念: Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化.容器是完全 ...

  9. P1903 [国家集训队]数颜色 / 维护队列(带修莫队)

    题目描述: 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. ...

  10. vscode常用快捷键总结

    记住快捷键能够提高工作效率 Ctrl+Shift+P,F1 展示全局命令面板 Ctrl+P 快速打开最近打开的文件 Ctrl+Shift+N 打开新的编辑器窗口 Ctrl+Shift+W 关闭编辑器 ...