Pytest-django: pytest.mark.django_dbはsetup_module()ではうまく機能しません

作成日 2013年09月14日  ·  15コメント  ·  ソース: pytest-dev/pytest-django

これが私のテストコードです:

import pytest
pytestmark = pytest.mark.django_db

from handy.db import do_sql, fetch_val

def setup_module(fetch_val):
    print 1
    do_sql('''
        create table test (
            id int primary key,
            tag int not null
        );

        insert into test values (1, 10), (2, 20);
    ''')
    print 2

def test_fetch_val():
    print 3
    assert fetch_val('select min(id) from test') == 1

そして、 test_fetch_val()からDatabaseError: relation "test" does not existを取得します。 私も得る

2
Creating test database for alias 'default'...
3

キャプチャされた出力。 データベースが作成される前にsetup_module()が呼び出されたようです。

最も参考になるコメント

+1私にとって、いくつかの初期のDjano単体テストから切り替えるだけで、これは、APIテストケース用にデータベースを初期化する際の大きな欠点です。 実際にセッション/モジュールデータベースフィクスチャをサポートすることは基本的な機能であるはずです。 これを解決する方法の提案はありますか?

全てのコメント15件

django_dbマークはフィクスチャに基づいているため、フィクスチャとsetup_ *メソッドの間で通信する方法がわかりません。

同じことを実現するために、代わりにモジュールスコープのフィクスチャを使用できますか? つまり、

pytestmark = pytest.mark.usefixture('test_table')

@pytest.fixture(scope='module')
def test_table(db):
    do_sql('create table ...')

def test_fetch_val():
    assert fetch_val('...') == 1

試してみました。 動作しませんでした。 私は今Database access not allowed, use the "django_db" mark to enableを手に入れました。
また、 test_table()が実行されません(そこで例外を発生させようとしました)

申し訳ありませんが、usefixtureではなくusefixturesである必要があります。

http://pytest.org/latest/fixture.html#usefixtures

今、私はScopeMismatchError: You tried to access the 'function' scoped funcarg 'db' with a 'module' scoped request object, involved factoriesを取得します。

パラメータからdbパラメータを削除すると、フィクスチャが失敗し、scope = 'module' make thinksが機能するようになりますが、すべてのテストでtest_table()が実行されます。

私も試しました

pytestmark = pytest.mark.django_db

@pytest.fixture(scope='module')
def test_table():
    do_sql('''
        create table test (
            id int primary key,
            tag int not null
        );

        insert into test values (1, 10), (2, 20);
    ''')

def test_fetch_val(test_table):
    assert fetch_val('select min(id) from test') == 1

def test_fetch_val2(test_table):
    assert fetch_val('select min(id) from test') == 1

これはほぼ機能しますが、2番目のテストはDatabaseError: relation "test" does not exist何らかの理由で失敗します。 私には完全な謎。

Djangoとdjango_dbマーカーは、各テストケースが独自のトランザクションで実行されるように機能するため、データベースにデータを挿入するモジュールレベルのフィクスチャでdjango_dbを使用することは実際には意味がありません。

ここでのユースケースは何ですか? Djangoを使用せずに、テストで「手動」でデータベーステーブルを作成しているのに、Djangoのテストデータベース/テストデータベースカーソルを使用したいのはなぜですか?

プレーンなデータベースカーソルを作成するだけでは、目的を達成できませんでしたか?

(最後の例ではScopeMismatchErrorを回避していますが、トランザクションが最初のテストの後にロールバックされ、テストテーブルがロールバックされるため、代わりにテストで失敗します。)

内部でdjangoカーソルを使用するいくつかの低レベルのdbユーティリティをテストしようとしています-https ://github.com/Suor/handy/blob/master/handy/db.py#L40

そして、 models.pyモデルを定義し、それをテストするためにdjango形式でフィクスチャを定義するのははるかに面倒だと思います。 かなり基本的な機能をテストするには、合計3つのファイルになります。

テストを実行する前に初期化コードを実行して、試してみるデータを用意したいだけです。

ああ、私はそれを機能させました! 初期化SQLをbegin; ... commit;ラップすることは役に立ちました。

あなたが提供したすべてのヒントに感謝します。

それは私には少し壊れやすいように見えるハックです。 おそらく、これらの関数を実行するために使用できる単純なモデルを使用したテストにのみ使用される追加のアプリをセットアップします。 その後、DjangoのORMを使用して、テストのデータを簡単に入力できます。 タイピングが少し増え、ファイルがいくつか追加されますが、将来の破損に備えて安全なはずです。

他の誰かがこの問題を見つけた場合:pytest-djangoのデータベース設定はフィクスチャに基づいているため、setup_function / setup_class / setup_moduleでデータベース設定を行うことは実際にはサポートされていないか、適切な方法で可能ではありません。

解決策は、dbフィクスチャを適切に要求するフィクスチャを使用することです。
http://pytest-django.readthedocs.org/en/latest/helpers.html#db

@pelme
dbフィクスチャを使用すると、クラス、モジュール、またはセッションではなく、関数スコープでのみこのようなセットアップを実行できます。 たとえば、クラステストを実行する前に、データベースにいくつかのレコードを入力する必要がある場合です。

==================================== ERRORS ====================================
___________ ERROR at setup of TestHistoryAlerts.test_one_point_data ____________
ScopeMismatch: You tried to access the 'function' scoped fixture 'db' with a 'session' scoped request object, involved factories
tests/conftest.py:140:  def ts(db)
../../../../.virtualenvs/app/lib/python2.7/site-packages/pytest_django/fixtures.py:158:  def db(request, _django_db_setup, _django_cursor_wrapper)

それを処理する他の方法はありますか?

はい、それは現在実装されているdbフィクスチャの制限です。 PR#258では、クラス/モジュール/セッションスコープによってバインドされたデータベース状態を作成できるようにするためのいくつかの作業がありました。

この問題はかなり古いものですが、 pytestpytest-django発生していた問題の解決策を見つけることが役立つことがわかりました。 pytest 3.5.0以降、 django_dbマークとmoduleレベルのフィクスチャを使用すると問題が発生します。

以下は3.5.0前に機能していました(少なくとも問題は発生していませんでした)。

@pytest.fixture(scope='module')
def user():
    return User.objects.create(...)

@pytest.mark.django_db
def test_some_case(user):
    pass

3.5.0それは発生します

Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.

解決策は、 scope='module'を削除すること

+1私にとって、いくつかの初期のDjano単体テストから切り替えるだけで、これは、APIテストケース用にデータベースを初期化する際の大きな欠点です。 実際にセッション/モジュールデータベースフィクスチャをサポートすることは基本的な機能であるはずです。 これを解決する方法の提案はありますか?

+1

このページは役に立ちましたか?
0 / 5 - 0 評価