首页 > 解决方案 > 如何在每次测试后重置 Django 测试数据库 ID?

问题描述

我有一个 django 应用程序,我正在对它进行一些单元测试。所以我遇到的问题不是当一个测试插入测试数据库时。接下来是测试。由于每个测试都没有保存事务,因此前一个测试的条目不存在,这很好,尽管自动增量 id 正在增加,就好像数据库中仍有条目一样。我需要解决这个问题,因为我要插入更多数据,而我无法控制给它的 id,并且需要能够获取这些特定数据以进行测试。如果我硬编码代码以获取对象,我将不得不在每次添加新测试时更改代码,这并不理想。

我有多个测试正在运行,但为了简单起见,我将展示两个。

from django.test import TestCase
from app.models import Model

class VersionMerge(TestCase):
   fixtures = ['initial_test_data.json']

   def test_model_test1(self):
       *Insert new data*
       *grab new data in*
       *Check data*

   def test_model_test2(self):
       *Insert new data*
       *grab new data*
       *Check data*

问题出现在test_model_test2中,当我尝试获取新数据时,我必须将对象打印出来才能看到 id 才能获取它。

我有一个关于如何在实际数据库而不是测试数据库上解决此问题的解决方案。对于我来说,我需要能够连接到 docker 容器并运行 psql 命令来重置 table_id_seq。

docker exec -t  $CONTAINER_ID psql --dbname=test_database_name -username=user -c "SELECT setval('modelName_appName_id_seq', 2, true)"

这将转到表格并将最后一个 id 值设置为 2 以使下一个 id 为 3。但是,每当我尝试从 python 内部运行命令时,使用

cmd = "command above"
os.system(cmd)

当我运行它时,我收到以下错误。

sh: 1: docker: not found
sh: 1: docker: not found

寻求任何帮助,无论是解决问题的新方法还是改进我的方法。

TLDR;我需要能够修改 django 单元测试创​​建的数据库中的数据。

标签: pythondjangodatabaseshelldocker

解决方案


如果您需要测试来重置主键序列,您可以发出 RawSQL 查询来执行此操作。这个 StackOverflow 问题回答了如何做到这一点。

如果您使用的是 pytest,则可以使用更简单的选项。我们在所有 Django 项目中都使用 pytest 和 pytest-django,这让测试变得轻而易举。pytest-django 提供了一个数据库夹具,它可以采用布尔参数来重置序列。像这样使用它:

@pytest.mark.django_db(transaction=True, reset_sequences=True)
def mytest():
    [...]

推荐阅读