2009-05-25 46 views
129

我想为在数据库表上执行后端操作的Django manage.py命令编写单元测试。我将如何直接从代码调用管理命令?如何从测试驱动程序直接调用定制的Django manage.py命令?

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

回答

237

测试这样的事情的最佳方式 - 提取所需的功能从命令本身到独立函数或类。它有助于从“命令执行的东西”中抽象出来,并在没有附加要求的情况下编写测试。

但如果由于某种原因不能脱钩的逻辑形式的命令,你可以使用call_command法这样的任何代码调用它:

from django.core.management import call_command 

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

+1把检验的逻辑在其他地方(模型法管理方法的独立功能???),所以你不需要乱用call_command机器都没有。也使该功能更易于重用。 – 2009-05-26 18:30:45

+30

即使你提取了逻辑,这个函数仍然可以用来测试你的命令的具体行为,如所需的参数,并确保它调用你的库函数来完成真正的工作。 – 2012-12-05 02:05:29

+0

开头段落适用于任何边界情况。将您自己的biz逻辑代码移出受限于与某些内容(如用户)进行交互的代码。但是,如果你编写代码行,它可能有一个错误,所以测试的确应该落在任何边界之后。 – Phlip 2016-02-27 16:36:11

19

而不是做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) 
1

上内特的回答大厦我有这样的:

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,这将排序为你。它并不完美 - 它不会输出管道 - 但它会使用测试数据库。然后您可以测试数据库效果。

我相信使用迈克尔Foords模拟模块,并重新布线的测试的持续时间标准输出就意味着你能得到一些更多的是出于这个技术太 - 测试输出,退出条件等

12

以下代码:

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

5

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()) 
相关问题