我有一个类范围的参数化夹具,它为其参数获取 3 个数据库并返回到每个数据库的连接。
类中的测试使用此装置来测试每个数据库连接属性。
现在我有一个带有数据库表测试的新类,我想使用上面的夹具但要在每个连接表上进行参数化。
关于实现这一点的 pytest 方式有什么建议吗?我找不到基于已经参数化的元素进行参数化的方法。
谢谢
测试类用于:
随着pytest这是没有必要的安装和拆卸能够在灯具级的完成。
出于这个原因,我的解决方案不使用类(但它可能与它们一起使用)。
为了表明,(假)连接被创建,然后关闭观察标准输出上的输出。诀窍是使用@pytest.yield_fixture,它不是使用return而是yield提供注入测试用例的参数中使用的值。第一条yield语句之后的任何内容都作为拆卸代码执行。
第一种情况很自然py.test,所有夹具变体都组合在一起。
因为它有 M x N 测试用例运行,我称之为“矩形”。
我的测试在tests/test_it.py:
import pytest
@pytest.yield_fixture(scope="class", params=["mysql", "pgsql", "firebird"])
def db_connect(request):
print("\nopening db")
yield request.param
print("closing db")
@pytest.fixture(scope="class", params=["user", "groups"])
def table_name(request):
return request.param
def test_it(db_connect, table_name):
print("Testing: {} + {}".format(db_connect, table_name))
Run Code Online (Sandbox Code Playgroud)
如果您需要更多类似的测试用例test_it,只需使用另一个名称创建它们。
运行我的测试用例::
$ py.test -sv tests
========================================= test session starts =========================================
platform linux2 -- Python 2.7.9 -- py-1.4.30 -- pytest-2.7.2 -- /home/javl/.virtualenvs/stack/bin/python2
rootdir: /home/javl/sandbox/stack/tests, inifile:
collected 6 items
tests/test_it.py::test_it[mysql-user]
opening db
Testing: mysql + user
PASSEDclosing db
tests/test_it.py::test_it[pgsql-user]
opening db
Testing: pgsql + user
PASSEDclosing db
tests/test_it.py::test_it[pgsql-groups]
opening db
Testing: pgsql + groups
PASSEDclosing db
tests/test_it.py::test_it[mysql-groups]
opening db
Testing: mysql + groups
PASSEDclosing db
tests/test_it.py::test_it[firebird-groups]
opening db
Testing: firebird + groups
PASSEDclosing db
tests/test_it.py::test_it[firebird-user]
opening db
Testing: firebird + user
PASSEDclosing db
====================================== 6 passed in 0.01 seconds =======================================
Run Code Online (Sandbox Code Playgroud)
思路如下:
db_connect使用参数化夹具生成几个夹具table_name夹具变体test_it(db_connect, table_name)只有通过适当的combinatins被称为db_connect和
table_name。这根本行不通
唯一的解决方案是使用某种场景,这些场景明确定义了哪些组合是正确的。
我们必须参数化测试函数,而不是参数化装置。
通常,参数值按原样直接传递给测试函数。如果我们想要一个fixture(命名为参数名称)来负责创建要使用的值,我们必须将参数指定为indirect。如果我们说indirect=True,所有参数都将被这样处理,如果我们提供参数名称列表,则只有指定的参数将被传递到fixture,其余的将按原样进入测试函数。在这里,我使用了间接参数的显式列表。
import pytest
DBCFG = {"pgsql": "postgresql://scott:tiger@localhost:5432/mydatabaser",
"mysql": "mysql://scott:tiger@localhost/foo",
"oracle": "oracle://scott:tiger@127.0.0.1:1521/sidname"
}
@pytest.yield_fixture(scope="session")
def db_connect(request):
connect_name = request.param
print("\nopening db {connect_name}".format(connect_name=connect_name))
assert connect_name in DBCFG
yield DBCFG[connect_name]
print("\nclosing db {connect_name}".format(connect_name=connect_name))
@pytest.fixture(scope="session")
def table_name(request):
return "tabname-by-fixture {request.param}".format(request=request)
scenarios = [
("mysql", "myslq-user"),
("mysql", "myslq-groups"),
("pgsql", "pgsql-user"),
("pgsql", "pgsql-groups"),
("oracle", "oracle-user"),
("oracle", "oracle-groups"),
]
@pytest.mark.parametrize("db_connect,table_name",
scenarios,
indirect=["db_connect", "table_name"])
def test_it(db_connect, table_name):
print("Testing: {} + {}".format(db_connect, table_name))
Run Code Online (Sandbox Code Playgroud)
运行测试套件:
$ py.test -sv tests/test_indirect.py
py.test========================================= test session starts ==================================
=======
platform linux2 -- Python 2.7.9, pytest-2.8.7, py-1.4.31, pluggy-0.3.1 -- /home/javl/.virtualenvs/stack
/bin/python2
cachedir: tests/.cache
rootdir: /home/javl/sandbox/stack/tests, inifile:
collected 6 items
tests/test_indirect.py::test_it[mysql-myslq-user]
opening db mysql
Testing: mysql://scott:tiger@localhost/foo + tabname-by-fixture myslq-user
PASSED
closing db mysql
tests/test_indirect.py::test_it[mysql-myslq-groups]
opening db mysql
Testing: mysql://scott:tiger@localhost/foo + tabname-by-fixture myslq-groups
PASSED
closing db mysql
tests/test_indirect.py::test_it[pgsql-pgsql-user]
opening db pgsql
Testing: postgresql://scott:tiger@localhost:5432/mydatabaser + tabname-by-fixture pgsql-user
PASSED
closing db pgsql
tests/test_indirect.py::test_it[pgsql-pgsql-groups]
opening db pgsql
Testing: postgresql://scott:tiger@localhost:5432/mydatabaser + tabname-by-fixture pgsql-groups
PASSED
closing db pgsql
tests/test_indirect.py::test_it[oracle-oracle-user]
opening db oracle
Testing: oracle://scott:tiger@127.0.0.1:1521/sidname + tabname-by-fixture oracle-user
PASSED
closing db oracle
tests/test_indirect.py::test_it[oracle-oracle-groups]
opening db oracle
Testing: oracle://scott:tiger@127.0.0.1:1521/sidname + tabname-by-fixture oracle-groups
PASSED
closing db oracle
====================================== 6 passed in 0.01 seconds =======================================
Run Code Online (Sandbox Code Playgroud)
我们看到它有效。
无论如何,有一个小问题 -db_connect范围“会话”不受尊重,它在函数级别被实例化和销毁。这是已知问题。
| 归档时间: |
|
| 查看次数: |
2221 次 |
| 最近记录: |