Как я могу вызвать пользовательский Django manage.py команда непосредственно от тестового драйвера?
Я хочу написать модульный тест для Django manage.py команда, выполняющая бэкэнд-операцию над таблицей базы данных. Как вызвать команду управления непосредственно из кода?
Я не хочу выполнять команду в оболочке операционной системы из tests.py потому что я не могу использовать тестовую среду, настроенную с помощью manage.py тест (тестовая база данных, тестовый макет электронной почты и т. д...)
5 ответов
лучший способ проверить такие вещи-извлечь необходимую функциональность из самой команды в автономную функцию или класс. Это помогает абстрагироваться от" выполнения команд " и писать тест без дополнительных требований.
но если вы по какой-то причине не можете отделить команду логической формы, вы можете вызвать ее из любого кода, используя call_command способ такой:
from django.core.management import call_command
call_command('my_command', 'foo', bar='baz')
вместо того, чтобы делать трюк call_command, вы можете запустить свою задачу, выполнив:
from myapp.management.commands import my_management_task
cmd = my_management_task.Command()
opts = {} # kwargs for your command -- lets you override stuff for testing...
cmd.handle_noargs(**opts)
следующий код:
from django.core.management import call_command
call_command('collectstatic', verbosity=3, interactive=False)
call_command('migrate', 'myapp', verbosity=3, interactive=False)
...равно следующим командам, набранным в терминале:
$ ./manage.py collectstatic --noinput -v 3
$ ./manage.py migrate myapp --noinput -v 3
посмотреть выполнение команд управления из django docs.
на документация Django по call_command не говоря уже о том, что out
необходимо перенаправить на sys.stdout
. Пример кода должен гласить:
from django.core.management import call_command
from django.test import TestCase
from django.utils.six import StringIO
import sys
class ClosepollTest(TestCase):
def test_command_output(self):
out = StringIO()
sys.stdout = out
call_command('closepoll', stdout=out)
self.assertIn('Expected output', out.getvalue())
основываясь на ответе Нейта, у меня есть это:
def make_test_wrapper_for(command_module):
def _run_cmd_with(*args):
"""Run the possibly_add_alert command with the supplied arguments"""
cmd = command_module.Command()
(opts, args) = OptionParser(option_list=cmd.option_list).parse_args(list(args))
cmd.handle(*args, **vars(opts))
return _run_cmd_with
использование:
from myapp.management import mycommand
cmd_runner = make_test_wrapper_for(mycommand)
cmd_runner("foo", "bar")
преимущество здесь в том, что если вы использовали дополнительные параметры и OptParse, это будет сортировать для вас. Это не совсем идеально - и это еще не трубные выходы-но он будет использовать тестовую базу данных. Затем можно протестировать эффекты базы данных.
Я уверен, что использование модуля Micheal Foords mock, а также перемотка stdout на время теста означают, что вы можете получить некоторые больше из этого метода слишком-испытайте выход, условия выхода etc.