test_extract_and_generate.py 4.09 KB
Newer Older
Sarina Canelake committed
1 2 3
"""
This test tests that i18n extraction (`paver i18n_extract -v`) works properly.
"""
4 5 6
from datetime import datetime, timedelta
import os
import sys
Sarina Canelake committed
7
import string  # pylint: disable=deprecated-module
8 9 10 11 12 13 14 15 16 17 18
import random
import re

from unittest import TestCase
from mock import patch
from polib import pofile
from pytz import UTC

from i18n import extract
from i18n import generate
from i18n import dummy
19
from i18n.config import CONFIGURATION
20 21 22 23 24 25 26 27 28 29


class TestGenerate(TestCase):
    """
    Tests functionality of i18n/generate.py
    """
    generated_files = ('django-partial.po', 'djangojs-partial.po', 'mako.po')

    @classmethod
    def setUpClass(cls):
30 31 32 33 34 35
        sys.stderr.write(
            "\nThis test tests that i18n extraction (`paver i18n_extract`) works properly. "
            "If you experience failures, please check that all instances of `gettext` and "
            "`ngettext` are used correctly. You can also try running `paver i18n_extract -v` "
            "locally for more detail.\n"
        )
36 37 38 39 40
        sys.stderr.write(
            "\nExtracting i18n strings and generating dummy translations; "
            "this may take a few minutes\n"
        )
        sys.stderr.flush()
41 42
        extract.main(verbosity=0)
        dummy.main(verbosity=0)
43 44 45 46 47 48 49 50 51 52

    def setUp(self):
        # Subtract 1 second to help comparisons with file-modify time succeed,
        # since os.path.getmtime() is not millisecond-accurate
        self.start_time = datetime.now(UTC) - timedelta(seconds=1)

    def test_merge(self):
        """
        Tests merge script on English source files.
        """
53 54
        filename = os.path.join(CONFIGURATION.source_messages_dir, random_name())
        generate.merge(CONFIGURATION.source_locale, target=filename)
55 56 57 58
        self.assertTrue(os.path.exists(filename))
        os.remove(filename)

    # Patch dummy_locales to not have esperanto present
59
    @patch.object(CONFIGURATION, 'dummy_locales', ['fake2'])
60 61 62 63 64 65 66 67 68
    def test_main(self):
        """
        Runs generate.main() which should merge source files,
        then compile all sources in all configured languages.
        Validates output by checking all .mo files in all configured languages.
        .mo files should exist, and be recently created (modified
        after start of test suite)
        """
        generate.main(verbosity=0, strict=False)
69
        for locale in CONFIGURATION.translated_locales:
70
            for filename in ('django', 'djangojs'):
Sarina Canelake committed
71
                mofile = filename + '.mo'
72
                path = os.path.join(CONFIGURATION.get_messages_dir(locale), mofile)
73 74
                exists = os.path.exists(path)
                self.assertTrue(exists, msg='Missing file in locale %s: %s' % (locale, mofile))
Sarina Canelake committed
75 76 77 78
                self.assertTrue(
                    datetime.fromtimestamp(os.path.getmtime(path), UTC) >= self.start_time,
                    msg='File not recently modified: %s' % path
                )
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
            # Segmenting means that the merge headers don't work they way they
            # used to, so don't make this check for now. I'm not sure if we'll
            # get the merge header back eventually, or delete this code eventually.
            # self.assert_merge_headers(locale)

    def assert_merge_headers(self, locale):
        """
        This is invoked by test_main to ensure that it runs after
        calling generate.main().

        There should be exactly three merge comment headers
        in our merged .po file. This counts them to be sure.
        A merge comment looks like this:
        # #-#-#-#-#  django-partial.po (0.1a)  #-#-#-#-#

        """
95
        path = os.path.join(CONFIGURATION.get_messages_dir(locale), 'django.po')
Sarina Canelake committed
96
        pof = pofile(path)
97
        pattern = re.compile('^#-#-#-#-#', re.M)
Sarina Canelake committed
98 99 100 101 102 103
        match = pattern.findall(pof.header)
        self.assertEqual(
            len(match),
            3,
            msg="Found %s (should be 3) merge comments in the header for %s" % (len(match), path)
        )
104 105 106 107 108 109


def random_name(size=6):
    """Returns random filename as string, like test-4BZ81W"""
    chars = string.ascii_uppercase + string.digits
    return 'test-' + ''.join(random.choice(chars) for x in range(size))