我有一个 python 测试,它使用固定装置作为凭据(用户 ID 和密码的元组)
def test_something(credentials)
(userid, password) = credentials
print("Hello {0}, welcome to my test".format(userid))
我有用于凭证的 pytest 固定装置:
@pytest.fixture()
def credentials():
return ("my_userid", "my_password")
效果很好
现在我想将其扩展到多个凭据(例如登台和生产),以便我的测试将运行两次(登台和生产各一次)。
我以为参数化就是答案,但似乎我无法用夹具进行参数化。
我很想做这样的事情:
@pytest.fixture(params=[staging_credentials, production_credentials])
def credentials(request):
return request.param
其中 staging_credentials 和 production_credentials 都是固定装置:
@pytest.fixture()
def staging_credentials():
return ("staging_userid", "staging_password")
@pytest.fixture()
def production_credentials():
return ("prod_userid", "prod_password")
但显然该灯具的参数不能是其他灯具。
关于如何优雅地处理这个问题有什么建议吗? 我看过https://docs.pytest.org/en/latest/proposals/parametrize_with_fixtures.html但这似乎太暴力了。
谢谢! 史蒂夫
间接参数化就是答案。因此,灯具的参数可以是其他灯具(按名称/代码)。
import pytest
all_credentials = {
'staging': ('user1', 'pass1'),
'prod': ('user2', 'pass2'),
}
@pytest.fixture
def credentials(request):
return all_credentials[request.param]
@pytest.mark.parametrize('credentials', ['staging', 'prod'], indirect=True)
def test_me(credentials):
pass
从技术上讲,你不仅可以通过其键获取字典值,还可以根据
credentials
生成request.param
结果,并且此参数将是传递给测试的同名参数的值。
如果您想使用其他灯具(可能是因为安装/拆卸阶段,因为这是这样做的唯一原因):
import pytest
@pytest.fixture
def credentials(request):
return request.getfuncargvalue(request.param)
@pytest.fixture()
def staging_credentials():
return ("staging_userid", "staging_password")
@pytest.fixture()
def production_credentials():
return ("prod_userid", "prod_password")
@pytest.mark.parametrize('credentials', ['staging_credentials', 'production_credentials'], indirect=True)
def test_me(credentials):
pass
这里,
request.getfuncargvalue(...)
将通过灯具名称动态返回灯具值。
这是使用我创建的新 pytest 插件 pytest-fixture-forms 的更简单的解决方案:
from pytest_fixture_forms import FixtureForms
import pytest
class Credentials(FixtureForms):
@pytest.fixture
def staging(self):
return ("staging_userid", "staging_password")
@pytest.fixture
def production(self):
return ("prod_userid", "prod_password")
def test_something(credentials):
userid, password = credentials.value
print(f"Hello {userid}, welcome to my test")
虽然间接参数化有效,但与使用 pytest-fixture-forms 相比,它有几个缺点:
credentials.form
了解您是否正在使用“登台”或“生产”凭证进行测试:def test_something(credentials):
userid, password = credentials.value
if credentials.form == "staging":
assert userid.startswith("staging_")
如果您只想使用特定凭据运行测试(就像间接示例那样),您仍然可以这样做:
@pytest.mark.parametrize("credentials_form", ["staging"]) # Only test staging
def test_something(credentials):
userid, password = credentials.value
该插件在内部处理所有复杂性,同时为您的测试提供更简单、更直观的 API。
安装插件:
pip install pytest-fixture-forms