使用假设和py.test来测试python中的复合策略,我必须一次测试一个吗?

时间:2017-09-21 19:05:39

标签: python unit-testing pytest python-hypothesis

我有3个文件,module.py,其中包含一个测试输入是否为数字的示例函数。我有一个名为test_mymodule_long.py的文件成功测试并使用 py.test hypothesis 传递了几种类型的输入。我正在使用Python 3.6,但这不重要(如果你不是,只需删除类型提示)。对于这个特殊功能,将这些分开对我来说没有帮助;如果假设找到边缘情况,我只想知道有问题的输入和引发的异常。因此,我想按照test_mymodule_short.py中的说明编写此测试,但这不起作用。

我的问题是:有没有办法在假设中比在test_mymodule_long.py中更有效地编写策略?

以下是每个文件中的代码:

'''
mymodule.py
'''

from typing import Union

Number = Union[int, float]


def is_numeric(x: Number):
    try:
        y = float(x)
        return True
    except:
        return False

# -------------------------------------------

'''
test_mymodule_long.py [This code works]
(using pytest to discover tests automatically)
'''
from hypothesis import given, example
import hypothesis.strategies as st
import mymodule

@given(st.integers())
def test_is_numeric_integer(num):
    result = stats.is_numeric(num)
    assert isinstance(result, bool)


@given(st.floats())
def test_is_numeric_float(num):
    result = stats.is_numeric(num)
    assert isinstance(result, bool)


@given(st.text())
def test_is_numeric_text(num):
    result = stats.is_numeric(num)
    assert isinstance(result, bool)


@given(st.lists(st.floats()))
def test_is_numeric_list(num):
    result = stats.is_numeric(num)
    assert isinstance(result, bool)

# -------------------------------------------

'''
test_mymodule_short.py [This code fails!]
(using pytest to discover tests automatically)
'''
from hypothesis import given, example
import hypothesis.strategies as st
import mymodule

@given(st.integers())
@given(st.floats())
@given(st.text())
@given(st.lists(st.floats()))
def test_is_numeric_list(num):
    result = mymodule.is_numeric(num)
    assert isinstance(result, bool)

请注意,我不认为错误信息在这里真的很重要,它更像是一个 this-not-how-you-do-it 的情况,我正在就是否有一种紧凑的方法来测试一个具有多个假设策略的函数。另外,我知道正确的is_numeric函数将被编程不同(假设你甚至需要这样的函数)。我也知道这里指出的测试不够完整,无法知道它是否有效。这些只是让我的问题清楚的例子。

1 个答案:

答案 0 :(得分:4)

单一测试无法使用多种策略,但可以将多种策略合并为一种策略并在测试中使用 - one_of策略。所以你可以写下面的内容:

from hypothesis import given, example
import hypothesis.strategies as st
import mymodule

@given(st.one_of(
    st.integers(), 
    st.floats(),
    st.text(),
    st.lists(st.floats()),
))
def test_is_numeric_list(num):
    result = mymodule.is_numeric(num)
    assert isinstance(result, bool)