Python 使用peewee ORM进行代码单元测试的自定义sqlite数据库

Python 使用peewee ORM进行代码单元测试的自定义sqlite数据库,python,sqlite,peewee,Python,Sqlite,Peewee,我正在尝试使用peewee python ORM实现一个多对多场景,我想要一些单元测试。Peewee教程很棒,但它假设数据库是在模块级别定义的,然后所有模型都在使用它。我的情况不同:我没有一个源代码文件(从python的角度来看是一个模块),其中包含显式运行的测试,我使用的是从该文件收集测试并运行它们的nose 如何仅对测试中实例化的模型(由nose运行)使用自定义数据库?我的目标是只将内存中的数据库用于测试,以加快测试过程。我今天刚刚推送了一个commit,这使测试变得更容易 修复程序采用上下

我正在尝试使用peewee python ORM实现一个多对多场景,我想要一些单元测试。Peewee教程很棒,但它假设数据库是在模块级别定义的,然后所有模型都在使用它。我的情况不同:我没有一个源代码文件(从python的角度来看是一个模块),其中包含显式运行的测试,我使用的是从该文件收集测试并运行它们的nose


如何仅对测试中实例化的模型(由nose运行)使用自定义数据库?我的目标是只将内存中的数据库用于测试,以加快测试过程。

我今天刚刚推送了一个commit,这使测试变得更容易

修复程序采用上下文管理器的形式,允许您覆盖模型的数据库:

from unittest import TestCase
from playhouse.test_utils import test_database
from peewee import *

from my_app.models import User, Tweet

test_db = SqliteDatabase(':memory:')

class TestUsersTweets(TestCase):
    def create_test_data(self):
        # ... create a bunch of users and tweets
        for i in range(10):
            User.create(username='user-%d' % i)

    def test_timeline(self):
        with test_database(test_db, (User, Tweet)):
            # This data will be created in `test_db`
            self.create_test_data()

            # Perform assertions on test data inside ctx manager.
            self.assertEqual(Tweet.timeline('user-0') [...])

        # once we exit the context manager, we're back to using the normal database
请参阅并查看示例测试用例:


    • 若要在每个测试用例中不包括上下文管理器,请覆盖
      运行
      方法

      导入和数据库声明 类TestUsersTweets(TestCase): def运行(自身,结果=无): 使用test_数据库(test_db,(用户,Tweet)): super(TestUsersTweets,self).run(结果) def测试_时间表(自我): self.create_test_data() self.assertEqual(Tweet.timeline('user-0')[…]))
      我从@coleifer和@avalanchy那里得到了很好的答案,并将它们向前推进了一步

      为了避免覆盖每个
      TestCase
      子类上的run方法,您可以使用基类。。。我也喜欢这样的想法,不必写下我工作的每一个模型课,所以我想出了这个主意

      import unittest
      import inspect
      import sys
      import peewee
      from abc import ABCMeta
      from playhouse.test_utils import test_database
      from business_logic.models import *
      
      test_db = peewee.SqliteDatabase(':memory:')
      
      
      class TestCaseWithPeewee(unittest.TestCase):
          """
          This abstract class is used to "inject" the test database so that the tests don't use the real sqlite db
          """
      
          __metaclass__ = ABCMeta
      
          def run(self, result=None):
              model_classes = [m[1] for m in inspect.getmembers(sys.modules['business_logic.models'], inspect.isclass) if
                               issubclass(m[1], peewee.Model) and m[1] != peewee.Model]
              with test_database(test_db, model_classes):
                  super(TestCaseWithPeewee, self).run(result)
      

      因此,现在我可以用Peewee继承
      TestCase,在使用
      test\u数据库时,我遇到了
      test\u db
      未初始化的问题:

      nose.proxy.Exception:错误,数据库在打开连接之前未正确初始化
      
      -------------------->>开始捕获日志>结束捕获日志显然,对于所描述的场景有一种新的方法,您可以在测试用例的
      setUp()
      方法中绑定模型:

      示例来自:

      #tests.py
      导入单元测试
      从my_app.models导入事件日志、关系、推特、用户
      模型=[用户、推特、事件日志、关系]
      #使用内存中的SQLite进行测试。
      test_db=SqliteDatabase(':内存:')
      类BaseTestCase(unittest.TestCase):
      def设置(自):
      #将模型类绑定到测试数据库。因为我们有一份完整的
      #在所有模型中,我们不需要递归地绑定依赖项。
      test_db.bind(模型,bind_refs=False,bind_backrefs=False)
      测试数据库连接()
      测试数据库。创建表(模型)
      def拆卸(自):
      #由于SQLite内存中数据库仅处于活动状态,因此不完全必要
      #在连接期间,在下一步中,我们将关闭
      #这种联系……但仍然是一种良好的做法。
      测试数据库下拉表(模型)
      #关闭与数据库的连接。
      测试数据库关闭()
      #如果我们愿意,我们可以将模型重新绑定到原始模型
      #这里是数据库。但对于测试来说,这可能是不必要的。
      
      我对此也很好奇。可以通过在运行测试之前在模型上设置
      db_config
      值,然后在拆卸方法中将其设置回原处来处理此问题。我希望这也适用于Peewee。回溯表明测试数据库处于“延迟”状态。测试数据库需要用数据库名初始化。这仍然是测试的方法吗?