Запуск конкретного тестового примера в Django, когда у вашего приложения есть каталог тестов

165

В документации Django ( http://docs.djangoproject.com/en/1.3/topics/testing/#running-tests ) говорится, что вы можете запускать отдельные тестовые случаи, указав их:

$ ./manage.py test animals.AnimalTestCase

Это предполагает, что у вас есть свои тесты в файле tests.py в вашем приложении Django. Если это правда, то эта команда работает как ожидалось.

У меня есть мои тесты для приложения Django в каталоге тестов:

my_project/apps/my_app/
├── __init__.py
├── tests
   ├── __init__.py
   ├── field_tests.py
   ├── storage_tests.py
├── urls.py
├── utils.py
└── views.py

tests/__init__.pyФайл имеет функцию ванной ():

import unittest

from my_project.apps.my_app.tests import field_tests, storage_tests

def suite():
    tests_loader = unittest.TestLoader().loadTestsFromModule
    test_suites = []
    test_suites.append(tests_loader(field_tests))
    test_suites.append(tests_loader(storage_tests))
    return unittest.TestSuite(test_suites)

Для запуска тестов я делаю:

$ ./manage.py test my_app

Попытка указать отдельный тестовый пример вызывает исключение:

$ ./manage.py test my_app.tests.storage_tests.StorageTestCase
...
ValueError: Test label 'my_app.tests.storage_tests.StorageTestCase' should be of the form app.TestCase or app.TestCase.test_method

Я пытался сделать то, что говорилось в сообщении об исключении:

$ ./manage.py test my_app.StorageTestCase
...
ValueError: Test label 'my_app.StorageTestCase' does not refer to a test

Как указать отдельный тестовый случай, когда мои тесты находятся в нескольких файлах?

hekevintran
источник

Ответы:

156

Оформить заказ Джанго-Нос . Это позволяет указать тесты для запуска, как:

python manage.py test another.test:TestCase.test_method

или, как отмечено в комментариях, используйте синтаксис:

python manage.py test another.test.TestCase.test_method
Сэм Долан
источник
Спасибо @sdolan. Столкнулся с той же проблемой, что и хекевинтран. Переключился на django-nose, и это устранило эту проблему, также работает намного лучше, чем стандартный тестер Django.
LeeMobile
Это запускает тест, но как запустить весь TestCase?
jMyles
5
@jMyles:another.test:TestCase
Сэм Долан
4
Вниманию таких людей, как я, которые слепо вставляют из Stackoverflow: это приведет к ошибке без упомянутого плагина, используйте синтаксис, описанный в другом ответе (. Вместо :), который работает в Django 1.6+.
Энди Смит
1
я отклонил этот ответ, потому что он на самом деле не отвечает на вопрос ОП, который заключался в том, как это сделать в Django. Скорее, он просто предлагает переключиться на Nosetest
Джош Браун
175

Начиная с Django 1.6, вы можете запустить полный тестовый набор или отдельный тест, используя полные точечные обозначения для элемента, который вы хотите запустить.

Автоматическое обнаружение тестов теперь будет находить тесты в любом файле, который начинается с test в рабочем каталоге, поэтому для решения вопроса вам придется переименовать файлы, но теперь вы можете хранить их в нужном каталоге. Если вы хотите использовать пользовательские имена файлов, вы можете указать шаблон (бегун по умолчанию Django) с флагом опции --pattern="my_pattern_*.py".

Поэтому, если вы находитесь в своем manage.pyкаталоге и хотите запустить тест test_aвнутри TestCaseподкласса Aвнутри файла tests.pyв приложении / модуле, exampleвы должны сделать:

python manage.py test example.tests.A.test_a

Если вы не хотите включать зависимость и используете Django 1.6 или более позднюю версию, это то, как вы это делаете.

Смотрите документацию Django для получения дополнительной информации.

cristiano2lopes
источник
Приятно видеть, что эта функция встроена в Django.
Хекевинтран
Я не могу заставить это работать на всех: error: option --pattern not recognizedиinvalid command name
геоидеский
Это прекрасно работает в Django v3!
Кирк
11

Я сам столкнулся с этой проблемой и нашел этот вопрос, на случай, если кто-нибудь еще придет, вот что я откопал. DjangoTestSuiteRuner использует метод build_test (label), который выясняет, какие тестовые сценарии следует запускать на основе метки. При изучении этого метода выясняется, что они выполняют getattr () для модуля «models» или «test». Это означает, что если вы возвращаете набор, который тестовый исполнитель не ищет в этом наборе, он просматривает только один из этих модулей.

Быстрый обходной путь - использовать __init__.pyдля импорта тестов напрямую, а не для определения набора. Он делает их частью модуля «test», и build_test (label) может их найти.

Для вашего примера выше, tests/__init__.pyдолжно просто содержать:

from field_tests import *
from storage_tests import *

Это не очень элегантно, и, конечно, если вы пытаетесь сделать что-то более сложное с вашим набором, то это не сработает, но будет в этом случае.

Крис Т
источник
11

Это должно работать

python manage.py test my_app.tests.storage_tests
Свапнил патель
источник
4

Я также столкнулся с этой проблемой и вместо того, чтобы использовать django-nose, я перешел по этой ссылке здесь: http://www.pioverpi.net/2010/03/10/organizing-django-tests-into-folders/ . Вам нужно открыть свой init .py и импортировать ваши тесты.

Например, в init .py:from unique_test_file import *

Остин
источник
3

Поместите этот код в свой __init__.py, и он импортирует все тестовые классы в пакете и подпакетах. Это позволит вам запускать определенные тесты, не импортируя каждый файл вручную.

import pkgutil
import unittest

for loader, module_name, is_pkg in pkgutil.walk_packages(__path__):
    module = loader.find_module(module_name).load_module(module_name)
    for name in dir(module):
        obj = getattr(module, name)
        if isinstance(obj, type) and issubclass(obj, unittest.case.TestCase):
            exec ('%s = obj' % obj.__name__)

Точно так же для вашего набора тестов вы можете просто использовать:

def suite():   
    return unittest.TestLoader().discover("appname.tests", pattern="*.py")

Теперь все, что вам нужно сделать для новых тестов, это написать их и убедиться, что они находятся в папке тестов. Нет больше утомительного обслуживания импорта!

Брайс Дреннан
источник