I'm trying to create tests for my Django application but I'm having some trouble creating a test database.
I'd like to keep the existing structure while entering new curated test-information, creating test users, uploading test content, etc. Which I can then populate a test database with so that I have curated data on which I can test edge-cases.
Creating a test database seems simple, just run python manage.py test --keepdb. Getting entries into it seems more difficult.
Is it possible to run Django in "test mode" with the test database being used so that I can use the website UI to enter all the data, or is there some other better way to do it entirely?
I assume you mean testing with unit tests?
Usually you fill the database with fixtures, or some other test data that is populated into the database as a part of the test itself.
Django fixtures: https://code.djangoproject.com/wiki/Fixtures
Fixtureless is a good option, https://pypi.org/project/django-fixtureless/
Factory Boy http://factoryboy.readthedocs.io/en/latest/
These options allow you to fill your database with fake or static data to use in your tests.
Related
I want to use my test database with data in it which was created when testcase ran, how can i do it?
I tried running normal django test which inherits TestCase and put a break point after test data is been generated. Now if I login to the test_db (which django creates) in different terminal tab through postgres command and query it, no data is shown! can someone explain why this happens?
TestCase wraps tests in an atomic block and rolls back the transaction so that no changes are saved to the database.
If you want changes to be saved, you could use SimpleTestCase, and set databases = __all__ (Django 2.2+), or allow_database_queries = True (earlier versions of Django).
I used inspectdb to import the Models schema from MySQL database connected with MySQL Connector/Python.
When I run the tests, the system shows:
django.db.utils.ProgrammingError: Table 'test_mydb.cards' doesn't exist
But the table name is just mydb.cards, not test_mydb.cards
Why is this prefix being added? My app's name is just container.
Django uses unittest module for testing, also it creates a blank database for testing as tests should be run ideally always on same blank database or fixtures filled database.
Tests that require a database (namely, model tests) will not use your
“real” (production) database. Separate, blank databases are created
for the tests.
Regardless of whether the tests pass or fail, the test databases are
destroyed when all the tests have been executed.
Check out if you are having migration sorted for the table test tries to access, as all tables that don't have migrations aren't accessible to test suite without monkeypatching or workarounds
I found the reason: I had managed property to False in models.py Class Meta for each table. I never set it there myself, it is the default after doing inspectdb.
Please read: Django Models Options: Managed
In my Django app, I want to add a couple of fields to my existing models and possibly create a new class. I just want to test the new feature and approve if it works.
I can revert the code using git easily. But if I make a makemigrations+migrate then my MySQL database will change and reversing the changes looks like manual deletion of tables and reverting to an old state using a command like django-admin migrate [app_label] [migration_name] (In some cases it looks really cumbersome, example).
I'm wondering if there is any safe practice to try manipulating the database and revert it back to it's initial state safely.
Probable solution #1:
You can utilize the test database that gets created when using django.test.TestCase:
Tests that require a database (namely, model tests) will not use your
“real” (production) database. Separate, blank databases are created
for the tests.
Create some unit tests for your project and make your migrations (without migrating to your production DB, just keep the migrations). Then:
If the database does not exist, it will first be created. Any
migrations will also be applied in order to keep it up to date.
Usually, the database gets destroyed at the end of your tests, but you can keep it between runs:
You can prevent the test databases from being destroyed by using them
test --keepdb option. This will preserve the test database between
runs.
With this trick you can test every migration you make in a fake DB and when you do finalize your model and you have all the migrations history complete, you can migrate on your production DB.
Probable solution #2:
You can make a copy of your database as #albar suggests and have it as a back up while you are working on your new migrations.
Break stuff as much as you want and when you are set and done, replace the "battered" DB with your back up and apply your migration history to it.
Background
I'm trying to replace fixtures in my unit tests with model factories (using Factory Boy). It would help for me to determine why the current unit tests are failing if I could look at the database generated by loading the fixtures and compare them to the data generated by the factories.
I have tried to use the --keepdb flag when running the tests to save a copy of the test database but this doesn't seem to save an accessible database anywhere.
Question
Django test databases are discarded after the tests run. Is there any way to save a copy of a database before it is deleted?
Alternatively, is there a better way to compare the data created by a fixture file and the data created by a model factory?
My default database is not being migrated into Django's test database. A database is being created with default tables that Django uses to log tests (such as django_content_type and django_admin_log), but not my app's tables.
When I run the tests with a verbosity level of 3 (-v 3), I see that my app is categorized under Synchronizing apps without migrations... which confirms that the migrations aren't being performed.
I don't, however, know how to tell Django's tests to migrate my app's database tables. I can output python manage.py makemigrations easily but apparently that doesn't carry over to the tests.
What am I missing?
Thank you!
Edit: Sorry, I meant the relations are not being created. I want to test views which rely on models in the database. In order to do so, I'm uploading fixtures (to not deal with data on production). However, when I try to upload a fixture I get a relation "mymodel" does not exist error.
Django's tests are designed to create a test database to perform tests.
I think that making your tests depend of a prod database is a bad idea.
You should design your tests to cover as many cases as possible, not to check if it works with your current database (which can evolve).
Here are some pages about testing with django 1.8 :
https://docs.djangoproject.com/en/1.8/intro/tutorial05/
https://docs.djangoproject.com/en/1.8/topics/testing/