Reputation: 8192
Help! I am unable to get testing for my management command to work. The command works fine when tested manually:
$ ./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
but not in a test. It's outputting to stdout despite call_command
specifying stdout=f
(f
is a StringIO()
). Running the test, I get
$ ./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'...
The test code which generates this is as follows. print(f'Returned\n"{text}"')
shows that I'm getting a null string back from do_command
(which creates the StringIO() and invokes call_command
). What I'm trying to intercept is being written to the console, just as when I invoke the command directly.
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 )
Upvotes: 3
Views: 859
Reputation: 8192
I was using:
sys.stdout.write()
but should have been using:
self.stdout.write()
(use self
instead of sys
)
When you are using management commands and wish to provide console output, you should write to self.stdout and self.stderr, instead of printing to stdout and stderr directly. By using these proxies, it becomes much easier to test your custom command. https://docs.djangoproject.com/en/dev/howto/custom-management-commands/
Upvotes: 3