Я думаю, вы не должны сами это кодировать, но посмотрите на Tree :: Visualize , который, кажется, является хорошей реализацией Perl с различными возможными стилями и использует / порт один из алгоритмов там .
Можно поместить тесты в tests/
подкаталог приложения (а не tests.py
файл) и включать tests/models.py
с моделями только для теста.
Затем предоставляют выполняющий тест сценарий ( пример ), который включает Ваш tests/
"приложение" в INSTALLED_APPS
. (Это не работает, когда запущенное приложение тестирует из реального проекта, который не будет иметь тестового приложения в INSTALLED_APPS
, но я редко нахожу полезным запустить допускающие повторное использование тесты приложения из проекта, и Django 1.6 + не делает по умолчанию.)
( ПРИМЕЧАНИЕ : альтернативный динамический метод описал только ниже работ в Django 1.1 +, если Ваш тестовый сценарий разделяет на подклассы TransactionTestCase
- который значительно замедляет Ваши тесты - и больше не работает вообще в Django 1.7 +. Это оставляют здесь только для исторического интереса; не используйте его.)
В начале Ваших тестов (т.е. в методе установки, или в начале ряда doctests), можно динамично добавить "myapp.tests"
к установке INSTALLED_APPS и затем сделать это:
from django.core.management import call_command
from django.db.models import loading
loading.cache.loaded = False
call_command('syncdb', verbosity=0)
Затем в конце Ваших тестов, необходимо вымыться путем восстановления старой версии INSTALLED_APPS и очистки кэша приложения снова.
Этот класс инкапсулирует шаблон, таким образом, он не загромождает Ваш тестовый код вполне так же.
Это решение работает только для более ранних версий django
(до 1.7
). Вы можете легко проверить свою версию:
import django
django.VERSION < (1, 7)
Исходный ответ:
Это довольно странно, но form me работает очень простой шаблон:
Ниже я поместил код, который определяет модель статьи, которая необходима только для тестов (она существует в someapp / tests.py и я можно проверить это просто с помощью: ./ manage.py test someapp ):
class Article(models.Model):
title = models.CharField(max_length=128)
description = models.TextField()
document = DocumentTextField(template=lambda i: i.description)
def __unicode__(self):
return self.title
__test__ = {"doctest": """
#smuggling model for tests
>>> from .tests import Article
#testing data
>>> by_two = Article.objects.create(title="divisible by two", description="two four six eight")
>>> by_three = Article.objects.create(title="divisible by three", description="three six nine")
>>> by_four = Article.objects.create(title="divisible by four", description="four four eight")
>>> Article.objects.all().search(document='four')
[<Article: divisible by two>, <Article: divisible by four>]
>>> Article.objects.all().search(document='three')
[<Article: divisible by three>]
"""}
Модульные тесты также работают с таким определением модели.
Ответ @ paluh требует добавления нежелательного кода в не тестовый файл, и, по моему опыту, решение @ carl не работает с django.test.TestCase, который является нужно было использовать приспособления. Если вы хотите использовать django.test.TestCase, вам необходимо убедиться, что вы вызываете syncdb до загрузки фикстур. Это требует переопределения метода _pre_setup (помещения кода в метод setUp недостаточно). Я использую свою версию TestCase, которая позволяет мне добавлять приложения с тестовыми моделями. Он определяется следующим образом:
from django.conf import settings
from django.core.management import call_command
from django.db.models import loading
from django import test
class TestCase(test.TestCase):
apps = ()
def _pre_setup(self):
# Add the models to the db.
self._original_installed_apps = list(settings.INSTALLED_APPS)
for app in self.apps:
settings.INSTALLED_APPS.append(app)
loading.cache.loaded = False
call_command('syncdb', interactive=False, verbosity=0)
# Call the original method that does the fixtures etc.
super(TestCase, self)._pre_setup()
def _post_teardown(self):
# Call the original method.
super(TestCase, self)._post_teardown()
# Restore the settings.
settings.INSTALLED_APPS = self._original_installed_apps
loading.cache.loaded = False