3

I'd like to know immediately when I've broken a test in Django. Instead of always running manage.py test separately, is there a way to run tests in the background when running manage.py runserver and report them to that same terminal? The tests would ideally be re-run when a file is saved, just like how the server is reloaded normally.

This would be great to detect mistakes sooner. And even better that it'd be right in your face instead of hiding behind a manual test step.

Is this possible?

3
  • Using Pycharm, I made a custom configuration to target manage.py and run test --pattern="*_test.py" this way I just have to name all my test files *_test.py Commented Mar 30, 2015 at 17:20
  • It is possible with various ways, you could do it through a custom python script, or through a shell script, you could even create a custom Django management command, it all depends on how you would like to integrate that in your project. Commented Mar 30, 2015 at 17:26
  • @petkostas Django management command would be ok. I'm just making sure I didn't overlook something obvious, or if there was an existing solution out there already if this isn't a built-in feature. Commented Mar 30, 2015 at 17:35

1 Answer 1

1

I ended up overriding the management command.

app-name\management\commands\runserver.py:

from __future__ import print_function

import subprocess
from threading import Thread

from django.core.management.commands.runserver import Command as BaseCommand
# or: from devserver.management.commands.runserver import Command as BaseCommand
from django.conf import settings
from termcolor import colored


BEEP_CHARACTER = '\a'


def call_then_log():
    try:
        output = subprocess.check_output('manage.py test --failfast',
                                         stderr=subprocess.STDOUT, shell=True)
    except subprocess.CalledProcessError as ex:
        print(colored(ex.output, 'red', attrs=['bold']))
        print(BEEP_CHARACTER, end='')
        return

    print(output)


def run_background_tests():
    print('Running tests...')
    thread = Thread(target=call_then_log, name='runserver-background-tests')
    thread.daemon = True
    thread.start()


class Command(BaseCommand):
    def inner_run(self, *args, **options):
        if settings.DEBUG and not settings.TESTING:
            run_background_tests()
        super(Command, self).inner_run(*args, **options)

requirements.txt:

termcolor

This runs your tests in a background thread, which runs each time Django auto-reloads. The old thread will be stopped. If any test fails, it will beep and the first failure result will be printed in red to the terminal.

This answer is also worth reading for speeding up your tests for an even faster feedback loop.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.