How to test custom django-admin commands

DjangoTestingDjango AdminCustom Action

Django Problem Overview


I created custom django-admin commands

But, I don't know how to test it in standard django tests

Django Solutions


Solution 1 - Django

If you're using some coverage tool it would be good to call it from the code with:

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

class CommandsTestCase(TestCase):
    def test_mycommand(self):
        " Test my custom command."

        args = []
        opts = {}
        call_command('mycommand', *args, **opts)

        # Some Asserts.

From the official documentation

> Management commands can be tested with the call_command() function. The output can be redirected into a StringIO instance

Solution 2 - Django

You should make your actual command script the minimum possible, so that it just calls a function elsewhere. The function can then be tested via unit tests or doctests as normal.

Solution 3 - Django

you can see in github.com example see here

def test_command_style(self):
    out = StringIO()
    management.call_command('dance', style='Jive', stdout=out)
    self.assertEquals(out.getvalue(),
        "I don't feel like dancing Jive.")

Solution 4 - Django

To add to what has already been posted here. If your django-admin command passes a file as parameter, you could do something like this:

from django.test import TestCase
from django.core.management import call_command
from io import StringIO
import os

    
class CommandTestCase(TestCase):
    def test_command_import(self):
        out = StringIO()
        call_command(
            'my_command', os.path.join('path/to/file', 'my_file.txt'),
            stdout=out
        )
        self.assertIn(
        'Expected Value',
            out.getvalue()
        )

This works when your django-command is used in a manner like this:

$ python manage.py my_command my_file.txt

Solution 5 - Django

A simple alternative to parsing stdout is to make your management command exit with an error code if it doesn't run successfully, for example using sys.exit(1).

You can catch this in a test with:

    with self.assertRaises(SystemExit):
        call_command('mycommand')

Solution 6 - Django

I agree with Daniel that the actual command script should do the minimum possible but you can also test it directly in a Django unit test using os.popen4.

From within your unit test you can have a command like

fin, fout = os.popen4('python manage.py yourcommand')
result = fout.read()

You can then analyze the contents of result to test whether your Django command was successful.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiondixonView Question on Stackoverflow
Solution 1 - DjangoJorge E. CardonaView Answer on Stackoverflow
Solution 2 - DjangoDaniel RosemanView Answer on Stackoverflow
Solution 3 - DjangomadjardiView Answer on Stackoverflow
Solution 4 - DjangoasforView Answer on Stackoverflow
Solution 5 - DjangoBoscoView Answer on Stackoverflow
Solution 6 - DjangoAaron VernonView Answer on Stackoverflow