Background
I have a Django project ("api") with unittest tests and behave features. Relevant parts of its structure are
code/ # i.e. the Django root is not the root of the project
manage.py
api/
settings.py
# and other Django stuff
app/
# Django app stuff
features/
environment.py
steps/
foo.feature
virtualenv/
I use behave-django. python manage.py behave
works.
I use PyCharm. It's configured to use the project's virtualenv. Its Django support is configured thus:
Running Django and running unittest tests inside PyCharm works.
The problem
When I attempt to run a behave feature in PyCharm (by hitting control-shift-R when editing the feature file and choosing the behave run context configuration) I get
/Users/dave/data/projects/api/code/virtualenv/bin/python2.7 "/Applications/PyCharm 2016.3.app/Contents/helpers/pycharm/behave_runner.py"
Testing started at 04:31 ...
Traceback (most recent call last):
File "/Applications/PyCharm 2016.3.app/Contents/helpers/pycharm/behave_runner.py", line 294, in <module>
_BehaveRunner(my_config, base_dir).run()
File "/Applications/PyCharm 2016.3.app/Contents/helpers/pycharm/_bdd_utils.py", line 91, in run
number_of_tests = self._get_number_of_tests()
File "/Applications/PyCharm 2016.3.app/Contents/helpers/pycharm/_bdd_utils.py", line 211, in _get_number_of_tests
for feature in self._get_features_to_run():
File "/Applications/PyCharm 2016.3.app/Contents/helpers/pycharm/behave_runner.py", line 231, in _get_features_to_run
self.__real_runner.run()
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/behave/runner.py", line 672, in run
return self.run_with_paths()
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/behave/runner.py", line 678, in run_with_paths
self.load_step_definitions()
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/behave/runner.py", line 658, in load_step_definitions
exec_file(os.path.join(path, name), step_module_globals)
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/behave/runner.py", line 304, in exec_file
exec(code, globals, locals)
File "code/features/steps/common.py", line 5, in <module>
from django.contrib.auth.models import User
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/contrib/auth/models.py", line 4, in <module>
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/contrib/auth/base_user.py", line 52, in <module>
class AbstractBaseUser(models.Model):
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/contrib/auth/base_user.py", line 53, in AbstractBaseUser
password = models.CharField(_('password'), max_length=128)
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 1043, in __init__
super(CharField, self).__init__(*args, **kwargs)
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/db/models/fields/__init__.py", line 166, in __init__
self.db_tablespace = db_tablespace or settings.DEFAULT_INDEX_TABLESPACE
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/conf/__init__.py", line 53, in __getattr__
self._setup(name)
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/conf/__init__.py", line 39, in _setup
% (desc, ENVIRONMENT_VARIABLE))
django.core.exceptions.ImproperlyConfigured: Requested setting DEFAULT_INDEX_TABLESPACE, but settings are not configured. You must either define the environment variable DJANGO_SETTINGS_MODULE or call settings.configure() before accessing settings.
Process finished with exit code 1
How can I run my behave features in the intended way in PyCharm?
Things I tried that didn't work
Setting the run configuration's working directory to .../api/code
didn't make a difference.
The suggestion in the stack trace above seems bogus, because the settings file is the default, and I didn't need to set DJANGO_SETTINGS_MODULE
to make anything else work in or out of PyCharm, but if I add DJANGO_SETTINGS_MODULE=api.settings
to the behave run configuration in PyCharm I get
[some duplicate stack frames removed]
File "code/features/steps/common.py", line 5, in <module>
from django.contrib.auth.models import User
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/contrib/auth/models.py", line 4, in <module>
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/contrib/auth/base_user.py", line 52, in <module>
class AbstractBaseUser(models.Model):
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/db/models/base.py", line 105, in __new__
app_config = apps.get_containing_app_config(module)
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/apps/registry.py", line 237, in get_containing_app_config
self.check_apps_ready()
File "/Users/dave/data/projects/api/code/virtualenv/lib/python2.7/site-packages/django/apps/registry.py", line 124, in check_apps_ready
raise AppRegistryNotReady("Apps aren't loaded yet.")
django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
When I run django.setup()
in features/environment.py
(not in before_all
, but at the top level) I get farther, but
- the tests run in my regular database, not in a temporary test database, and
- behave-django features like
context.base_url
are not available, so some tests fail.
How can I make this work?
(Disclosure: I'm one of the maintainers of
behave-django
, the integration of behave and Django.)Behave Is a Standalone Tool
The actual problem is that
behave
is not meant to be aware of Django and integrate into it. It's meant to run as an external tool. And that's what PyCharm (2016.3.1) seems to take for granted, and what happens when PyCharm runs the tests. The tests are run just as if you ranbehave
(notpython manage.py behave
!) from the terminal.In
code/features/steps/common.py
, line 5, you have an import towards Django (User model), which requires Django being already running, e.g. via a management command (runserver
). Inbehave-django
we require a management command to be run instead, so that aLiveServerTestCase
can launch before your code is reached. Django will be ready, because we make it launch a runserver before it hits your code.JetBrains would have to take this into account if
behave-django
should work out of the box.Alternative Integration (Partial Solution)
You can integrate into Django with
behave
only, no need forbehave-django
, with a few extra lines of code inenvironment.py
. You will lose a few features of our integration, and you'll have to replicate this integration approach over all your projects, though.See the Manual Integration section of the behave docs. You could try to replicate
behave-django
's behavior by adding some of its code to access thelive_server_url
to your test setup.The rest is probably up to JetBrains. Sorry for the bad news!