如何为带有可选参数的函数编写测试
How to write a test for a function with optional arguments
我想测试带有可选参数的函数调用。
这是我的代码:
list_get()
list_get(key, "city", 0)
list_get(key, 'contact_no', 2, {}, policy)
list_get(key, "contact_no", 0)
list_get(key, "contact_no", 1, {}, policy, "")
list_get(key, "contact_no", 0, 888)
由于可选参数,我无法对其进行参数化,因此我为 pytest
中的每个 api 调用编写了单独的测试函数。
我相信应该有更好的方法来测试这个。
您可以使用 *
operator:
@pytest.mark.parametrize('args,expected', [
([], expVal0),
([key, "city", 0], expVal1),
([key, 'contact_no', 2, {}, policy], expVal2)
([key, "contact_no", 0], expVal3)
([key, "contact_no", 1, {}, policy, ""], expVal4)
([key, "contact_no", 0, 888], expVal5)
])
def test_list_get(args, expected):
assert list_get(*args) == expected
我认为你做的很好,但我建议传递键值参数,这样你就不会混淆参数顺序。
我假设你的函数头看起来像这样:
def list_get(key=None, city=None, contact_no=None, policy=None):
...
在您的测试中定义您要测试的参数组合列表:
kwargs = {'key': '..', 'city': '..', 'contact_no': '..', 'policy': '..'}
list_get(**kwargs)
kwargs_all_default_values = {}
list_get(**kwargs_all_default_values)
除了@forge 和@ezequiel-muns 的回答之外,我还建议使用 pyhamcrest
中的一些糖:
import pytest
from hamcrest import assert_that, calling, is_not, raises
@pytest.mark.parametrize('func, args, kwargs', [
[list_get, (), {}],
[list_get, (key, "city", 0), {}],
[list_get, (key, "contact_no", 1, {}, policy, ""), {}],
[list_get, (), {'key': key}],
])
def test_func_dont_raises(func, args, kwargs):
assert_that(calling(func).with_args(*args, **kwargs), is_not(raises(Exception)))
对于遇到此问题的未来读者,他们尝试设置 @parameterize
d 测试以生成笛卡尔参数集,有时根本不想传递给定参数(如果可选),然后使用None
值的过滤器将有助于
def function_under_test(foo="foo-default", bar="bar-default"):
print([locals()[arg] for arg in inspect.getargspec(function_under_test).args])
@pytest.mark.parametrize("foo", [None, 1, 2])
@pytest.mark.parametrize("bar", [None, "a", "b"])
def test_optional_params(foo, bar):
args = locals()
filtered = {k: v for k, v in args.items() if v is not None}
function_under_test(**filtered) # <-- Notice the double star
样本运行:
PASSED [ 11%]['foo-default', 'bar-default']
PASSED [ 22%][1, 'bar-default']
PASSED [ 33%][2, 'bar-default']
PASSED [ 44%]['foo-default', 'a']
PASSED [ 55%][1, 'a']
PASSED [ 66%][2, 'a']
PASSED [ 77%]['foo-default', 'b']
PASSED [ 88%][1, 'b']
PASSED [100%][2, 'b']
我想测试带有可选参数的函数调用。
这是我的代码:
list_get()
list_get(key, "city", 0)
list_get(key, 'contact_no', 2, {}, policy)
list_get(key, "contact_no", 0)
list_get(key, "contact_no", 1, {}, policy, "")
list_get(key, "contact_no", 0, 888)
由于可选参数,我无法对其进行参数化,因此我为 pytest
中的每个 api 调用编写了单独的测试函数。
我相信应该有更好的方法来测试这个。
您可以使用 *
operator:
@pytest.mark.parametrize('args,expected', [
([], expVal0),
([key, "city", 0], expVal1),
([key, 'contact_no', 2, {}, policy], expVal2)
([key, "contact_no", 0], expVal3)
([key, "contact_no", 1, {}, policy, ""], expVal4)
([key, "contact_no", 0, 888], expVal5)
])
def test_list_get(args, expected):
assert list_get(*args) == expected
我认为你做的很好,但我建议传递键值参数,这样你就不会混淆参数顺序。
我假设你的函数头看起来像这样:
def list_get(key=None, city=None, contact_no=None, policy=None):
...
在您的测试中定义您要测试的参数组合列表:
kwargs = {'key': '..', 'city': '..', 'contact_no': '..', 'policy': '..'}
list_get(**kwargs)
kwargs_all_default_values = {}
list_get(**kwargs_all_default_values)
除了@forge 和@ezequiel-muns 的回答之外,我还建议使用 pyhamcrest
中的一些糖:
import pytest
from hamcrest import assert_that, calling, is_not, raises
@pytest.mark.parametrize('func, args, kwargs', [
[list_get, (), {}],
[list_get, (key, "city", 0), {}],
[list_get, (key, "contact_no", 1, {}, policy, ""), {}],
[list_get, (), {'key': key}],
])
def test_func_dont_raises(func, args, kwargs):
assert_that(calling(func).with_args(*args, **kwargs), is_not(raises(Exception)))
对于遇到此问题的未来读者,他们尝试设置 @parameterize
d 测试以生成笛卡尔参数集,有时根本不想传递给定参数(如果可选),然后使用None
值的过滤器将有助于
def function_under_test(foo="foo-default", bar="bar-default"):
print([locals()[arg] for arg in inspect.getargspec(function_under_test).args])
@pytest.mark.parametrize("foo", [None, 1, 2])
@pytest.mark.parametrize("bar", [None, "a", "b"])
def test_optional_params(foo, bar):
args = locals()
filtered = {k: v for k, v in args.items() if v is not None}
function_under_test(**filtered) # <-- Notice the double star
样本运行:
PASSED [ 11%]['foo-default', 'bar-default']
PASSED [ 22%][1, 'bar-default']
PASSED [ 33%][2, 'bar-default']
PASSED [ 44%]['foo-default', 'a']
PASSED [ 55%][1, 'a']
PASSED [ 66%][2, 'a']
PASSED [ 77%]['foo-default', 'b']
PASSED [ 88%][1, 'b']
PASSED [100%][2, 'b']