简体   繁体   English

如何使用自定义SQL视图扩展Django的测试数据库?

[英]How to extend Django's test database with custom SQL view?

I'm using Django 2.1 with MySQL. 我正在将Django 2.1与MySQL配合使用。 I have one custom SQL view, which is bound with a model with Meta managed = False . 我有一个自定义SQL视图,该视图绑定到带有Meta managed = False的模型。 Django's TestCase has no idea how the view is created, so I'd like to provide SQL command to create this view. Django的TestCase不知道如何创建视图,因此我想提供SQL命令来创建该视图。 The best option would be to do this on database create, but I have no idea how to do that. 最好的选择是在创建数据库时执行此操作,但是我不知道如何执行此操作。

What I've done so far was to override TestCase 's setUp method. 到目前为止,我所做的是重写TestCasesetUp方法。 It looks like that: 看起来像这样:

class TaskDoneViewTest(TestCase):

    def setUp(self):
        """
        Create custom SQL view
        """
        cursor = connection.cursor()
        file_handle = open('app/tests/create_sql_view.sql', 'r+')
        sql_file = File(file_handle)
        sql = sql_file.read()
        cursor.execute(sql)
        cursor.close()

    def test_repeatable_task_done(self):
        # ...

    def test_one_time_task_done(self):
        # ...

I've got this solution from similar SO post: How to use database view in test cases . 我从类似的SO帖子中得到了该解决方案: 如何在测试用例中使用数据库视图 It would be a nice temporary solution, but the problem is with all those 2 test cases active I'm getting following error: 这将是一个不错的临时解决方案,但问题在于所有这两个测试用例都处于活动状态,我得到以下错误:

$ python manage.py test app.tests
Creating test database for alias 'default'...
System check identified no issues (0 silenced).
...E..
======================================================================
ERROR: test_repeatable_task_done (app.tests.test_views.TaskDoneViewTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/asmox/AppDev/Python/bubblechecklist/project_root/app/tests/test_views.py", line 80, in setUp
    cursor.execute(sql)
  File "/home/asmox/AppDev/Python/bubblechecklist/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/home/asmox/AppDev/Python/bubblechecklist/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/asmox/AppDev/Python/bubblechecklist/env/lib/python3.6/site-packages/django/db/backends/utils.py", line 80, in _execute
    self.db.validate_no_broken_transaction()
  File "/home/asmox/AppDev/Python/bubblechecklist/env/lib/python3.6/site-packages/django/db/backends/base/base.py", line 437, in validate_no_broken_transaction
    "An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.

For some reason this error doesn't happen when I have only one test case active (why?).This error remains until I change my test's base class from TestCase to TransactionTestCase . 由于某种原因,当我只有一个测试用例处于活动状态时,不会发生此错误(为什么?)。直到将测试的基类从TestCase更改为TransactionTestCase为止,该错误一直存在。

Well, I would ask why this happen and if there is any solution to get it okay with simple TestCase class, because my test for now has nothing to do with transactions and I find this working solutions a bit too dirty, but... 好吧,我想问为什么会发生这种情况,以及是否有任何解决方案可以通过简单的TestCase类使之TestCase ,因为目前我的测试与事务无关,我发现这种有效的解决方案有点脏,但是...

I would more likely stick to the main issue, that is, to globally (for all my test cases) do the following thing: 我将更可能坚持主要问题,即在全局范围内(对于我所有的测试用例)执行以下操作:

When testing database is created, do one more custom SQL from provided file. 创建测试数据库后,请从提供的文件中再执行一个自定义SQL。 It is going to create required view 这将创建所需的视图

Can you please help me how to do that? 你能帮我怎么做吗?

If you read the documentation for TestCase , you'll see that it wraps each test in a double transaction, one at the class level and one at the test level. 如果阅读TestCase文档 ,您会发现它将每个测试包装在一个双重事务中,一个在类级别,一个在测试级别。 The setUp() method runs for each test and is thus inside this double wrapping. setUp()方法针对每个测试运行,因此位于此双重包装内。

As shown in the above mentioned docs, it is suggested you use setUpTestData() to set up your db at the class level. 如上述文档所示,建议您使用setUpTestData()在类级别上设置数据库。 This is also where you'd add initial data to your db for all your tests to use. 您也可以在此处向数据库添加初始数据以供所有测试使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM