Pytest插件,用于根据有趣的模式断言数据。

pytest-voluptuous的Python项目详细描述


pytest volupturous

a pytest 用于断言数据的插件 性感的 模式。

常见的用例是验证http api响应(在功能测试中):

importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()

如果验证失败,则比较返回 false 并断言失败,打印错误详细信息:

E       AssertionError: assert failed to validation error(s):
E         - info.platform: not a valid value for dictionary value @ data[u'info'][u'platform']
E         - info.description: length of value must be at most 10 for dictionary value @ data[u'info'][u'description']
E         - info.downloads: expected list for dictionary value @ data[u'info'][u'downloads']
E         - info.classifiers: expected dict for dictionary value @ data[u'info'][u'classifiers']
E         - urls: expected int for dictionary value @ data[u'urls']

安装

适用于Python2.7和3.4+:

pip install pytest-voluptuous

更改日志

请参见更改日志。

功能

  • 提供 实用程序模式 s 精确 部分 )以减少样板文件。
  • 实现一个pytest钩子来提供关于 断言 失败的错误详细信息。
  • 打印描述性验证 失败消息
  • 等于 无序的 验证器(有助于丰富的项目,在0.10+中可用)。
为什么?

因为写作:

< Buff行情>
>>> r = {'info': {'package_url': 'http://pypi.python.org/pypi/pytest'}}
>>> assert 'info' in r
>>> assert 'package_url' in r['info']
>>> assert r['info']['package_url'] == 'http://pypi.python.org/pypi/pytest'

…太烦人了。

为什么不将json模式 json模式 ?太冗长,太不方便。json模式永远不会 与能够利用平台优点的验证库的便利性相匹配。

为什么不去别的图书馆?没有特别的原因-但是它很容易使用和理解。此外, 语法非常简洁。

用法

简介

从指定模式开始:

< Buff行情>
>>> from pytest_voluptuous import S, Partial, Exact
>>> from voluptuous.validators import All, Length
>>> schema = S({
...     'info': Partial({
...         'package_url': 'http://pypi.python.org/pypi/pytest',
...         'platform': 'unix',
...         'description': Length(min=100),
...         'downloads': dict,
...         'classifiers': list,
...     }),
...     'urls': list
... })

然后加载数据以验证:

< Buff行情>
>>> import requests
>>> data = requests.get('https://pypi.python.org/pypi/pytest/json').json()

现在,如果断言这一点,数据将根据架构进行验证,但是比较并没有引起错误 将只计算为 false 这将使断言失败:

< Buff行情>
>>> assert data == schema
Traceback (most recent call last):
    ...
AssertionError

现在,如果数据与模式不匹配,那么获取断言错误(assertionerror)就不是很好了,但是不用担心 在这里没有pytest魔法,但是一旦你运行pytest,你会得到:

E       AssertionError: assert failed to validation error(s):
E         - info.platform: not a valid value for dictionary value @ data[u'info'][u'platform']
E         - info.description: length of value must be at most 10 for dictionary value @ data[u'info'][u'description']
E         - info.downloads: expected list for dictionary value @ data[u'info'][u'downloads']
E         - info.classifiers: expected dict for dictionary value @ data[u'info'][u'classifiers']
E         - urls: expected int for dictionary value @ data[u'urls']

详细信息

使用 = 运算符进行精确验证:

< Buff行情>
>>> data = {'foo': 1, 'bar': True}
>>> S({'foo': 1, 'bar': True}) == data
True

在这些示例中,我们省略了assert(以便更容易地进行诊断)。

使用 <;= 执行 部分验证(允许额外的键,即):

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
0

您选择的运算符将被继承,因此测试数据为:

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
1

使用 = 还必须在嵌套上下文中提供精确值

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
2

<;= 表示部分匹配:

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
3

当需要混合和匹配运算符时,可以使用 partial

松开匹配 < Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
4

并严格地使用 精确的

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
5

记住,匹配模式是继承的,因此您可能会做如下事情:

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
6

不存在 >;= 。如果要声明可能丢失的架构键,请使用可选的

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
7

或者,如果您想使所有键都是可选的,则覆盖 必需的

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
8

在这些情况下,如果要 需要一个键:

< Buff行情>
importrequestsfrompytest_voluptuousimportS,Partial,Exactfromvoluptuous.validatorsimportAll,Lengthdeftest_pypi():resp=requests.get('https://pypi.python.org/pypi/pytest/json')assertS({'info':Partial({'package_url':'http://pypi.python.org/pypi/pytest','platform':'INVALID VALUE','description':Length(max=10),'downloads':list,'classifiers':dict,}),'urls':int})==resp.json()
9

就这样。对于可用的验证程序,请查看 有趣的文档

有问题

性感的0.9.3及更早版本:

在volupturous pre-0.10.2 [] 中,匹配任何列表,而不是空列表。若要声明空列表,请使用等于([])

类似地,在volupturouspre-0.10.2中, {} 并不总是与空的dict匹配。 模式({…}, extra=prevent廑extra) (或 exact ), {} 确实与 {} 完全匹配。但是,在里面 模式({…}, extra=allow_extra)(或``partial ),它匹配 any dict(因为允许任何额外的键)。 若要声明空dict,请使用 等于({})

性感的0.10.0+:

在volupturous 0.10.0+ {} [] 中,计算为 empty dict和 empty list,因此您不需要以上的解决方法。

始终使用 dict list 来验证任何大小的dict或list。它的工作原理与性感版不同。

任何版本:

[str,int] 匹配同时包含字符串和int的任何列表(以任何顺序和1-n次)。验证 包含这些类型的固定长度列表,使用 ExactSequence([str, int]) 无序([str, int]) 当命令没有意义的时候。您还可以使用这些函数中的值,如exactsequence([2,3])

许可证

Apache2.0许可。有关详细信息,请参见许可证。

更改日志

1.1.0(2018-10-31)

新的

  • 3 : 在错误消息中包含实际值以便于调试(并删除错误消息中错误路径的重复)。 感谢 @turbo87

修复

    <HREF="https://github.com/f-secure/pytest-voluptuous/pull/4/commits/404407fdd554cdbe17323f1cc935225bb429b29d" rel="nofollow">提交: 如果路径为空(当错误位于"主级别"时),则跳过错误输出中的路径前缀。 感谢 @turbo87

1.0.2(2018-02-16)

修复

1.0.1(2017-01-10)

第一个公共版本。

1.0.0(2016-12-07)

第一版。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
试图读取字段“java”。lang.反对安卓。util。一对首先   gradle对java的影响。属性作为任务的输入?   java我的return语句不起作用。我做错了什么?   java通用同步代码块[无对象锁定]   macos Java小程序游戏不能在Mac上运行,即使它可以在PC上运行   java Firebase GeoFire设置位置未在服务中工作   java排序字符串对象   java通过JLabel上传背景图像(jpg)后,如何将图像缩放到它所在的面板上?   java无法连接到jsp中的数据库   java如何在整个ant taskdef操作的执行过程中拥有一个singleton类实例   java如何在按键事件中检查JTtextField中的字符串数字验证器   如何最好地输出大型单行XML文件(使用Java/Eclipse)?   内存不足,Java运行时环境无法在Java应用程序中继续运行   java Hibernate连接错误:组织上的NullPointerException。冬眠hql。阿斯特。HqlSqlWalker。createFromJoinElement   linux将参数从shell脚本传递到java类   java对于接受多个参数的setter是否有类似于@JsonCreator的注释?   java在链表中添加节点