为什么 call_command( ... stdout=f ) 不拦截 stdout ?

问题描述 投票:0回答:1

救命!我无法测试我的管理命令是否正常工作。该命令在手动测试时工作正常:

$ ./manage.py import_stock stock/tests/header_only.csv  
Descriptions: 0 found, 0 not found, 0 not unique
StockLines:   0 found, 0 not found, 0 not unique

但不在测试中。尽管

call_command
指定了
stdout=f
f
StringIO()
),它仍输出到标准输出。运行测试,我明白了

$ ./manage.py  test stock/tests --keepdb
Using existing test database for alias 'default'...
System check identified no issues (0 silenced).
Descriptions: 0 found, 0 not found, 0 not unique
StockLines:   0 found, 0 not found, 0 not unique
Returned
""

F
======================================================================
FAIL: test_001_invocation (test_import_stock_mgmt_cmd.Test_010_import_stock)
make sure I've got the basic testing framework right!
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/nigel/django/sarah/silsondb/stock/tests/test_import_stock_mgmt_cmd.py",line 32, in test_001_invocation
    self.assertIn('Descriptions: 0', text)                     # do-nothing
AssertionError: 'Descriptions: 0' not found in ''

----------------------------------------------------------------------
Ran 1 test in 0.006s

FAILED (failures=1)
Preserving test database for alias 'default'...

生成此代码的测试代码如下。

print(f'Returned\n"{text}"')
显示我从
do_command
返回一个空字符串(它创建了 StringIO() 并调用
call_command
)。我试图拦截的内容正在写入控制台,就像我直接调用命令一样。

import csv
import io

from django.core.management import call_command
from django.core.management.base import CommandError
from django.test import TestCase

class Test_010_import_stock( TestCase):

    def do_command( self, *args, **kwargs):
        with io.StringIO() as f:
            call_command(  *args, stdout=f ) 
            return f.getvalue()

    def test_001_invocation(self):
        """ make sure I've got the basic testing framework right! """

        text = self.do_command( 'import_stock', 'stock/tests/header_only.csv')
        print(f'Returned\n"{text}"')
        print()
        self.assertIn('Descriptions: 0', text)                     # do-nothing
        self.assertIn('Stocklines:   0', text )
django django-testing
1个回答
2
投票

回答自己的问题。管理命令本身有点愚蠢的混乱。

知道您没有使用

print
,但应该在管理命令中使用
self.stdout.write()

但是一个聪明的结果是

sys.stdout.write
,而且运气不好,这个特定的命令正在导入 sys.path。这是那些早晨之一。

© www.soinside.com 2019 - 2024. All rights reserved.