[英]Python Testing: Seeding a database from Pytest fixture
I am currently trying to follow a wonderful tutorial around setting up and tearing down databases in a testing environment.我目前正在尝试遵循一个关于在测试环境中设置和拆除数据库的精彩教程。 Everything works well except for the
seed_database()
call which throws the following error.除了引发以下错误的
seed_database()
调用外,一切都运行良好。
AttributeError: 'function' object has no attribute 'add'
Some questions:一些问题:
db_session
even defined when I run seed_database
?db_session
时甚至定义了seed_database
? It's not being passed in anywhere... My initial guess was that it has something to do with the way Python fixtures work, but it seems a little magical.db_session
to actually be a proper scoped_session?db_session
进行哪些更改才能真正成为正确的 scoped_session? test_config.py
@pytest.fixture(scope="session")
def connection():
engine = create_engine(
"mysql+mysqldb://{}:{}@{}:{}/{}".format(
os.environ.get('TEST_DB_USER'),
os.environ.get('TEST_DB_PASSWORD'),
os.environ.get('TEST_DB_HOST'),
os.environ.get('TEST_DB_PORT'),
os.environ.get('TEST_DB_NAME'),
)
)
return engine.connect()
def seed_database():
users = [
{
"id": 1,
"name": "John Doe",
},
# ...
]
for user in users:
db_user = User(**user)
db_session.add(db_user)
db_session.commit()
@pytest.fixture(scope="session")
def setup_database(connection):
models.Base.metadata.bind = connection
models.Base.metadata.create_all()
seed_database()
yield
models.Base.metadata.drop_all()
@pytest.fixture
def db_session(setup_database, connection):
transaction = connection.begin()
yield scoped_session(
sessionmaker(autocommit=False, autoflush=False, bind=connection)
)
transaction.rollback()
test_user.py
from tests.test_config import db_session, setup_database, connection
def test_something(db_session):
# Some code here...
Why is db_session even defined when I run seed_database?
为什么在我运行seed_database 时甚至定义了db_session?
In Python functions are objects like other.在 Python 中,函数是像其他对象一样的对象。 Hence the 'function' object in the error message.
因此错误消息中的“函数”对象。
db_session
is defined in the module and therefore is accessible within seed_database
. db_session
在模块中定义,因此可以在seed_database
中访问。 The only "magic" is that you actually cannot call db_session
because Pytest fixtures cannot be called directly.唯一的“魔力”是您实际上无法调用
db_session
,因为无法直接调用 Pytest 固定装置。
What changes can I make for db_session to actually be a proper scoped_session?
我可以对 db_session 进行哪些更改才能真正成为正确的 scoped_session?
I think that you might have a "chicken and egg" situation: db_session
uses setup_database
fixture which calls seed_database
which requires db_session
to already return the session.我认为您可能会遇到“鸡和蛋”的情况:
db_session
使用setup_database
固定装置,它调用了需要seed_database
已经返回会话的db_session
。 You would need to reorganise the code to get out of this.您需要重新组织代码才能摆脱这种情况。
Without being familiar with the database sessions that you are using it's a bit of a guess work for me but maybe something like this would work:在不熟悉您正在使用的数据库会话的情况下,这对我来说有点猜测,但也许这样的事情会起作用:
def seed_database(db_session):
users = [
{
"id": 1,
"name": "John Doe",
},
# ...
]
for user in users:
db_user = User(**user)
db_session.add(db_user)
db_session.commit()
@pytest.fixture
def db_session(setup_database, connection):
transaction = connection.begin()
session = scoped_session(
sessionmaker(autocommit=False, autoflush=False, bind=connection)
)
seed_database(db_session=session)
yield session
transaction.rollback()
...and you would remove seed_database()
call from setup_database
. ...并且您将从
setup_database
中删除seed_database()
调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.