测试django国际化 - 模拟gettext

时间:2011-03-09 16:21:28

标签: python django internationalization mocking gettext

我正在国际化/开展django项目。我们有一个独立运行的部件并执行后台任务。这是由rabbitmq调用的。我想测试i18n / l10n是否适用于该部分。但是我们的应用尚未翻译,并且暂时不会。我想在翻译开始之前编写单元测试。

我想模拟一些翻译,以便_("anything")作为常量字符串返回,以便我可以测试它是否正在尝试翻译事物,而不需要设置所有翻译。

我尝试使用mock,但with mock.patch('django.utils.translations.ugettext_lazy'), my_function_that_just_returns_one_string):无效。 _导入为from django.utils.translations import ugettext_lazy as _

4 个答案:

答案 0 :(得分:2)

我找不到现有的方法来做到这一点。然而,通过阅读Django源代码,我想出了一个hacky,脆弱的方法,通过查看_active DjangoTranslation对象,然后包装他们的ugettext方法。我在这里描述了它:http://www.technomancy.org/python/django-i18n-test-translation-by-manually-setting-translations/

答案 1 :(得分:1)

我已经看过你的解决方案,我认为当你没有提供翻译字符串时,测试i18n支持既简单又简单。但是我担心translation包只是总是有效的东西,而且我们认为这是理所当然的,所以在评论很多的测试代码中看到它的内部结构至少会让我在恐惧中逃跑(轻笑)。 / p>

我认为创建一个测试应用程序,在测试设置中添加到INSTALLED_APPS,提供自己的翻译是一种更清晰的方法。您的测试将简化为translation.activate('fr'); self.assertEqual('xxx_anything', gettext('anything'), 'i18n support should be activated.')

通过简单的测试,其他开发人员可以快速跟进并看到测试应用程序包中包含一个/locale目录,该目录应立即记录您的方法。

答案 2 :(得分:0)

您可以执行以下操作来替换默认翻译对象上的ugettext方法:

from django.utils.translation.trans_real import get_language, translation

translation(get_language()).ugettext = mock_ugettext

答案 3 :(得分:0)

似乎您没有在修补正确的模块。如果是您的foo/models.py带有from django.utils.translations import ugettext_lazy as _语句,那么_foo.models模块的命名空间中,这是您必须修补的地方。

with mock.patch('foo.models._', return_value='MOCKED_TRANSLATION'):
    ...

with mock.patch('foo.models._') as mock_ugettext_lazy:
    mock_ugettext_lazy.side_effect = lambda x: x + ' translated'
    ...
    assert translated_text = 'example_text translated'

如果您有多个使用ugettext_lazy的模块,则可以这样做:

with mock.patch('foo.models._', side_effect=mock_translator), \
     mock.patch('bar._', side_effect=mock_translator):
    ...

不幸的是,对于使用ugettext_lazy的所有模块,没有一种方法可以对其进行模拟,因为一旦函数导入到模块中,就无济于事了django.utils.translations.ugettext_lazy -原始引用将继续指向原始功能。

有关更多信息,请参见https://docs.python.org/3/library/unittest.mock.html#where-to-patch