在django单元测试中使用用户模型的问题

时间:2010-05-15 14:32:55

标签: python django unit-testing django-testing

我有以下django测试用例,它给了我错误:

class MyTesting(unittest.TestCase):
    def setUp(self):
        self.u1 = User.objects.create(username='user1')
        self.up1 = UserProfile.objects.create(user=self.u1)

    def testA(self):
        ...

    def testB(self):
        ...

当我运行测试时,testA将成功通过,但在testB启动之前,我会收到以下错误:

IntegrityError: column username is not unique

很明显,它试图在每个测试用例之前创建self.u1并发现它已经存在于数据库中。如何在每个测试用例之后对其进行正确清理以便后续情况正确运行?

3 个答案:

答案 0 :(得分:28)

在每个测试用例之前和之后调用Unittests上的

setUptearDown方法。定义删除创建的用户的tearDown方法。

class MyTesting(unittest.TestCase):
    def setUp(self):
        self.u1 = User.objects.create(username='user1')
        self.up1 = UserProfile.objects.create(user=self.u1)

    def testA(self):
        ...

    def tearDown(self):
        self.up1.delete()
        self.u1.delete()

除非您真的想为每个用户手动创建用户个人资料,否则我还会建议create user profiles使用post_save信号。

删除评论

跟进

来自Django docs

  

当Django删除一个对象时,它   模拟SQL的行为   约束ON DELETE CASCADE - in   换句话说,任何具有的对象   指向对象的外键   被删除将被删除   它

在您的情况下,用户个人资料指向用户,因此您应该首先删除用户以同时删除个人资料。

答案 1 :(得分:9)

如果您希望django在每次测试运行后自动刷新测试数据库,那么您应该扩展django.test.TestCase,而不是django.utils.unittest.TestCase(正如您当前所做的那样)。

最好在每次测试后转储数据库,这样你可以确定测试是否一致,但请注意,这些额外开销会使测试运行速度变慢。

请参阅"Writing Tests" Django Docs

中的警告部分

答案 2 :(得分:2)

确切地说,setUp存在的目的在每个测试用例之前运行一次

相反的方法,在每个测试用例后运行一次的方法,命名为tearDown:这是你删除self.u1等的地方(大概是通过调用{{1}除非你只是删除对象,否则除非你有补充的专业清理要求。)