Reputation: 151
I have a very basic Django app (Python 3.6.4) and I've written a unit test which passes locally. An in memory SQLite DB is created (by default) for the tests. When my Travis CI build runs the same tests the tests pass but the test command fails with the following error:
File "/home/travis/virtualenv/python3.6.5/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 301, in execute
return Database.Cursor.execute(self, query)
django.db.utils.OperationalError: near "SCHEMA": syntax error
The command "python manage.py test --settings=myapp.dev_settings" exited with 1.
One strange thing I notice is that when the tests are run on Travis, it's says it's reusing an existing DB and never destroys it after the tests are run:
$ python manage.py test --settings=myapp.dev_settings
Using existing test database for alias 'default'...
I don't really get that, because it should be an in memory DB and when I run it locally, a new database is created each time:
Creating test database for alias 'default'...
. . .
Destroying test database for alias 'default'...
My dev_settings.py
file has a sqlite db on the filesystem, but that is only used for running the local development server:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
Travis installs all the dependencies and they match my local environment (I'm fairly sure).
Any help would be great, I'm definitely missing something obvious here!!!
Upvotes: 2
Views: 1561
Reputation: 839
This is because the Django-Heroku package sets its own Test Runner that does extra stuff with the database if it detects a CI environment, presumably to cater to their Heroku CI offering:
# Enable test runner if found in CI environment.
if 'CI' in os.environ:
config['TEST_RUNNER'] = 'django_heroku.HerokuDiscoverRunner'
The test runner does the following which does not work for SQLite:
with connection.cursor() as cursor:
cursor.execute(
"""
DROP SCHEMA public CASCADE;
CREATE SCHEMA public;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO public;
COMMENT ON SCHEMA public IS 'standard public schema';
"""
)
Unfortunately this check also detects non-Heroku CI environments such as Travis or GitLab CI and attempts to use the above configuration.
You can solve this problem by disabling the Heroku test runner like so in your settings.py
:
# Configure Django App for Heroku.
django_heroku.settings(locals(), test_runner=False)
Upvotes: 6
Reputation: 695
@LaSmell is correct (I had the same problem). It's because you're trying to access Heroku dependencies in your build.
BUT I can still show you how to implement a solution.
You need to do 3 things to solve this problem.
1 - Specify a new requirements doc without django-heroku
I personally made another file called requirements-build.txt and it has all the same dependencies except django-heroku==0.3.1
I just delete it out.
2 - Specify the new requirements file in .travis.yml
In your .travis.yml file just replace
install:
- pip install -r requirements.txt
with
install:
- pip install -r requirements-build.txt
3 - Account for these changes in your settings.py file
To make sure you don't import heroku-django if it's not installed, check if it can be imported first. I did:
# Try to import django-heroku depending on Travis or Heroku
try:
# Configure Django App for Heroku.
import django_heroku
django_heroku.settings(locals())
except ImportError:
found = False
This way it will only use django-heroku if it has been installed. Since Heroku uses requirements.txt by default this patch works perfectly fine.
Hope this helps! It took me a while to get it myself.
Upvotes: 2
Reputation: 151
In the stack trace of the travis build I noticed an unexpected package being executed:
File "/home/travis/virtualenv/python3.6.5/lib/python3.6/site-packages/django_heroku/core.py", line 41, in teardown_databases
self._wipe_tables(connection)
The problem was I was executing my tests with a settings.py file that included Heroku (deployment) specific code:
import django_heroku
import dj_database_url
# Parse database configuration from Heroku's $DATABASE_URL (Postgres)
DATABASES = {
'default': dj_database_url.config(conn_max_age=500, ssl_require=True)
}
# Activate Django-Heroku (DATABASE_URL and all that).
django_heroku.settings(locals())
And dependencies in my requirements.txt file:
django-heroku==0.3.1
Once I remove all the Heroku config from the Travis build config, the build passes!
Still unsure how I didn't see this fail locally.
Upvotes: 1