测试类用于:
- 为测试用例提供设置和拆卸功能
- 在测试期间分享一些共同的价值观
With pytest
这不是必需的,因为设置和拆卸可以在夹具级别完成。
因此,我的解决方案不使用类(但它可能可以与它们一起使用)。
为了表明,(假)连接已创建,然后关闭,观察标准输出上的输出。诀窍是
使用@pytest.yield_fixture
,没有使用return
but yield
提供使用的值
注入测试用例的参数。无论先在后的是什么yield
语句被执行
作为拆解代码。
“矩形”样式:通过两个参数化夹具进行 M x N 测试运行
第一种情况很自然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))
如果您需要更多测试用例,例如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 =======================================
从一个灯具到 N 个从属灯具的“爆炸三角形”
想法如下:
- 生成几个
db_connect
夹具,使用参数化夹具
- 对于每个 db_connect 生成 N 个变体
table_name
固定装置
- have
test_it(db_connect, table_name)
仅通过适当的组合来调用db_connect
and
table_name
.
这根本行不通
唯一的解决方案是使用某种场景,明确定义哪些组合是
正确的。
“场景”:测试功能级别的间接参数化
我们必须参数化测试功能,而不是参数化夹具。
通常,参数值按原样直接传递给测试函数。如果我们想要一个固定装置(名为
作为参数名称)为了创建要使用的值,我们必须指定参数
作为indirect
。如果我们说indirect=True
,如果我们提供,所有参数都将以这种方式处理
参数名称列表,只有指定的参数将被传递到固定装置中,其余的将被传递
因为他们正在进入测试功能。这里我使用显式的间接参数列表。
import pytest
DBCFG = {"pgsql": "postgresql://scott:tiger@localhost:5432/mydatabaser",
"mysql": "mysql://scott:tiger@localhost/foo",
"oracle": "oracle://scott:[email protected] /cdn-cgi/l/email-protection: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))
运行测试套件:
$ 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:[email protected] /cdn-cgi/l/email-protection: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:[email protected] /cdn-cgi/l/email-protection:1521/sidname + tabname-by-fixture oracle-groups
PASSED
closing db oracle
====================================== 6 passed in 0.01 seconds =======================================
我们看到它有效。
无论如何,有一个小问题——db_connect
范围“会话”不被尊重,它是
在函数级别实例化和销毁。这是已知问题 https://github.com/pytest-dev/pytest/issues/570.