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

Mik*_*keN 162 django unit-testing

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

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

Ale*_*lev 294

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

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

from django.core.management import call_command

call_command('my_command', 'foo', bar='baz')
Run Code Online (Sandbox Code Playgroud)

  • 即使您提取逻辑,此函数仍然可用于测试您的命令特定行为,如所需的参数,并确保它调用您的库函数,这样做真正起作用. (34认同)
  • +1将可测试逻辑放在其他地方(模型方法?管理器方法?独立函数?)所以你根本不需要搞乱call_command机制.还使功能更易于重用. (18认同)

Nat*_*ate 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)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常好的问题.三年前也许我会找到你的答案;) (16认同)
  • 当call_command还提供捕获stdin,stdout,stderr时,你为什么要这样做呢?当文档指定正确的方法时? (10认同)
  • 挖掘后,但今天这对我有所帮助:我并不总是使用我的代码库的所有应用程序(取决于所使用的Django站点),而`call_command`需要在`INSTALLED_APPS`中加载经过测试的应用程序.在为了测试目的加载应用程序并使用它之间,我选择了这个. (2认同)

Art*_*yan 16

以下代码:

from django.core.management import call_command
call_command('collectstatic', verbosity=3, interactive=False)
call_command('migrate', 'myapp', verbosity=3, interactive=False)
Run Code Online (Sandbox Code Playgroud)

...等于终端中输入的以下命令:

$ ./manage.py collectstatic --noinput -v 3
$ ./manage.py migrate myapp --noinput -v 3
Run Code Online (Sandbox Code Playgroud)

请参阅从django docs运行管理命令.


Ala*_*ars 12

对call_command Django文档没有提到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())
Run Code Online (Sandbox Code Playgroud)

  • 哇。感谢您分享此提示。这是一个很大的疏忽,并且[在 3.2 文档中仍然如此](https://docs.djangoproject.com/en/3.2/topics/testing/tools/#management-commands)。我想我会提交一份 PR! (2认同)