从sqlite迁移到postgres(Django)时如何更新unittests

2024-04-23 15:21:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个很大的Django项目,有很多视图/模型。我最近将我的项目从sqlite3迁移到postgres本地,并计划进一步扩展它(将postgres放在单独的机器上,等等)。你知道吗

当我从sqlite迁移到postgres时,我遵循了these instructions,它似乎工作得很好。(即,我的running应用程序看起来与db为sqlite时相同)

我的问题是:当我运行以前编写的单元测试时,第一个单元测试工作,所有正在进行的单元测试都失败。单独来说,单元测试工作得很好。我在stackoverflow上看到了一些解决这个问题的other posts,但是解决方案还不清楚。我如何为我的unittests修改我的setUp()/teardown()方法,以便它们与我新迁移的postgres db一起通过?我需要完全重写所有单元测试吗?你知道吗

我已经看到了pytest-postgresql library,尽管我不完全确定如何基于此修改我的单元测试。你知道吗

我的测试套件是用不同的类来测试视图的。比如说

class View1Tests(TestCase):
    def setUp(self):
        c1 = Category.objects.create(id=55555, leaf_node_name="Test Category 1")
        c2 = Category.objects.create(id=12345, leaf_node_name="Test Category 2")

        s1 = Search.objects.create(category=c1, username="testuser")
        s2 = Search.objects.create(category=c2, username="testuser2")


    def test_view1_success(self):
         #blablabla

    def test_view1_fail(self):
         #blablabla

    def test_view1_something(self):
         #blablabla

我遇到这样的错误:

appname.models.DoesNotExist: Search matching query does not exist.

同样,当sqlite3是db时,所有这些单元测试都运行得非常好。我认为这是一个问题与postgres测试设置?但我不知从何说起。任何帮助都将不胜感激!!你知道吗


Tags: 项目testself视图dbsearchobjectsdef
1条回答
网友
1楼 · 发布于 2024-04-23 15:21:32

我想我终于解决了问题。当尝试使用默认主键(例如MyModel.objects.get(pk=1)MyModel.objects.get(id=1))获取对象时,会出现问题。我的假设是Postgres使用串行数据类型作为AutoField,增量的值取决于Postgres生成的序列。你知道吗

我找到的解决办法非常简单。通过具有该对象唯一属性的属性获取,或者使用列表索引获取所有对象并进行筛选。后一种方法不应该太麻烦,因为在大多数情况下,会创建一些模型实例。你知道吗

下面是一个完整的例子

# models.py
class Book(models.Model):
    isbn = models.CharField(
        max_length=13,
        primary_key=True  # uniqueness is enforced
    )
    book_name = models.CharField(
        max_length=128,
        unique=True  # another unique field
    )
    author_count = models.IntegerField()
    book_genre = models.CharField(max_length=64)


# tests.py
class MyTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        # first object
        Book.objects.create(
            isbn='10101',
            book_name='Binary Code',
            author_count=1,
            book_genre='Fiction'
        )

        # second object
        Book.objects.create(
            isbn='314159',
            book_name='Life of Pi',
            author_count=1,
            book_genre='Philosophy'
        )

    def setUp(self):
        self.book1 = Book.objects.all()[0]
        # or self.book1 = Book.objects.get(isbn='10101')
        # or self.book1 = Book.objects.get(book_name='Binary Code')
        self.book2 = Book.objects.all()[1]
        # or self.book2 = Book.objects.get(isbn='314159')
        # or self.book2 = Book.objects.get(book_name='Life of Pi')

    def test_something(self):
        # lastly, since `setUp` is called before every test_* method
        # you can just access the instance's attributes without calling `get`
        # e.g:
        self.assertEqual(self.book1.book_genre, 'Fiction')

    def test_something_else(self):
        # you an also reload the instance using `refresh_from_db`
        # after making changes
        Book.objects.filter(author_count=1).update(book_genre='Fiction')
        self.book2.refresh_from_db()
        self.assertEqual(self.book2.book_genre, 'Fiction')

相关问题 更多 >