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

Python 从sqlite迁移到postgres(django)时如何更新unittests,python,django,postgresql,python-unittest,pytest-django,Python,Django,Postgresql,Python Unittest,Pytest Django,我有一个很大的Django项目,有很多视图/模型。我最近将我的项目从sqlite3迁移到本地postgres,并计划进一步扩展(将postgres放在单独的机器上,等等) 当我从sqlite迁移到postgres时,我遵循了这一点,它似乎工作得非常完美。(也就是说,我的跑步应用程序看起来与数据库使用sqlite时完全相同) 我的问题是:当我运行以前编写的单元测试时,第一个单元测试工作正常,所有正在进行的单元测试都失败。单独而言,单元测试工作良好。我在stackoverflow上看到了一些解决这个

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

当我从sqlite迁移到postgres时,我遵循了这一点,它似乎工作得非常完美。(也就是说,我的跑步应用程序看起来与数据库使用sqlite时完全相同)

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

我已经看到了,尽管我不完全确定如何基于此修改我的单元测试

我的测试套件是用测试视图的不同类设置的。那么比如说,

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:搜索匹配查询不存在


同样,当sqlite3是db时,所有这些单元测试都运行得非常好。我认为这是一个问题的postgres测试设置?但我甚至不知道从哪里开始。任何帮助都将不胜感激

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

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

这里有一个完整的例子
可能是一个愚蠢的问题,但您的测试类可能扩展了
django.test.TestCase
,并且您正在使用
python manage.py test
?WillKeeling我的测试扩展了django.test.TestCase。但是,我正在运行
pytest
来运行所有测试。运行
python manage.py测试也会抛出相同的错误。@HeidiLyons:您解决了这个问题吗?我现在也在同一个地方。如果你能发布对你有用的东西,那就太好了!谢谢。从sqlite迁移到postgresql时,我也遇到了同样的错误。如果我发现了问题所在,我会发布回复。解决方案张贴在下面。为什么会发生这种情况?我有一个问题。。。我想测试补丁和删除需要提供模型id的方法。我该如何测试这个,id是随机的。以前,我使用的是sqlite,但在迁移到postgres后,这些测试开始失败。@GoutamBSeervi正如我在回答中提到的,使用列表索引来获取记录,而不是按ID获取。这应该允许您测试其他方法。这是一项大量的工作。。我得重写我所有的测试。我已经被这个错误困扰了一天,现在我可以通过用TransactionTestCase替换TestCase来解决这个问题,现在我的测试工作正常了……但是现在它们需要更多的时间。xD以前大约需要一秒钟,现在是70秒
# 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')