Django unittests - ImproperlyConfigured error - django

Im trying to write tests for my module. When i run:
python manage.py test my_module
Im getting message:
django.core.exceptions.ImproperlyConfigured: Please fill out the database NAME in the settings module before using the database.
I dont have any test yet, just BaseTest where im creating users, groups and assigning permissions.
Where could be the problem? Server normally works, configuration seems to be good. Do i need to define settings for test?
Ok. I think i know what was the problem :] I had lists with permissions stored in other module. So i were writting from module.perms import perms (normal python list). Its seems, that python is doing something more than just import that list from other module to my module. And that was the cause of failing.
Solution:
Surround code after list definition with:
if __name__ == "__main__":
...
Then everything should be working good.

Ok. I think i know what was the problem :] I had lists with permissions stored in other module. So i were writting from module.perms import perms (normal python list). Its seems, that python is doing something more than just import that list from other module to my module. And that was the cause of failing.
Solution: Surround code after list definition with:
if __name__ == "__main__":
...
Then everything should be working good.

You need to have your DATABASE setting in place in settings.py, and your app needs to be in installed apps. For example:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'database.sqlite',

python manage.py test doesn't use the NAME database defined in settings.py DATABASES. From the docs -
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.
By default the test databases get their names by prepending test_ to
the value of the NAME settings for the databases defined in DATABASES.
When using the SQLite database engine the tests will by default use an
in-memory database (i.e., the database will be created in memory,
bypassing the filesystem entirely!). If you want to use a different
database name, specify TEST_NAME in the dictionary for any given
database in DATABASES.
To answer your question. You can define a test database with the TEST_NAME setting. But you shouldn't have to.

Here's another potential solution for people finding this through search:
I was trying to define my own TestRunner class inside my settings file, which meant it had to import DjangoTestSuiteRunner. This import at the top of the file caused the ImproperlyConfigured error. Moving the custom TestRunner class to a separate file resolved the issue.

Related

django: Use different configuration for test database?

Can I specific a different configuration for the test database? Or alternatives simply use a different user in production?(how to manage that as settings file needs to be updated as well?) The testing requirements for postgresql require in my opinion too many privs like create DB and in my case I also need to create an extension upon db creation which means superuser privileges.
This is very messy, but a valid workaround nonetheless. We use a snippet of code like this in settings.py to run tests using a local sqlite3 database.
import sys
if 'test' in sys.argv or 'test_coverage' in sys.argv:
DATABASES['default']['ENGINE'] = 'django.db.backends.sqlite3'
DATABASES['default']['NAME'] = os.path.join(BASE_DIR, 'db.sqlite3')

How to access django database with pytest

I am wanting to use pytest with django to test api queries. Is there any way to do this in pytest without resorting to creating a test database? Pytest keeps throwing an error that database access is not allowed. I end up having to do this at the top of my pytest files:
import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE","MyProject.settings")
import django
django.setup()
I tried using the pytest-django library, but it doesn't have a mark for accessing the db that I can use.
It always helps to rtfd:
https://pytest-django.readthedocs.io/en/latest/database.html
pytest-django takes a conservative approach to enabling database access. By default your tests will fail if they try to access the database. Only if you explicitly request database access will this be allowed. This encourages you to keep database-needing tests to a minimum which makes it very clear what code uses the database.

Django database not always available

I have specified multiple databases in settings.py. One of the databases is a local Oracle database which is only available on my computer at work. So when I open my site on a computer which does not have access to this Oracle database, I see the error A server error occurred. Please contact the administrator..
So my code works as it should when I'm on my work computer, but fails when I use my page online from another computer which does not have access to the local Oracle database.
I don't want to access the local database remotely. I just want to ignore the error when I don't have access to the local Oracle database.
You can use a local.py file in your settings module that is unique for the environment you're working on. Given a settings module, you can put the following in your __init__.py:
try:
import .local
except ImportError:
pass
Then on the machine where the Oracle database is available, set the right settings in the local settings file, but don't check it in to your version control system (e.g. put it in .gitignore).
Also watch for the order in your settings, after you import your local settings, you shouldn't override them if you want to keep the changes. You can move the import down in the file, or just add the settings to the existing dict.
You can use if statements in your settings.py, since it's just a Python script. So you can add a function to detect whether you are at work, and then use that function to decide whether the at work-only database should be added to the DATABASES variable.
# in settings.py
def at_work():
'Determines whether the project runs at work'
if at_work():
DATABASES = {...}
else:
DATABASES = {...}
Of course, if your models depend on the database that is only available at work, you will need to add a mock database to enable use of the models elsewhere, even if there is no data available.

Getting rid of empty models.py in django testsuite

I have two pure service apps, that act as servant to my core models. Hence, they do not have any own models.
While the testsuite for the first service runs fine, the second throws the following error:
django.core.exceptions.ImproperlyConfigured:
App with label location is missing a models.py module.
If I add an empty models.py, the suite runs fine.
I can't spot a difference in terms of architecture / structure between the apps. But I want to get rid of the empty, unneeded models.py.
How would I do that?
Update: What you ask is now possible. With Django 1.7 you no longer need a models.py file. -release notes
Previously: Django testing requires every app to have a models.py file. It's okay to leave it empty (or with a helpful comment!). Ticket discussion on the matter of apps without models. Direct from the code (added in 1.4/still in 1.5):
the test runner won't currently load a test module with no models.py file
As far as I know, it is necessary to include a 'models.py' module on every Django application to make it run properly

django - specify database for TestCase fixtures

I have two databases that my site uses and I have an app that uses both of them. I need to write a TestCase that loads fixtures for both databases. I use a DB router, which works fine in production, but in the testing framework, Django insists on using the 'default' database for all fixtures, even for models that specify the other database. How do I tell Django to run a fixture against another database?
My TestCase is defined list:
class VerifierTestCase(TestCase):
fixtures = ['zipcodes_test.json', 'all_states.json', 'wtf.json']
multi_db = True
There is actually a bug in Django that causes it to ignore the name-based db-specific pointers if you specify the entire fixture name.
so if you do fixtures = ["mydata.default.yaml", "mydata.myotherdatabase.yaml"]
It will load both fixtures into the default database.
But if you do fixtures = ['mydata']
It will load correctly. This is also true for dbengine specific filenames (e.g. mydata.default.postgresql.sql) as well.
Fixtures are targeted at specific databases by filename. This is true in TestCase instances as well, as they just call the loaddata command.
See https://docs.djangoproject.com/en/dev/ref/django-admin/#database-specific-fixtures
If you have a multi-db setup with models exclusive to each database. You need to save a fixture file for each database (with the non-applicable database files being empty).
If your code defines fixtures = ["sample"] and you have two databases default and other.
You need two files: sample.default.json and sample.other.json. If sample contains only models from db default, sample.other.json will be an empty file ([]) and vice-versa.
Tried with Django 3.2