Detect django testing mode

后端 未结 6 852
逝去的感伤
逝去的感伤 2020-12-14 13:41

I\'m writing a reusable django app and I need to ensure that its models are only sync\'ed when the app is in test mode. I\'ve tried to use a custom DjangoTestRunner, but I f

相关标签:
6条回答
  • 2020-12-14 14:23

    I'm using settings.py overrides. I have a global settings.py, which contains most stuff, and then I have overrides for it. Each settings file starts with:

    from myproject.settings import settings
    

    and then goes on to override some of the settings.

    • prod_settings.py - Production settings (e.g. overrides DEBUG=False)
    • dev_settings.py - Development settings (e.g. more logging)
    • test_settings.py

    And then I can define UNIT_TESTS=False in the base settings.py, and override it to UNIT_TESTS=True in test_settings.py.

    Then whenever I run a command, I need to decide which settings to run against (e.g. DJANGO_SETTINGS_MODULE=myproject.test_settings ./manage.py test). I like that clarity.

    0 讨论(0)
  • 2020-12-14 14:24

    The selected answer is a massive hack. :)

    A less-massive hack would be to create your own TestSuiteRunner subclass and change a setting or do whatever else you need to for the rest of your application. You specify the test runner in your settings:

    TEST_RUNNER = 'your.project.MyTestSuiteRunner'
    

    In general, you don't want to do this, but it works if you absolutely need it.

    from django.conf import settings
    from django.test.simple import DjangoTestSuiteRunner
    
    class MyTestSuiteRunner(DjangoTestSuiteRunner):
        def __init__(self, *args, **kwargs):
            settings.IM_IN_TEST_MODE = True
            super(MyTestSuiteRunner, self).__init__(*args, **kwargs)
    

    NOTE: As of Django 1.8, DjangoTestSuiteRunner has been deprecated. You should use DiscoverRunner instead:

    from django.conf import settings
    from django.test.runner import DiscoverRunner
    
    
    class MyTestSuiteRunner(DiscoverRunner):
        def __init__(self, *args, **kwargs):
            settings.IM_IN_TEST_MODE = True
            super(MyTestSuiteRunner, self).__init__(*args, **kwargs)
    
    0 讨论(0)
  • 2020-12-14 14:25

    I've been using Django class based settings. I use the 'switcher' from the package and load a different config/class for testing=True:

    switcher.register(TestingSettings, testing=True)
    

    In my configuration, I have a BaseSettings, ProductionSettings, DevelopmentSettings, TestingSettings, etc. They subclass off of each other as needed. In BaseSettings I have IS_TESTING=False, and then in TestingSettings I set it to True.

    It works well if you keep your class inheritance clean. But I find it works better than the import * method Django developers usually use.

    0 讨论(0)
  • 2020-12-14 14:30

    Not quite sure about your use case but one way I've seen to detect when the test suite is running is to check if django.core.mail has a outbox attribute such as:

    from django.core import mail
    
    if hasattr(mail, 'outbox'):
        # We are in test mode!
        pass
    else:
        # Not in test mode...
        pass
    

    This attributed is added by the Django test runner in setup_test_environment and removed in teardown_test_environment. You can check the source here: https://code.djangoproject.com/browser/django/trunk/django/test/utils.py

    Edit: If you want models defined for testing only then you should check out Django ticket #7835 in particular comment #24 part of which is given below:

    Apparently you can simply define models directly in your tests.py. Syncdb never imports tests.py, so those models won't get synced to the normal db, but they will get synced to the test database, and can be used in tests.

    0 讨论(0)
  • 2020-12-14 14:41

    Well, you can just simply use environment variables in this way:

    export MYAPP_TEST=1 && python manage.py test
    

    then in your settings.py file:

    import os
    
    TEST = os.environ.get('MYAPP_TEST')
    
    if TEST:
        # Do something
    
    0 讨论(0)
  • 2020-12-14 14:48

    I think the answer provided here https://stackoverflow.com/a/7651002/465673 is a much cleaner way of doing it:

    Put this in your settings.py:

    import sys
    
    TESTING = sys.argv[1:2] == ['test']
    
    0 讨论(0)
提交回复
热议问题