Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Django test client in setUpClass

I have a test class where I would like to create and login a user once:

class UserModelTest(TestCase):
    fixtures = ['group_perms']

    @classmethod
    def setUpClass(cls):
        cls.standard_user = UserFactory(first_name='Firsto', last_name='Namo')

    @classmethod
    def tearDownClass(cls):
        cls.standard_user.delete()

    def setUp(self):
        self.moderator = ModeratorFactory() # I'm here because I need access to fixtures to work - but I'd rather be in setUpClass
        self.client.login(email=self.moderator.email, pass='pass') # I'm here because I need access to self.client to work - but I'd rather be in setUpClass

So my question (or two):

  • Can I move the moderator into the setUpClass method (given it needs access to fixtures)?

  • Can I access self.client in setUpClass?

like image 548
Nicole Harris Avatar asked Dec 19 '22 07:12

Nicole Harris


2 Answers

Short answer is no - but that's not the end of the story.

self.client is a convenience that is configured as part of the "pre-test" sequence. This means it is configured on a per-test basis; so you can use it in setUp(), but not setUpClass(). Similarly for fixtures - they're set up as part of pre-test, so they're not available in setUpClass().

However, there's nothing especially magical about self.client - it's just an instance of django.test.Client that Django sets up for you because it's something that is very useful to have around. You can set up your own client if you want - you just have to instantiate an instance of Client:

from django.test import Client
...
self.myclient = Client() 

and then use self.myclient as you would self.client. This can be very useful if you need to check "two user" behaviour - for example, checking that if an admin approves an article, a user can then see it. You create two clients, log them in with separate accounts, and then GET the same article URL with each client. In your case, you could create a client purely for class setup activities.

The only caveat on using django.test.Client in setUpClass() relate to transactional side effects. setUpClass() doesn't fall inside the transaction protection of a test case, so anything you do in setUpClass() will be "permanent" on the test database. You'll need to manually roll back or undo any database changes that setUpClass() makes, or you'll get cross-testcase side effects.

If you're using Django 1.8, you can use setUpTestData() instead - in this case, anything the client does would be protected by a transaction.

like image 66
freakboy3742 Avatar answered Dec 22 '22 10:12

freakboy3742


I don't think it's possible to move the creation of the moderator into the setUpClass method in Django 1.7.

Django 1.8 has a setUpTestData hook that you will be able to use.

class UserModelTest(TestCase):
    ...
    @classmethod
    def setUpTestData(cls):
        cls.moderator = ModeratorFactory()
like image 20
Alasdair Avatar answered Dec 22 '22 11:12

Alasdair