如何直接从测试驱动程序调用自定义Django manage.py命令?

时间:2009-05-25 17:39:06

标签: django unit-testing

我想为Django manage.py命令编写单元测试,该命令对数据库表执行后端操作。我如何直接从代码中调用管理命令?

我不想从tests.py在操作系统的shell上执行命令,因为我无法使用manage.py test设置的测试环境(测试数据库,测试虚拟电子邮件发件箱等等... )

5 个答案:

答案 0 :(得分:277)

测试此类事物的最佳方法 - 从命令本身提取所需的功能到独立的功能或类。它有助于从“命令执行东西”中抽象出来并编写测试而无需额外的要求。

但是如果你由于某种原因无法解耦逻辑形式命令,你可以使用call_command方法从任何代码中调用它:

from django.core.management import call_command

call_command('my_command', 'foo', bar='baz')

答案 1 :(得分:21)

您可以通过执行以下操作来运行您的任务:

,而不是执行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)

答案 2 :(得分:16)

以下代码:

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

请参阅running management commands from django docs

答案 3 :(得分:10)

Django documentation on the 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())

答案 4 :(得分:1)

根据Nate的回答,我有这个:

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模拟模块并在测试期间重新连接stdout意味着你也可以从这项技术中获得更多 - 测试输出,退出条件等。