具有可选键的字典策略

时间:2018-05-30 11:06:29

标签: python python-3.x unit-testing testing python-hypothesis

目前我正在使用假设fixed_dictionaries策略生成一个字典,其中包含对我的应用程序有效的特定密钥和数据类型。我需要一个策略来生成这个固定的字典以及其他删除了特定键的字典。或者是带有某些最小键组的字典,带有可选的附加键,最好是以产生这些可选键的各种组合的方式。

这是需要验证的json架构的示例,带有2个可选字段。我想为此架构生成所有可能的有效数据。

'user_stub': {
    '_id':        {'type': 'string'},
    'username':   {'type': 'string'},
    'social':     {'type': 'string'},
    'api_name':   {'type':     'string',
                   'required': False},
    'profile_id': {'type':     'integer',
                   'required': False},
}

这是我提出的,但它不正确,因为它保留了键但使用None作为值,而我想要删除键。

return st.fixed_dictionaries({
    '_id':        st.text(),
    'username':   st.text(),
    'social':     st.text(),
    'api_name':   st.one_of(st.none(),
                            st.text()),
    'profile_id': st.one_of(st.none(),
                            st.integers()),
})

编辑:更新的复合策略 - >

似乎最好根据返回的数据类型分离其他可选字典,否则可能会获得值不匹配的键。

@st.composite
def generate_data(draw):
    base_data = st.fixed_dictionaries({
        '_id':      st.text(),
        'username': st.text(),
        'social':   st.text(),
    })
    optional_strs = st.dictionaries(
        keys=st.just('api_name'),
        values=st.text()
    )
    optional_ints = st.dictionaries(
        keys=st.just('profile_id'),
        values=st.integers()
    )

    b = draw(base_data)
    s = draw(optional_strs)
    i = draw(optional_ints)
    return {**b, **s, **i}  # noice

2 个答案:

答案 0 :(得分:3)

fixed_dictionaries策略中获取所需条目,并从dictionaries策略中选择可选项。然后通过merging将它们组合成一个字典。

您可以在测试中执行此操作,也可以创建一个为您执行此操作的composite strategy

答案 1 :(得分:1)

das-g提供了一个有效的解决方案!

另一种方法是

fixed_dictionaries(dict(
    required=text(),
    optional=none()|text(),  # note None first, for shrinking
)).map(
    lambda d: {k: v for k, v in d.items() if v is not None}
)