6

私はフラスコ テクノロジ スタックを学習しようとしています。私のアプリケーションでは、Flask-SQLAlchemy を使用しています。すべてが完璧に機能しますが、統合テストの作成に苦労しています。実稼働環境では PostgreSQL を使用しているため、SQLite を使用したくありません。実際には、大量のモックを配置すると、ロジック自体ではなく、独自の実装がよりテストされます。

そのため、いくつかの調査の後、テストデータベースにデータを書き込むテストを実装し、各テストの後に変更をロールバックすることにしました (パフォーマンスのために)。実際、私はこのアプローチに似たものを実装しようとしています: http://sontek.net/blog/detail/writing-tests-for-pyramid-and-sqlalchemy

私の問題は、正しいトランザクションを作成し、それをロールバックできることです。これが私の基本クラスのコードです:

from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class MyAppIntegrationTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
    app.config['TESTING'] = True
    app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2:///db_test'
    init_app()
    db.app = app
    db.create_all(app=app)

    @classmethod
    def tearDownClass(cls):
        db.drop_all(app=app)

    def setUp(self):
        db.session.rollback()
        self.trans = db.session.begin(subtransactions=True)

    def tearDown(self):
        self.trans.rollback()

テストを実行しようとすると、次のエラーが発生しました。

Traceback (most recent call last):
 File "myapp/src/core/tests/__init__.py", line 53, in tearDown
   self.trans.rollback()
 File "myapp/venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 370, in rollback
   self._assert_active(prepared_ok=True, rollback_ok=True)
 File "myapp/venv/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 203, in _assert_active
   raise sa_exc.ResourceClosedError(closed_msg)
ResourceClosedError: This transaction is closed

これは scoped_session の問題であり、テストを実行しているときにすべてのテストで 1 つのグローバル セッションを再利用すると思いますが、SQLAlchemy に関する私の知識はまだ十分ではありません。

どんな助けでも大歓迎です!ありがとう!

4

3 に答える 3

0

これを設定する方法についてブログ投稿を書きました...要するに、ネストされたトランザクションを作成して、アプリケーション内の session.commit() 呼び出しが分離を壊さないようにする必要があります。次に、リスナーを内部トランザクションに適用して、誰かがコミットまたはロールバックしようとするたびに再起動します。 Flask-Sqlalchemy トランザクション テスト ケースのセットアップ

于 2016-08-26T02:31:46.717 に答える
0

あなたの質問に対する可能な解決策:

データベースのデータサイズがそれほど大きくなく、データを変更せずに保持したい場合は、セットアップでバックアップを行うことができます (まっすぐな SQL 文を書くことによって)。

"CREATE TABLE {0}_backup SELECT * FROM {0}".format(table_name)

ティアダウンで回復する

"DROP TABLE {0}".format(table_name)
"RENAME TABLE {0}_backup TO {0}".format(table_name)
于 2016-08-26T03:44:22.267 に答える
0

問題を引き起こしているのは、tearDownClass と setUpClass です。

setUpClass はすべてのテストの前に 1 回呼び出され、tearDownClass はクラス内のすべてのテストの後に呼び出されます。

したがって、3つのテストがある場合。

setUpClass が呼び出されます

セットアップが呼び出されます

teaDown が呼び出されます (ロールバックしますが、セッションを開始しないと、エラーがスローされます)

setUp が呼び出されます (エラーになる別のロールバック)

等...

teaDown に db.session.begin を追加すれば問題ありません。

from flask.ext.sqlalchemy import SQLAlchemy
db = SQLAlchemy()

class MyAppIntegrationTestCase(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        app.config['TESTING'] = True
        app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2:///db_test'
        init_app()
        db.app = app
        db.create_all(app=app)

    @classmethod
    def tearDownClass(cls):
        db.drop_all(app=app)

    def setUp(self):
        db.session.rollback()
        self.trans = db.session.begin(subtransactions=True)

    def tearDown(self):
        self.trans.rollback()
        db.session.begin()
于 2015-07-23T03:34:42.240 に答える