140👍
Put this in your settings.py:
import sys
TESTING = len(sys.argv) > 1 and sys.argv[1] == 'test'
This tests whether the second commandline argument (after ./manage.py
) was test
. Then you can access this variable from other modules, like so:
from django.conf import settings
if settings.TESTING:
...
There are good reasons to do this: suppose you’re accessing some backend service, other than Django’s models and DB connections. Then you might need to know when to call the production service vs. the test service.
24👍
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)
- [Django]-How to set current user to user field in Django Rest Framework?
- [Django]-Do we need to upload virtual env on github too?
- [Django]-How to define two fields "unique" as couple
15👍
Just look at request.META['SERVER_NAME']
def my_view(request):
if request.META['SERVER_NAME'] == "testserver":
print "This is test environment!"
- [Django]-Change model class name in Django admin interface
- [Django]-Django URL Redirect
- [Django]-Enforce unique upload file names using django?
9👍
There’s also a way to temporarily overwrite settings in a unit test in Django. This might be a easier/cleaner solution for certain cases.
You can do this inside a test:
with self.settings(MY_SETTING='my_value'):
# test code
Or add it as a decorator on the test method:
@override_settings(MY_SETTING='my_value')
def test_my_test(self):
# test code
You can also set the decorator for the whole test case class:
@override_settings(MY_SETTING='my_value')
class MyTestCase(TestCase):
# test methods
For more info check the Django docs: https://docs.djangoproject.com/en/1.11/topics/testing/tools/#django.test.override_settings
- [Django]-How to convert a Django QuerySet to a list?
- [Django]-How to get a favicon to show up in my django app?
- [Django]-How to return HTTP 400 response in Django?
6👍
I think the best approach is to run your tests using their own settings file (i.e. settings/tests.py). That file can look like this (the first line imports settings from a local.py settings file):
from local import *
TEST_MODE = True
Then do ducktyping to check if you are in test mode.
try:
if settings.TEST_MODE:
print 'foo'
except AttributeError:
pass
- [Django]-Limit foreign key choices in select in an inline form in admin
- [Django]-Django manage.py runserver invalid syntax
- [Django]-Django: Calculate the Sum of the column values through query
3👍
If you are multiple settings file for different environment, all you need to do is to create one settings file for testing.
For instance, your setting files are:
your_project/
|_ settings/
|_ __init__.py
|_ base.py <-- your original settings
|_ testing.py <-- for testing only
In your testing.py, add a TESTING
flag:
from .base import *
TESTING = True
In your application, you can access settings.TESTING
to check if you’re in testing environment.
To run tests, use:
python manage.py test --settings your_project.settings.testing
- [Django]-What are the differences between django-tastypie and djangorestframework?
- [Django]-When should I use a custom Manager versus a custom QuerySet in Django?
- [Django]-How to create an object for a Django model with a many to many field?
2👍
While there’s no official way to see whether we’re in a test environment, django actually leaves some clues for us.
By default Django’s test runner automatically redirects all Django-sent email to a dummy outbox. This is accomplished by replacing EMAIL_BACKEND in a function called setup_test_environment, which in turn is called by a method of DiscoverRunner. So, we can check whether settings.EMAIL_BACKEND is set to ‘django.core.mail.backends.locmem.EmailBackend’. That mean we’re in a test environment.
A less hacky solution would be following the devs lead by adding our own setting by subclassing DisoverRunner and then overriding setup_test_environment method.
- [Django]-Django : Testing if the page has redirected to the desired url
- [Django]-AngularJS with Django – Conflicting template tags
- [Django]-How to create a user in Django?
1👍
Piggybacking off of @Tobia’s answer, I think it is better implemented in settings.py like this:
import sys
try:
TESTING = 'test' == sys.argv[1]
except IndexError:
TESTING = False
This will prevent it from catching things like ./manage.py loaddata test.json
or ./manage.py i_am_not_running_a_test
- [Django]-How to pass multiple values for a single URL parameter?
- [Django]-Django Framework – Is there a shutdown event that can be subscribed to?
- [Django]-Django: How to get related objects of a queryset?
0👍
I wanted to exclude some data migrations from being run in tests, and came up with this solution on a Django 3.2 project:
class Migration(migrations.Migration):
def apply(self, project_state, schema_editor, collect_sql=False):
import inspect
if 'create_test_db' in [i.function for i in inspect.stack()]:
return project_state
else:
return super().apply(project_state, schema_editor, collect_sql=collect_sql)
I haven’t seen this suggested elsewhere, and for my purposes it’s pretty clean. Of course, it might break if Django changes the name of the create_test_db
method (or the return value of the apply
method) at some point in time, but modifying this to work should be reasonably simple, since it’s likely that some method exists in the stack that doesn’t exist during non-test migration runs.
- [Django]-How to access Enum types in Django templates
- [Django]-Manually logging in a user without password
- [Django]-Django exception middleware: TypeError: object() takes no parameters