Django Sessions in StaticLiveServerTestCase

This is for Django 1.8.

Here was the scenario. I have a Django site where most of the pages require the user to login. I have a form that gets some initial values from Django sessions. The form has lots of javascript, so live testing seemed best. The problem I could not set the session values in the test code.

Initially, this seemed pretty easy because in the test code, there was a variable called:

self.client.session

However, changes to the session were not present when the test code called the view. Careful inspection showed that the session id’s in self.client.session and view.request.session were different.

Adding the following method to StaticLiveServerTestCase solved the problem:

    def save_to_session(self, key, value):
        cookies = self.selenium.get_cookies()
        session_key = None
        for cookie in cookies:
            if cookie[u'name'] == u'sessionid':
                session_key = cookie[u'value']
                break

        if session_key:
            from django.contrib.sessions.backends.cached_db import SessionStore
            s = SessionStore(session_key)
            s[key] = value
            s.save()

 

Advertisements

Django and Pytest

As of Django 1.8, when you run tests and have migrations, the tests build the test database from the migrations (if you do not believe me, run tests with -v 3). If you have a lot of migrations, this can be painfully slow.

Pytest has an option that builds the test database directly:

pytest --nomigrations ./my_test.py

In my case, I get about a x5 speed up.

This works for  django.test.TestCase and django.contrib.staticfiles.testing.StaticLiveServerTestCase.

Unfortunately, pytest is not a drop in replacement for django test.

Failed: Database access not allowed, use the “django_db” mark

Sometimes you will get the above error. Based on the error message, it seems like you may need to alter your code some how. However, according to the docs, if you are using django.test.TestCase you do not need to alter your code.

One way you get get this error is if your imports access the database. Move the imports to inside the test class and the problems go away.

Python Mock Functions Not Being Called

Are you using mock to mock some functions during testing and mysteriously your tests are ignoring the mock decorator?

One way this can happen is if the function being mocked is either defined in the module that is being tested or is imported into the module being tested. How to get around this?

In my case, after I wasted time figuring out why mock was not working, I ended up modifying the code in my module so that I did not need mock. In the end, I think the modified code is better anyway. Often making code testable, makes it better too.

Numpy set_printoptions is not Working

Are you trying to use numpy.set_printoptions to format how arrays are printed and it does not seem to be working? Try checking the array dtype.

In my case, I was using a ufunc to apply a function to every element in the array. When I printed the result, I got a bunch of floating point numbers. When I tried to use numpy.set_printoptions to make the output a little more readable, it did not work. Further investigation showed that my array was now dtype “object”, not dtype “float64” as the original array. Converting the array solved the problem:

y = my_ufunc(x).astype(numpy.float64)

Working in Python 3.6 in Ubuntu 14.04

This link shows how to install python 3.6 on Ubuntu 14.04: https://askubuntu.com/questions/949638/installation-of-python3-6-2-on-ubuntu-14-04-python3-version-still-shows-3-4

When installing python 3.6 you will get a warning about not removing python 3.5. The commands above will not remove 3.5.

To run python 3.6, type:

/usr/bin/python3.6

In python 3.6, the pyvenv command for making virtualenvs was deprecated. The new command is:

python3.6 -m venv full-path-to-venv-dir

When I run that command, I get an error:

returned non-zero exit status 1

although the virtualenv folder is created along with a bunch of folders and files. Running the command like this works:

python3.6 -m venv full-path-to-venv-dir --without-pip

The virtual env can be activated with:

source path-to-env/bin/activate

After you activate the virtual env, you can install pip inside it, by downloading it and running it with the virtual env version of python:

wget https://bootstrap.pypa.io/get-pip.py
python get-pip.py

Testing Django When Using @cached_property

I use the @cached_property decorator quite a bit. It’s pretty straightforward. Usually, it’s set it and forget it. As noted in the docs, it persists as long as the instance persists.

However, it can cause problems during testing if you want to change it’s value. Here is how to change the value (from SO):

class SomeClass(object):

    @cached_property
    def expensive_property(self):
         return datetime.now()

obj = SomeClass()
print obj.expensive_property
print obj.expensive_property # outputs the same value as before
del obj.expensive_property
print obj.expensive_property # outputs new value