21

我有以下 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在每个测试用例之前创建并发现它已经存在于数据库中。如何在每个测试用例之后正确清理它,以便后续用例正确运行?

4

3 回答 3

29

setUptearDownUnittests 上的方法在每个测试用例之前和之后调用。定义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()

我还建议使用信号创建用户配置文件post_save,除非您真的想为每个用户手动创建用户配置文件。

删除评论的后续:

来自Django 文档

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

在您的情况下,用户配置文件指向用户,因此您应该先删除用户以同时删除配置文件。

于 2010-05-15T14:35:57.120 回答
10

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

每次测试后转储数据库是一种很好的做法,这样您就可以更加确定您的测试是一致的,但请注意,您的测试会因额外的开销而运行得更慢。

请参阅“编写测试”Django Docs中的警告部分。

于 2012-12-29T16:09:30.167 回答
3

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

相反的方法,在每个测试用例之后运行一次,被命名为tearDown: 那是你删除self.u1等的地方(大概只是调用self.u1.delete(),除非你除了删除对象之外还有补充的专门清理要求)。

于 2010-05-15T14:35:15.873 回答