Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable translations during unit tests in django?

I'm using Django Internationalization tools to translate some strings from my application. The code looks like this:

from django.utils.translation import ugettext as _
def my_view(request):
    output = _("Welcome to my site.")
    return HttpResponse(output)

Then, I'm writing unit tests using the Django test client. These tests make a request to the view and compare the returned contents.

How can I disable the translations while running the unit tests? I'm aiming to do this:

class FoobarTestCase(unittest.TestCase):
    def setUp(self):
        # Do something here to disable the string translation. But what?
        # I've already tried this, but it didn't work:
        django.utils.translation.deactivate_all()
    def testFoobar(self):
        c = Client()
        response = c.get("/foobar")
        # I want to compare to the original string without translations.
        self.assertEquals(response.content.strip(), "Welcome to my site.")
like image 763
Denilson Sá Maia Avatar asked May 31 '12 18:05

Denilson Sá Maia


2 Answers

Calling .get() or .post() on the test client will run all the configured middlewares. This means it will also run LocaleMiddleware, which will call translation.get_language_from_request() followed by translation.activate(language).

What this means is that the currently active language is ignored and thrown away when writing tests using the test client. In other words, the following code does not work:

def testFoobar(self):
    c = Client()
    # This will not work.
    translation.deactivate_all()
    # This will not work either.
    translation.activate('en-us')
    # The next call will override the earlier activate/deactivate calls.
    response = c.get("/foobar")

There a few solutions:

  1. Setting the desired language at the session object.
  2. Setting the desired language at a cookie.
  3. Sending HTTP_ACCEPT_LANGUAGE header.
  4. Setting settings.LANGUAGE_CODE

Source (from Django 1.4, but it is mostly unchanged since 1.1 or earlier):

  • django.utils.translation.get_language_from_request()
  • django.middleware.locale.LocaleMiddleware.process_request()
like image 155
Denilson Sá Maia Avatar answered Sep 19 '22 19:09

Denilson Sá Maia


I solved this same issue with approach number 4. from @Denilson Sá's answer. It turns out this does not require any test-specific settings file and can be defined on a per-test basis with a decorator or context manager provided by django (see overriding settings).

It can be used like this:

from django.test import TestCase, override_settings

class MyTest(TestCase):
    @override_settings(LANGUAGE_CODE='en-US', LANGUAGES=(('en', 'English'),))
    def test_mypage(self):
        // ...

The decorator can also be applied to the entire TestCase subclass, or for even more fine-grained control there is also a context manager (see the docs linked above).

Being this rather common for me, I also defined:

english = override_settings(
    LANGUAGE_CODE='en-US',
    LANGUAGES=(('en', 'English'),),
)

So that now I can simply use @english on the test cases requiring it.

like image 26
Davide Avatar answered Sep 20 '22 19:09

Davide