mirror of
https://github.com/Hopiu/django-modeltranslation.git
synced 2026-05-05 03:54:43 +00:00
Allow tests to be run together with other apps.
This commit is contained in:
parent
8d9d837b2f
commit
c7b8b77e86
5 changed files with 189 additions and 53 deletions
|
|
@ -1,15 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Tests have to be run with modeltranslation.tests.settings:
|
||||
./manage.py test --settings=modeltranslation.tests.settings modeltranslation
|
||||
|
||||
TODO: Merge autoregister tests from django-modeltranslation-wrapper.
|
||||
|
||||
NOTE: Perhaps ModeltranslationTestBase in tearDownClass should reload some modules,
|
||||
so that tests for other apps are in the same environment.
|
||||
|
||||
"""
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
from django.conf import settings as django_settings
|
||||
from django.contrib.admin.sites import AdminSite
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.exceptions import ValidationError
|
||||
|
|
@ -28,16 +29,86 @@ from modeltranslation.tests.models import (
|
|||
FileFieldsModel, TestModel, MultitableBModelA, MultitableModelC,
|
||||
MultitableDTestModel)
|
||||
from modeltranslation.tests.translation import FallbackModel2TranslationOptions
|
||||
from modeltranslation.tests.test_settings import TEST_SETTINGS
|
||||
|
||||
try:
|
||||
from django.test.utils import override_settings
|
||||
except ImportError:
|
||||
from modeltranslation.tests.utils import override_settings
|
||||
|
||||
# None of the following tests really depend on the content of the request,
|
||||
# so we'll just pass in None.
|
||||
request = None
|
||||
|
||||
|
||||
@override_settings(**TEST_SETTINGS)
|
||||
class ModeltranslationTestBase(TestCase):
|
||||
urls = 'modeltranslation.tests.urls'
|
||||
cache = AppCache()
|
||||
synced = False
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""
|
||||
Prepare database:
|
||||
* Call syncdb to create tables for tests.models (since during
|
||||
default testrunner's db creation modeltranslation.tests was not in INSTALLED_APPS
|
||||
"""
|
||||
super(ModeltranslationTestBase, cls).setUpClass()
|
||||
if not ModeltranslationTestBase.synced:
|
||||
# In odred to perform only one syncdb
|
||||
ModeltranslationTestBase.synced = True
|
||||
with override_settings(**TEST_SETTINGS):
|
||||
import sys
|
||||
|
||||
# 1. Reload translation in case USE_I18N was False
|
||||
from django.utils import translation
|
||||
reload(translation)
|
||||
|
||||
# 2. Reload MT because LANGUAGES likely changed.
|
||||
reload(mt_settings)
|
||||
reload(translator)
|
||||
from modeltranslation import admin, utils
|
||||
reload(admin)
|
||||
reload(utils)
|
||||
|
||||
# 3. Reset test models (because autodiscover have already run, those models
|
||||
# have translation fields, but for languages previously defined. We want
|
||||
# to be sure that 'de' and 'en' are available)
|
||||
del cls.cache.app_models['tests']
|
||||
from modeltranslation.tests import models
|
||||
reload(models)
|
||||
cls.cache.load_app('modeltranslation.tests')
|
||||
sys.modules.pop('modeltranslation.tests.translation', None)
|
||||
|
||||
# 4. Autodiscover
|
||||
from modeltranslation import models
|
||||
reload(models)
|
||||
|
||||
# 5. Reload some imported classes
|
||||
cls.reload_globals('modeltranslation.tests.models')
|
||||
cls.reload_globals('modeltranslation.admin')
|
||||
|
||||
# 6. Syncdb (``migrate=False`` in case of south)
|
||||
from django.db import connections, DEFAULT_DB_ALIAS
|
||||
from django.core.management import call_command
|
||||
call_command('syncdb', verbosity=0, migrate=False, interactive=False,
|
||||
database=connections[DEFAULT_DB_ALIAS].alias, load_initial_data=False)
|
||||
|
||||
@staticmethod
|
||||
def reload_globals(module):
|
||||
"""
|
||||
Very ugly method for reloading things imported from module.
|
||||
|
||||
It wouldn't be needed if eg. ``TestModel`` calls would be replaced by ``models.TestModel``.
|
||||
"""
|
||||
names = []
|
||||
for name, item in globals().items():
|
||||
if hasattr(item, '__module__') and item.__module__ == module:
|
||||
names.append(name)
|
||||
_temp = __import__(module, globals(), locals(), names, -1)
|
||||
for name in names:
|
||||
globals()[name] = getattr(_temp, name)
|
||||
|
||||
@classmethod
|
||||
def clear_cache(cls):
|
||||
|
|
@ -71,17 +142,13 @@ class ModeltranslationTestBase(TestCase):
|
|||
class ModeltranslationTest(ModeltranslationTestBase):
|
||||
"""Basic tests for the modeltranslation application."""
|
||||
def test_registration(self):
|
||||
self.client.post('/set_language/', data={'language': 'de'})
|
||||
#self.client.session['django_language'] = 'de-de'
|
||||
#self.client.cookies[settings.LANGUAGE_COOKIE_NAME] = 'de-de'
|
||||
|
||||
langs = tuple(l[0] for l in settings.LANGUAGES)
|
||||
langs = tuple(l[0] for l in django_settings.LANGUAGES)
|
||||
self.failUnlessEqual(2, len(langs))
|
||||
self.failUnless('de' in langs)
|
||||
self.failUnless('en' in langs)
|
||||
self.failUnless(translator.translator)
|
||||
|
||||
# Check that eight models are registered for translation
|
||||
# Check that nine models are registered for translation
|
||||
self.failUnlessEqual(len(translator.translator._registry), 9)
|
||||
|
||||
# Try to unregister a model that is not registered
|
||||
|
|
|
|||
|
|
@ -1,59 +1,29 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Settings overrided for test time
|
||||
"""
|
||||
import os
|
||||
import django
|
||||
from django.conf import settings
|
||||
|
||||
|
||||
DIRNAME = os.path.dirname(__file__)
|
||||
|
||||
DEBUG = False
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ':memory:'
|
||||
}
|
||||
}
|
||||
test_db = os.environ.get('DB', 'sqlite')
|
||||
if test_db == 'mysql':
|
||||
DATABASES['default'].update({
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'modeltranslation',
|
||||
'USER': 'root',
|
||||
})
|
||||
elif test_db == 'postgres':
|
||||
DATABASES['default'].update({
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'USER': 'postgres',
|
||||
'NAME': 'modeltranslation',
|
||||
'OPTIONS': {
|
||||
'autocommit': True,
|
||||
}
|
||||
})
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.admin',
|
||||
'django.contrib.sites',
|
||||
'django.contrib.redirects',
|
||||
'modeltranslation',
|
||||
INSTALLED_APPS = tuple(settings.INSTALLED_APPS) + (
|
||||
'modeltranslation.tests',
|
||||
)
|
||||
if django.VERSION[0] >= 1 and django.VERSION[1] >= 3:
|
||||
INSTALLED_APPS += ('django.contrib.staticfiles',)
|
||||
# IMO this is unimportant
|
||||
#if django.VERSION[0] >= 1 and django.VERSION[1] >= 3:
|
||||
#INSTALLED_APPS += ('django.contrib.staticfiles',)
|
||||
|
||||
STATIC_URL = '/static/'
|
||||
|
||||
ROOT_URLCONF = 'modeltranslation.tests.urls'
|
||||
#STATIC_URL = '/static/'
|
||||
|
||||
MEDIA_URL = '/media/'
|
||||
MEDIA_ROOT = os.path.join(DIRNAME, 'media/')
|
||||
|
||||
SITE_ID = 1
|
||||
|
||||
LANGUAGES = (('de', 'Deutsch'),
|
||||
('en', 'English'))
|
||||
LANGUAGE_CODE = 'de'
|
||||
DEFAULT_LANGUAGE = 'de'
|
||||
|
||||
SECRET_KEY = 'z5)t*g3003n23lze(&u5)kt&9gtcf)*-o++m2#n-w!qts7u1cj'
|
||||
USE_I18N = True
|
||||
|
|
|
|||
6
modeltranslation/tests/test_settings.py
Normal file
6
modeltranslation/tests/test_settings.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
"""
|
||||
Get test settings in dict format (for use with settings_override).
|
||||
"""
|
||||
import settings as _settings
|
||||
|
||||
TEST_SETTINGS = dict((k, getattr(_settings, k)) for k in dir(_settings) if k == k.upper())
|
||||
60
modeltranslation/tests/utils.py
Normal file
60
modeltranslation/tests/utils.py
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
"""
|
||||
This is Django 1.4 override_settings decorator backported for compatibility with Django 1.3.
|
||||
|
||||
The only difference is that this version does not use settings_changes signal
|
||||
(because there is no such signal).
|
||||
"""
|
||||
|
||||
from django.conf import settings, UserSettingsHolder
|
||||
|
||||
|
||||
class override_settings(object):
|
||||
"""
|
||||
Acts as either a decorator, or a context manager. If it's a decorator it
|
||||
takes a function and returns a wrapped function. If it's a contextmanager
|
||||
it's used with the ``with`` statement. In either event entering/exiting
|
||||
are called before and after, respectively, the function/block is executed.
|
||||
"""
|
||||
def __init__(self, **kwargs):
|
||||
self.options = kwargs
|
||||
self.wrapped = settings._wrapped
|
||||
|
||||
def __enter__(self):
|
||||
self.enable()
|
||||
|
||||
def __exit__(self, exc_type, exc_value, traceback):
|
||||
self.disable()
|
||||
|
||||
def __call__(self, test_func):
|
||||
from django.test import TransactionTestCase
|
||||
if isinstance(test_func, type) and issubclass(test_func, TransactionTestCase):
|
||||
original_pre_setup = test_func._pre_setup
|
||||
original_post_teardown = test_func._post_teardown
|
||||
|
||||
def _pre_setup(innerself):
|
||||
self.enable()
|
||||
original_pre_setup(innerself)
|
||||
|
||||
def _post_teardown(innerself):
|
||||
original_post_teardown(innerself)
|
||||
self.disable()
|
||||
test_func._pre_setup = _pre_setup
|
||||
test_func._post_teardown = _post_teardown
|
||||
return test_func
|
||||
else:
|
||||
@wraps(test_func)
|
||||
def inner(*args, **kwargs):
|
||||
with self:
|
||||
return test_func(*args, **kwargs)
|
||||
return inner
|
||||
|
||||
def enable(self):
|
||||
override = UserSettingsHolder(settings._wrapped)
|
||||
for key, new_value in self.options.items():
|
||||
setattr(override, key, new_value)
|
||||
settings._wrapped = override
|
||||
|
||||
def disable(self):
|
||||
settings._wrapped = self.wrapped
|
||||
for key in self.options:
|
||||
new_value = getattr(settings, key, None)
|
||||
37
runtests.py
37
runtests.py
|
|
@ -2,11 +2,44 @@
|
|||
import os
|
||||
import sys
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'modeltranslation.tests.settings'
|
||||
|
||||
def runtests():
|
||||
if not settings.configured:
|
||||
# Choose database for settings
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': ':memory:'
|
||||
}
|
||||
}
|
||||
test_db = os.environ.get('DB', 'sqlite')
|
||||
if test_db == 'mysql':
|
||||
DATABASES['default'].update({
|
||||
'ENGINE': 'django.db.backends.mysql',
|
||||
'NAME': 'modeltranslation',
|
||||
'USER': 'root',
|
||||
})
|
||||
elif test_db == 'postgres':
|
||||
DATABASES['default'].update({
|
||||
'ENGINE': 'django.db.backends.postgresql_psycopg2',
|
||||
'USER': 'postgres',
|
||||
'NAME': 'modeltranslation',
|
||||
'OPTIONS': {
|
||||
'autocommit': True,
|
||||
}
|
||||
})
|
||||
|
||||
# Configure test environment
|
||||
settings.configure(
|
||||
DATABASES = DATABASES,
|
||||
INSTALLED_APPS = (
|
||||
'modeltranslation',
|
||||
),
|
||||
ROOT_URLCONF = None, # tests override urlconf, but it still needs to be defined
|
||||
)
|
||||
|
||||
failures = call_command(
|
||||
'test', 'modeltranslation', interactive=False, failfast=False,
|
||||
verbosity=2)
|
||||
|
|
|
|||
Loading…
Reference in a new issue