我有一个类范围的参数化夹具,它为其参数获取3个数据库并返回每个数据库的连接。
类中的测试使用此fixture来测试每个数据库连接属性。
现在我有一个带有数据库表测试的新类,我想使用上面的fixture,但要在每个连接表上进行参数化。
有关pytest实现此方法的任何建议吗?我无法找到一种基于已经参数化的元素进行参数化的方法。
由于
答案 0 :(得分:2)
测试类用于:
使用pytest
这不是必需的,因为可以在夹具级别进行设置和拆卸。
出于这个原因,我的解决方案不使用类(但它可能与它们一起使用)。
要显示(假)连接已创建然后关闭,请在stdout上观察输出。诀窍是
使用@pytest.yield_fixture
,return
但不使用yield
来提供使用的值
参数注入测试用例。无论执行第一个yield
语句后是什么
作为拆解代码。
第一种情况对于py.test
是自然的,其中所有夹具变体都是组合的。
由于它有M×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 =======================================
这个想法如下:
db_connect
灯具
table_name
fixtures test_it(db_connect, table_name)
和db_connect
的正确组合调用table_name
indirect
。这根本不起作用
唯一的解决方案是使用某种明确定义哪种组合的场景 正确的。
我们必须参数化测试功能,而不是参数化灯具。
通常,参数值按原样直接传递给测试函数。如果我们想要一个夹具(命名为
作为参数名称来处理创建要使用的值,我们必须指定参数
为indirect=True
。如果我们说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))
,如果我们提供,所有参数都将以这种方式处理
参数名称列表,只有指定的参数将传递给夹具,剩下的将进入
因为他们正在进入测试功能。这里我使用间接参数的显式列表。
$ 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 =======================================
运行测试套件:
db_connect
我们认为它有效。
无论如何,有一个小问题 - export class Base {
private image: string = "img/dog.png"; // default image
// you don't need catImg and dogImg here...
// private catImg: string;
// private dogImg: string;
private currentImg: string;
private enable: boolean;
constructor() { }
onMouseOver(image) {
enable = true;
currentImg = image;
}
onMouseClick(image) {
enable = false;
currentImg = image;
}
}
范围"会话"没有荣幸,事实确实如此
在功能级别实例化和销毁。这是known issue。