使用peeweeorm为代码的单元测试定制sqlite数据库

2024-10-01 15:28:59 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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


Tags: 模块文件实例模型数据库定义源代码场景
3条回答

我从@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)

所以,现在我可以从TestCaseWithPeewee继承,而不必担心除了测试之外的任何事情

我今天刚做了一个承诺,让事情变得简单。在

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

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

请参阅documentation并查看示例测试用例:

为了不在每个测试用例中都包含上下文管理器,请重写run方法。在

# imports and db declaration

class TestUsersTweets(TestCase):
    def run(self, result=None):
        with test_database(test_db, (User, Tweet)):
            super(TestUsersTweets, self).run(result)

    def test_timeline(self):
        self.create_test_data()
        self.assertEqual(Tweet.timeline('user-0') [...])

相关问题 更多 >

    热门问题