简体   繁体   English

使用pytest进行测试时如何使用fixtures正确清除数据库

[英]How to properly clear database using fixtures when testing with pytest

I have a test database.我有一个测试数据库。 Let's assume there are three tables created in there:假设在那里创建了三个表:

create table users (
    id serial constraint users_pkey primary key,
    name text not null
);
create table roles (
    id serial constraint roles_pkey primary key,
    name text not null
);
create table users_roles (
    user_id int constraint users_roles_users_fkey references users(id),
    role_id int constraint users_roles_roles_fkey references roles(id)
);

Every test starts with filling the database with data using factory_boy factories.每个测试都从使用 factory_boy 工厂用数据填充数据库开始。 Typical test looks like this:典型的测试如下所示:

def test_get_user_roles(api_client):
    user = UserFactory.create(id=1)
    role = RolesFactory.create(id=1)
    users_roles = UsersRolesFactory.create(user_id=1, role_id=1)
    response = api_client.get(f"/users/{user.id}/roles")
    assert ...

I could clear table using @pytest.mark.usefixtures("clear_users_roles", "clear_users", "clear_roles"), where "clear_users_roles", "clear_users", "clear_roles" are fixtures that obviously clear tables if there were no relationships between tables.我可以使用@pytest.mark.usefixtures("clear_users_roles", "clear_users", "clear_roles") 清除表,其中“clear_users_roles”、“clear_users”、“clear_roles”是在表之间没有关系的情况下明显清除表的夹具. But in the example above there are relationships (foreign keys) between table users_roles and user and between users_roles and roles and the problem is that fixtures run out of order.但是在上面的示例中,表 users_roles 和 user 之间以及 users_roles 和roles 之间存在关系(外键),问题是装置运行失序。 So when I run my tests I get an integrity error, because, for example, fixture "clear_users" was executed before "clear_users_roles" and my RDBMS cannot delete a record because the record still references to table "users".因此,当我运行我的测试时,我得到一个完整性错误,因为例如,夹具“clear_users”在“clear_users_roles”之前执行并且我的 RDBMS 无法删除记录,因为该记录仍然引用表“users”。 Is there a proper way to run fixtures in specific order?是否有以特定顺序运行装置的正确方法? Or may be there are some patterns/best practices for case like this?或者对于这种情况可能有一些模式/最佳实践?

Have you tried using teardown code in your fixtures with yield keyword?您是否尝试过在带有 yield 关键字的装置中使用拆卸代码?

Example from pytest documentation : pytest 文档中的示例:

# content of conftest.py

import smtplib
import pytest


@pytest.fixture(scope="module")
def smtp_connection():
    smtp_connection = smtplib.SMTP("smtp.gmail.com", 587, timeout=5)
    yield smtp_connection  # provide the fixture value
    print("teardown smtp")
    smtp_connection.close()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM