我使用Django Internationalization工具从我的应用程序中翻译某些字符串。代码如下所示:
from django.utils.translation import ugettext as _
def my_view(request):
output = _("Welcome to my site.")
return HttpResponse(output)
然后,我使用Django test client编写单元测试。这些测试向视图发出请求并比较返回的内容。
如何在运行单元测试时禁用翻译?我打算这样做:
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.")
答案 0 :(得分:11)
在测试客户端上调用.get()
或.post()
将运行所有已配置的中间件。这意味着它还会运行LocaleMiddleware
,它会调用translation.get_language_from_request()
,然后调用translation.activate(language)
。
这意味着当使用测试客户端编写测试时,将忽略当前活动的语言并将其丢弃。换句话说,以下代码不起作用:
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")
有几个解决方案:
HTTP_ACCEPT_LANGUAGE
标题。settings.LANGUAGE_CODE
来源(来自Django 1.4,但自1.1或更早以来它基本没有变化):
答案 1 :(得分:5)
我从@DenilsonSá的回答中用第4号方法解决了同样的问题。事实证明,这不需要任何特定于测试的设置文件,并且可以使用django提供的装饰器或上下文管理器在每个测试的基础上进行定义(参见overriding settings)。
可以像这样使用:
from django.test import TestCase, override_settings
class MyTest(TestCase):
@override_settings(LANGUAGE_CODE='en-US', LANGUAGES=(('en', 'English'),))
def test_mypage(self):
// ...
装饰器也可以应用于整个TestCase子类,或者对于更细粒度的控制,还有一个上下文管理器(参见上面链接的文档)。
这对我来说相当普遍,我也定义了:
english = override_settings(
LANGUAGE_CODE='en-US',
LANGUAGES=(('en', 'English'),),
)
现在我可以在需要它的测试用例上使用@english
。
答案 2 :(得分:1)
我认为将语言强制为单元测试的已知设置会更有意义。这意味着您正在测试更接近真实实现的内容。
要激活特定语言,您可以在设置中执行此操作:
from django.utils.translation import activate
...
activate('en-en')