每次测试后如何重置 Django 测试数据库 ID?

Rya*_*n w 7 python database django shell docker

我有一个 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*
Run Code Online (Sandbox Code Playgroud)

问题出现在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)"
Run Code Online (Sandbox Code Playgroud)

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

cmd = "command above"
os.system(cmd)
Run Code Online (Sandbox Code Playgroud)

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

sh: 1: docker: not found
sh: 1: docker: not found
Run Code Online (Sandbox Code Playgroud)

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

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

小智 7

TestCase我通过替换TransactionTestCase和 set来使其工作reset_sequences=True。然而测试运行速度较慢。

from django.test import TransactionTestCase

class ViewTest(TransactionTestCase):
    reset_sequences = True

    def test_view_redirects(self):
       ...
Run Code Online (Sandbox Code Playgroud)

这是文档


jnn*_*nns 6

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

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

@pytest.mark.django_db(transaction=True, reset_sequences=True)
def mytest():
    [...]
Run Code Online (Sandbox Code Playgroud)


Han*_*nny 1

您正在使用固定装置文件 - 将您想要的任何数据放在那里;然后根据需要在测试中编辑它。

虽然,这更难维护。在我看来 - 有更好的选择,可能更符合您的预期。

您最好使用类似的方法factory_boy并在实例化时使用您提供的虚拟数据生成模型(以及相关的外键)。

这样您就可以准确地知道正在测试的内容,并且它完全独立于其他一切。好的部分是,与使用某些固定装置相比factory_boy,您将拥有一个factories.py可以更轻松地保持最新状态的文件。

还有其他选项,例如Mixermodel_mommy,尽管我只有factory_boy和 的经验mixer

factory_boy可能看起来像这样:

   def test_model_test1(self):
       factory.ModelFactory(
       some_specific_attribute='some_specific_value'
       )
       model = Model.objects.all().first()
       # Test against your model
Run Code Online (Sandbox Code Playgroud)