Search code examples
pythondjangobashpython-multithreadingdjango-testing

Django does not exit after finishing tests when using threading module


I am doing integration tests using django.test.SimpleTestCase.
After running python manage.py test, the tests run successfully and the terminal hangs with the message:

---------------------------
Ran 5 tests in 1.365s

OK

The problem is that currently I go back to the terminal using CTRL+C, but I want to have automated tests in my CI/CD pipeline.

Did I do something wrong in the way I executed the tests? Or is this behaviour normal? In this case, is there an way in Bash to programatically execute and then exit the tests?

EDIT:
After analysing my app in depth, I was able to identify what was causing that behaviour. I am using threading in a way like the following in my views.py:

def __pooling():
  wait_time = 10
  call_remote_server()
  threading.Timer(wait_time, __pooling).start()

__pooling()

Basically I need that my application do something from time to time asynchronously. Should I change the way I am doing the pooling? Or should I disable it (how?) during the tests?


Solution

  • I was able to identify what was causing that behaviour. I am using threading in a way like the following in my views.py:

    def __pooling():
      wait_time = 10
      call_remote_server()
      threading.Timer(wait_time, __pooling).start()
    
    __pooling()
    

    Basically I need that my application do something from time to time asynchronously. Should I change the way I am doing the pooling?

    I don't fully understand your needs, but a more traditional approach would be to schedule a task (probably a management command) outside of Django itself. An OS-level scheduler like cron or Windows Task Scheduler, something like APScheduler, or a task queue like Celery would all be reasonable choices.

    Or should I disable it (how?) during the tests?

    I don't recommend continuing to use your __pooling() function as it exists today. In my opinion this kind of thing doesn't belong in your views.py. But if you want to keep it, something like

    from django.conf import settings
    
    if not settings.DEBUG:
      __pooling()
    

    might help. Your __pooling() function would only be called when DEBUG is falsy, as it should be in production. (If it is also falsy in your CI environment you could choose another existing setting, or add something to your settings.py specifically to control this.)