10

peewee python ORM を使用して多対多のシナリオを実装しようとしていますが、単体テストが必要です。Peewee チュートリアルは素晴らしいですが、データベースがモジュール レベルで定義され、すべてのモデルがそれを使用していることを前提としています。私の状況は異なります: 明示的に実行するテストを含むソース コード ファイル (Python の観点からのモジュール) がありません。そのファイルからテストを収集して実行するノーズを使用しています。

テストでインスタンス化されたモデル (ノーズによって実行されている) にのみカスタム データベースを使用するにはどうすればよいですか? 私の目標は、テスト プロセスを高速化するために、テスト専用のメモリ内データベースを使用することです。

4

6 に答える 6

13

今日、これを簡単にするコミットをプッシュしました。

修正は、モデルのデータベースをオーバーライドできるようにするコンテキスト マネージャーの形式です。

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

ドキュメントを参照し、テストケースの例を見てください。

于 2013-04-14T16:25:34.307 に答える
5

@coleifer と @avalanchy から素晴らしい回答を得て、さらに一歩進めました。

すべてのサブクラスで run メソッドをオーバーライドしないようにするために、基本クラスを使用できます...また、使用するすべてのTestCaseモデル クラスを書き留める必要がないというアイデアも気に入っているので、これを思いつきました

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で、テスト以外のことを心配する必要はありません

于 2014-09-17T15:37:51.360 に答える