How to run django unit-tests on production database?
Solution 1:
In case someone googles here searching for the solution for a given problem, here is the skeleton on how to perform unit tests on django production database. Check the django docs section here, for the file/directory structure, and instructions on where to put the given code. It should go in yourapp/management/commands/newcommandname.py
, and both the management and commands folders should contain empty __init__.py
files which makes python treat them as valid modules.
The test suite can by run as:
$python manage.py newcommandname
And here comes the code you should put in yourapp/management/commands/newcommandname.py
:
from django.core.management.base import BaseCommand
import unittest
class Command(BaseCommand):
help = """
If you need Arguments, please check other modules in
django/core/management/commands.
"""
def handle(self, **options):
suite = unittest.TestLoader().loadTestsFromTestCase(TestChronology)
unittest.TextTestRunner().run(suite)
class TestChronology(unittest.TestCase):
def setUp(self):
print "Write your pre-test prerequisites here"
def test_equality(self):
"""
Tests that 1 + 1 always equals 2.
"""
from core.models import Yourmodel
self.failUnlessEqual(1 + 1, 2)
Solution 2:
First, if you're running it on the production database, it isn't much of a "unit" test.
It's a first-class batch job and needs to be treated like a first-class production batch job.
You cam't to use the Django test
command for looking at production data. It always creates an empty database which is populated from fixtures in the TestCase.
You could make your production database processing a proper management command. This has the environment all properly configured so that your command can simply use the Django ORM to process your data.
The alternative is to be sure that you configure your settings. Either
use the DJANGO_SETTINGS_MODULE
environment variable or use the settings.configure()
function to create an environment.
You can then import the models and do the processing you want to do against the production database.
You can call it "test" if you want to, but you're looking at production data, so it's got to be treated like production application with respect to getting the settings file and using the proper ORM configuration.
Solution 3:
This TEST_RUNNER works on Django 1.3
from django.test.simple import DjangoTestSuiteRunner as TestRunner
class DjangoTestSuiteRunner(TestRunner):
def setup_databases(self, **kwargs):
pass
def teardown_databases(self, old_config, **kwargs):
pass
Solution 4:
A unittest is meant to test without any sideeffects. Though your test would be nothing that is known as unittest. If you want to do it anyway, you can use a custom test runner that is setting up the database (or in your case using the existing db).
You can set the TEST_RUNNER setting in your settings.py file. The default is locate in django.test.simple.run_tests
. You can look at the source here:
http://code.djangoproject.com/browser/django/trunk/django/test/simple.py
Copy and paste the code in a new file and remove the following lines from the code:
connection.creation.create_test_db(verbosity, autoclobber=not interactive)
...connection.creation.destroy_test_db(old_name, verbosity)
This will prevent django from creating a test database and reseting the database configuration of your settings file.
Solution 5:
Not a good idea, but if you know what you are doing (basically breaking your production) you can check this setting:
https://docs.djangoproject.com/en/2.2/ref/settings/#test
DATABASES = {
'default': {
...
'TEST': {
'NAME': 'your prod db'
}
}