views:

160

answers:

2

I have the following django test case that is giving me errors:

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):
        ...

When I run my tests, testA will pass sucessfully but before testB starts, I get the following error:

IntegrityError: column username is not unique

It's clear that it is trying to create self.u1 before each test case and finding that it already exists in the Database. How do I get it to properly clean up after each test case so that subsequent cases run correctly?

+2  A: 

Precisely, setUp exists for the very purpose of running once before each test case.

The converse method, the one that runs once after each test case, is named tearDown: that's where you delete self.u1 etc (presumably by just calling self.u1.delete(), unless you have supplementary specialized clean-up requirements in addition to just deleting the object).

Alex Martelli
+2  A: 

setUp and tearDown methods on Unittests are called before and after each test case. Define tearDown method which deletes the created user.

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()

I would also advise to create user profiles using post_save signal unless you really want to create user profile manually for each user.

Follow-up on delete comment:

From Django docs:

When Django deletes an object, it emulates the behavior of the SQL constraint ON DELETE CASCADE -- in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it.

In your case, user profile is pointing to user so you should delete the user first to delete the profile at the same time.

rebus
Thanks! The problem I'm having now is that when I delete up1, the delete does not cascade and delete u1 as well, even though I've specified User as a foreign key of UserProfile. e.g. `user = models.ForeignKey(User, unique=True)`
theycallmemorty
Actually you should delete the user in order to cascade and delete the user profile in one go, or you can delete the user profile first and then the user.
rebus
Bah... I read that not in the docs but for some reason got confused about which direction the Foreign Key was pointing...
theycallmemorty