为什么没有表现出与Django一起工作的文档手动集成?

时间:2016-12-20 12:48:35

标签: python django python-2.7 python-behave

我有一个Django(1.10.2)项目(“theproject”)和一些表现(0.4.0)的功能。我一直在使用behave-django。 python manage.py behave有效。但是,PyCharm (which uses the behave executable rather than a Django management command) doesn't know how to run my features,我正在尝试使用behave's documented "manual integration" with Django

我的整个features/environment.py

import os
import django
from django.test.runner import DiscoverRunner
from django.test.testcases import LiveServerTestCase
from splinter.browser import Browser

os.environ["DJANGO_SETTINGS_MODULE"] = "theproject.settings"

def before_all(context):
    django.setup()
    context.test_runner = DiscoverRunner()
    context.test_runner.setup_test_environment()
    context.old_db_config = context.test_runner.setup_databases()
    context.browser = Browser('phantomjs')

    # When we're running with PhantomJS we need to specify the window size.
    # This is a workaround for an issue where PhantomJS cannot find elements
    # by text - see: https://github.com/angular/protractor/issues/585
    if context.browser.driver_name == 'PhantomJS':
        context.browser.driver.set_window_size(1280, 1024)

def before_scenario(context, _):
    context.test_case = LiveServerTestCase
    context.test_case.setUpClass()

def after_scenario(context, _):
    context.test_case.tearDownClass()
    del context.test_case

def after_all(context):
    context.test_runner.teardown_databases(context.old_db_config)
    context.test_runner.teardown_test_environment()

    context.browser.quit()
    del context.browser

以下是来自INSTALLED_APPS的{​​{1}},以防它有用(我为此实验删除了theproject/setting.py):

'behave-django'

当我运行INSTALLED_APPS = [ 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django_extensions', 'oauth2_provider', 'push_notifications', 'raven.contrib.django.raven_compat', 'rest_framework', 'app1.apps.App1Config', 'app2', 'django.contrib.admin' # Must follow apps for apps' models to appear in admin UI ] 时,我得到了

behave

如何将这种集成django和行为的方式用于工作?

我试过的东西不起作用(或不完全):我在设置Exception AppRegistryNotReady: Apps aren't loaded yet. Traceback (most recent call last): File "/usr/local/bin/behave", line 11, in <module> sys.exit(main()) File "/usr/local/lib/python2.7/site-packages/behave/__main__.py", line 109, in main failed = runner.run() File "/usr/local/lib/python2.7/site-packages/behave/runner.py", line 672, in run return self.run_with_paths() File "/usr/local/lib/python2.7/site-packages/behave/runner.py", line 678, in run_with_paths self.load_step_definitions() File "/usr/local/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 "/usr/local/lib/python2.7/site-packages/behave/runner.py", line 304, in exec_file exec(code, globals, locals) File "features/steps/common.py", line 5, in <module> from django.contrib.auth.models import User File "/usr/local/lib/python2.7/site-packages/django/contrib/auth/models.py", line 4, in <module> from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager File "/usr/local/lib/python2.7/site-packages/django/contrib/auth/base_user.py", line 52, in <module> class AbstractBaseUser(models.Model): File "/usr/local/lib/python2.7/site-packages/django/db/models/base.py", line 105, in __new__ app_config = apps.get_containing_app_config(module) File "/usr/local/lib/python2.7/site-packages/django/apps/registry.py", line 237, in get_containing_app_config self.check_apps_ready() File "/usr/local/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. 后立即将django.setup()移至environment.py的顶层。这修复了DJANGO_SETTINGS_MODULE,但许多情况都失败了

AppRegistryNotReady

在behave-django下,一个事务在每个场景之前开始并随后回滚;这似乎并没有在现在讨厌。 IntegrityError: duplicate key value violates unique constraint "auth_user_username_key" DETAIL: Key (username)=(username) already exists. 延伸LiveServerTestCase,所以我很困惑。

4 个答案:

答案 0 :(得分:2)

您的数据库更改不会在方案之间回滚(因此box = matplotlib.text.Text.get_window_extent(ann) print box # prints Bbox(x0=268.0, y0=196.012085684, x1=315.75, y1=209.012085684) )。数据库仅在IntegrityError中被删除。尝试将所有代码移入after_all()before_scenario函数(请参阅related docs)。

测试的执行时间会增加,但测试将被隔离。而作为一个快速解决方案,这至少使他们现在通过。在评论和备选答案中提供更清洁解决方案的提示。

答案 1 :(得分:1)

您似乎误解了TransactionTestCase(和LiveServerTestCase)与交易相关的内容。它不是一个使用事务来运行测试并在最后回滚更改的测试用例(这就是Django&#34;常规&#34; TestCase所做的事情)。它是使用事务的测试用例,可以测试您自己的事务:

  

Django的TestCase类是TransactionTestCase的一个更常用的子类,它利用数据库事务工具来加速在每次测试开始时将数据库重置为已知状态的过程。然而,其结果是无法在Django TestCase类中测试某些数据库行为。例如,您无法测试事务中是否正在执行代码块,这在使用select_for_update()时是必需的。在这些情况下,您应该使用TransactionTestCase。

source

TransactionTestCase仍然通过刷新所有表,触发迁移后信号并重新安装fixture来重置数据库,但它在假设在测试用例上调用__call__的情况下运行。似乎行为是calling run() directly,因此它会跳过每次测试的数据库数据的设置/拆除。

您可以通过创建自己的子类来解决此问题,该子类在_pre_setup()_post_teardown()中调用setUp()tearDown()。唯一需要注意的是,覆盖setUp()tearDown() 的每个子类必须调用super(),或_pre_setup() / _post_teardown()赢得&#39被叫。

class BehaveLiveServerTestCase(LiveServerTestCase):
    def setUp(self):
        self._pre_setup()

    def tearDown(self):
        self._post_teardown()

答案 2 :(得分:0)

我很确定错误实际上是

  File "features/steps/common.py", line 5, in <module>

在加载应用之前尝试加载用户。尝试在step_impl内移动导入。

答案 3 :(得分:0)

这是我最终的结果。它允许我的功能在没有behave-django的behave命令下运行,因此可以在PyCharm运行配置中运行,而无需更改功能或步骤。 BehaviorDrivenTestCase中的context.test()before_scenario中的import os import django from django.contrib.staticfiles.testing import StaticLiveServerTestCase from django.core import management from django.shortcuts import resolve_url from django.test.runner import DiscoverRunner os.environ["DJANGO_SETTINGS_MODULE"] = "api.settings" django.setup() def before_all(context): context.test_runner = DiscoverRunner() context.test_runner.setup_test_environment() context.old_db_config = context.test_runner.setup_databases() def before_scenario(context, _): context.test = BehaviorDrivenTestCase() context.test.setUpClass() context.test() # this starts a transaction context.base_url = context.test.live_server_url def get_url(to=None, *args, **kwargs): return context.base_url + ( resolve_url(to, *args, **kwargs) if to else '') context.get_url = get_url class BehaviorDrivenTestCase(StaticLiveServerTestCase): """ Test case attached to the context during behave execution This test case prevents the regular tests from running. """ def runTest(*args, **kwargs): pass def after_scenario(context, _): context.test.tearDownClass() del context.test def after_all(context): context.test_runner.teardown_databases(context.old_db_config) context.test_runner.teardown_test_environment() 调用是从behave-django内部复制的。我省略了浏览器设置和拆卸以及与此问题无关的其他一些内容。

context.test()

隔离事务中的方案不适用于使用异步Javascript的UI的场景。删除management.call_command('flush', verbosity=0, interactive=False)并在before_scenario开头添加to_char()也可以正常工作,花费大约相同的时间,并且应该可以更好地使用异步Javascript。