带有动态参数的pytest堆栈参数化装饰器
pytest stack parametrize decorators with dynamic parameters
我是 pytest 的新手,所以请多多包涵。
我正在尝试使用堆栈参数化装饰器来测试多个组合排列,但问题是我如何使用堆栈中其他参数化装饰器的值。
我找到了以下内容:但这不是我要找的东西
Using fixtures in pytest.mark.parametrize\
这就是我要实现的目标:
@pytest.mark.parametrize("environment", ["main", "develop", "ci"])
@pytest.mark.parametrize("model", get_models())
@pytest.mark.parametrize("id", get_ids(environment, model)) #here i tried to use the returned values of environment and model from the above decorators
def test_ids(environment, model, id):
another_method(environment, model, id)
# some logic here
get_ids()
returns 基于给定 environment
和 model
.
的 ID 列表
此解决方案不起作用,因为它为 environment
和 model
引发了未解决的引用错误
我想使用 parametrize 装饰器的原因是因为我需要测试 environments
、models
和 ids
的所有排列,但希望 pytest 生成单独的测试对于每个组合。
我目前的解决方案是:
@pytest.mark.parametrize("environment", ["main", "develop", "ci"])
@pytest.mark.parametrize("model", get_models())
def test_ids(environment, model):
ids = get_ids(environment, model)
for id in ids:
another_method(environment, model, id)
# some logic here
这个解决方案有效,但是每个测试都非常长,因为它在一长串 id 上循环,
我更喜欢 运行 多个小测试,而不是更少但很长的测试。
这使得理解测试中发生的事情变得更加困难。
有什么建议吗?
我可以想到一种涉及使用挂钩的方法。它涉及使用 pytest_generate_tests
挂钩,因为这允许我们参数化测试。
我的test_id
脚本是这样设置的
def get_models():
return [1,2]
class TestEnvModelIds:
envs = ["main", "develop", "ci"]
model = get_models()
def test_ids(self, environment, model, id):
pass
请注意,我们已将测试放在 class 中,这很重要,因为我们希望稍后从挂钩中访问那些 class 属性。
真正的魔法发生在下面的函数中,我们把它放在我们测试目录根目录的 conftest.py
中。我已经为 get_models
和 get_ids
创建了玩具示例来说明这种方法是可行的。您的实际用例可能略有不同,因为您可能需要从您实际测试的项目中导入这些功能。
def get_ids(env, model):
data = {
"main": {
1: ["a", "b"],
2: ["c", "d"]
},
"develop": {
1: ["e", "f"],
2: ["g", "h"]
},
"ci": {
1: ["i", "j"],
2: ["k", "l"]
}
}
return data[env][model]
def pytest_generate_tests(metafunc):
if "TestEnvModelIds" == metafunc.cls.__qualname__:
envs = metafunc.cls.envs
models = metafunc.cls.model
argnames = metafunc.fixturenames
argvalues = []
for env in envs:
for model in models:
ids = get_ids(env, model)
for id_ in ids:
argvalues.append((env, model, id_))
metafunc.parametrize(argnames, argvalues, scope="class")
pytest_generate_tests
中发生的事情是我们遍历环境,然后是模型,最后是 ID。我们创建了这些三元组的列表,然后最终用它们参数化我们的测试。
当我们 运行 冗长的测试套件时,我们可以看到我们成功地生成了所需的所有可能的测试组合。
====================================== test session starts =======================================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /Users/DmitryPolonskiy/Desktop/so/bin/python3.9
cachedir: .pytest_cache
rootdir: ***
collected 12 items
tests/test_models.py::TestEnvModelIds::test_ids[main-1-a] PASSED [ 8%]
tests/test_models.py::TestEnvModelIds::test_ids[main-1-b] PASSED [ 16%]
tests/test_models.py::TestEnvModelIds::test_ids[main-2-c] PASSED [ 25%]
tests/test_models.py::TestEnvModelIds::test_ids[main-2-d] PASSED [ 33%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-1-e] PASSED [ 41%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-1-f] PASSED [ 50%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-2-g] PASSED [ 58%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-2-h] PASSED [ 66%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-1-i] PASSED [ 75%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-1-j] PASSED [ 83%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-2-k] PASSED [ 91%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-2-l] PASSED [100%]
======================================= 12 passed in 0.04s =======================================
我是 pytest 的新手,所以请多多包涵。
我正在尝试使用堆栈参数化装饰器来测试多个组合排列,但问题是我如何使用堆栈中其他参数化装饰器的值。
我找到了以下内容:但这不是我要找的东西
Using fixtures in pytest.mark.parametrize\
这就是我要实现的目标:
@pytest.mark.parametrize("environment", ["main", "develop", "ci"])
@pytest.mark.parametrize("model", get_models())
@pytest.mark.parametrize("id", get_ids(environment, model)) #here i tried to use the returned values of environment and model from the above decorators
def test_ids(environment, model, id):
another_method(environment, model, id)
# some logic here
get_ids()
returns 基于给定 environment
和 model
.
的 ID 列表
此解决方案不起作用,因为它为 environment
和 model
我想使用 parametrize 装饰器的原因是因为我需要测试 environments
、models
和 ids
的所有排列,但希望 pytest 生成单独的测试对于每个组合。
我目前的解决方案是:
@pytest.mark.parametrize("environment", ["main", "develop", "ci"])
@pytest.mark.parametrize("model", get_models())
def test_ids(environment, model):
ids = get_ids(environment, model)
for id in ids:
another_method(environment, model, id)
# some logic here
这个解决方案有效,但是每个测试都非常长,因为它在一长串 id 上循环,
我更喜欢 运行 多个小测试,而不是更少但很长的测试。
这使得理解测试中发生的事情变得更加困难。
有什么建议吗?
我可以想到一种涉及使用挂钩的方法。它涉及使用 pytest_generate_tests
挂钩,因为这允许我们参数化测试。
我的test_id
脚本是这样设置的
def get_models():
return [1,2]
class TestEnvModelIds:
envs = ["main", "develop", "ci"]
model = get_models()
def test_ids(self, environment, model, id):
pass
请注意,我们已将测试放在 class 中,这很重要,因为我们希望稍后从挂钩中访问那些 class 属性。
真正的魔法发生在下面的函数中,我们把它放在我们测试目录根目录的 conftest.py
中。我已经为 get_models
和 get_ids
创建了玩具示例来说明这种方法是可行的。您的实际用例可能略有不同,因为您可能需要从您实际测试的项目中导入这些功能。
def get_ids(env, model):
data = {
"main": {
1: ["a", "b"],
2: ["c", "d"]
},
"develop": {
1: ["e", "f"],
2: ["g", "h"]
},
"ci": {
1: ["i", "j"],
2: ["k", "l"]
}
}
return data[env][model]
def pytest_generate_tests(metafunc):
if "TestEnvModelIds" == metafunc.cls.__qualname__:
envs = metafunc.cls.envs
models = metafunc.cls.model
argnames = metafunc.fixturenames
argvalues = []
for env in envs:
for model in models:
ids = get_ids(env, model)
for id_ in ids:
argvalues.append((env, model, id_))
metafunc.parametrize(argnames, argvalues, scope="class")
pytest_generate_tests
中发生的事情是我们遍历环境,然后是模型,最后是 ID。我们创建了这些三元组的列表,然后最终用它们参数化我们的测试。
当我们 运行 冗长的测试套件时,我们可以看到我们成功地生成了所需的所有可能的测试组合。
====================================== test session starts =======================================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /Users/DmitryPolonskiy/Desktop/so/bin/python3.9
cachedir: .pytest_cache
rootdir: ***
collected 12 items
tests/test_models.py::TestEnvModelIds::test_ids[main-1-a] PASSED [ 8%]
tests/test_models.py::TestEnvModelIds::test_ids[main-1-b] PASSED [ 16%]
tests/test_models.py::TestEnvModelIds::test_ids[main-2-c] PASSED [ 25%]
tests/test_models.py::TestEnvModelIds::test_ids[main-2-d] PASSED [ 33%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-1-e] PASSED [ 41%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-1-f] PASSED [ 50%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-2-g] PASSED [ 58%]
tests/test_models.py::TestEnvModelIds::test_ids[develop-2-h] PASSED [ 66%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-1-i] PASSED [ 75%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-1-j] PASSED [ 83%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-2-k] PASSED [ 91%]
tests/test_models.py::TestEnvModelIds::test_ids[ci-2-l] PASSED [100%]
======================================= 12 passed in 0.04s =======================================