Model only for tests - django

I want to define model only for using in my test suite. It would be nice, to not create it's table on production. Is there any variable I can test agains to check if I'm in test mode?

If you're running your tests using the Django testing framework (python manage.py test) then it will automatically create all of the tables for your models in a completely different database, and then populate those tables from your application fixtures, prior to running your tests. Once the tests have completed, the database will be dropped. (If your production database is named foo, the test database will be named foo_test, unless you specify differently.)
If you have models that you need only for tests, then all you have to do is to place your test models in the same directory structure as your test code, instead of intermingled with your production models. That will ensure that they are not inadvertently mixed into your production database.

If you use at recent version of Django(I can confirm versions since 1.4 until 1.6), and uses django.test, you could put all your test models definitions in tests/__init__.py. This way, you will have test models in unit tests, without them polluting the production database.

Related

Django unittesting fails with CIText and Sqlite

I use CIText from django.contrib.postgres, how can I carry on using SQlite with my unit tests ?
At the moment django dies trying to run my tests with:
django.db.utils.ProgrammingError: type "citext" does not exist
LINE 1: ...gmodel" ALTER COLUMN "name" TYPE citext USING "name"::citext
If you use database-specific features, your application becomes dependent on that particular database.
If the dependencies on the app using citext are minimal, you could create a separate settings file for testing that does not include this app.
That obviously limits your test coverage and is only suitable for quick local testing. On a CI system, you definitely want to use the database you are using in production anyways.

Django: how do I specify on which apps and migrations test case depends?

I want to speed up my tests by running only necessary migrations to build database. Currently, Django runs all of them.
I know how to specify dependencies among migrations and actively use it. I watch for dependencies, most of my tests don't depend even on Django. I want some dividends for that.
Is there any way to specify particular apps or migrations on which test depends?
I found available_apps property of TransactionTestCase, which is marked as private API, but it doesn't work for me. Even if I run single test class or test method.

Django Testing: Does --keepdb reset changes made during tests?

According to the Django docs regarding tests, the --keepdb flag will preserve the the test database for future runs.
https://docs.djangoproject.com/en/1.8/ref/django-admin/#django-admin-option---keepdb
Just to be clear, will any changes made to the database by the tests (ie: object.save() ) be reset automatically? Or will these changes need to be reversed from within the tests?
If you're using Django's default TestCase, all tests are run in a transaction, which is rolled back when the tests finishes. If your database supports transactions, you won't have to clean up anything.
If you're using Django's LiveServerTestCase or TransactionTestCase, all tables are truncated after each test, and the initial data, which is serialized before the test, is reloaded into the test database. This will not preserve any data for migrated apps, only for unmigrated apps.
The --keepdb option will not do anything special with the database. It simply prevents that the test database is destroyed, and if a database is found at the start of the tests, it is used instead of creating a new one. So, any data that is somehow left in the database when the tests finish will be seen as initial data. This is mostly relevant if some error or a user interrupt prevents tests without transactions from cleaning up the database. In that case it may be a good idea to recreate the database.

Isolating database when run multiple django test suites on Jenkins server

Our Jenkins test server runs several different test suites for a Django app, and several of these suites require that a Postgres database is present and seeded with data (e.g., integration tests, database migration tests). Currently, we have a single SQL database dump with the test data, and we load that database in for the different tests.
I'd like to be able to run multiple suites concurrently on the same Jenkins server. However, I can't do that with the current model since multiple suites would try to use the same database and clobber each other.
I'll probably just use a sed script to modify the SQL dump file for each test suite before loading it so each suite uses a database with a different name. Is there a more elegant way to solve this problem?

Django test to use existing database

I'm having a hard time customizing the test database setup behavior. I would like to achieve the following:
The test suites need to use an existing database
The test suite shouldn't erase or recreate the database instead load the data from a mysql dump
Since the db is populated from a dump, no fixtures should be loaded
Upon finishing tests the database shouldn't be destroyed
I'm having a hard time getting the testsuiterunner to bypass creation.
Fast forward to 2016 and the ability to retain the database between tests has been built into django. It's available in the form of the --keep flag to manage.py
New in Django 1.8. Preserves the test database between test runs. This
has the advantage of skipping both the create and destroy actions
which can greatly decrease the time to run tests, especially those in
a large test suite. If the test database does not exist, it will be
created on the first run and then preserved for each subsequent run.
Any unapplied migrations will also be applied to the test database
before running the test suite.
This pretty much fullfills all the criteria you have mentioned in your questions. In fact it even goes one step further. There is no need to import the dump before each and every run.
This TEST_RUNNER works in 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
You'll need to provide a custom test runner.
The bits your interested in overriding with the default django.test.runner.DiscoverRunner are the DiscoverRunner.setup_databases and DiscoverRunner.teardown_databases methods. These two methods are involved with creating and destroying test databases and are executed only once. You'll want to provide test-specific project settings that use your existing test database by default and override these so that the dump data is loaded and the test database isn't destroyed.
Depending on the size and contents of the dump, a safe bet might be to just create a subprocess that will pipe the dump to your database's SQL command-line interface, otherwise you might be able to obtain a cursor and execute queries directly.
If your looking to get rid of fixture loading completely, you can provide a custom base test case that extends Django's default django.test.testcases.TestCase with the TestCase._fixutre_setup and TestCase._fixutre_teardown methods overriden to be noop.
Caveat emptor: this runner will make it impossible to facilitate tests for anything but your application's sources. It's possible to customize the runner to create a specific alias for a connection to your existing database and load the dump, then provide a custom test case that overrides TestCase._database_names to point to it's alias.