Pytest-django: pytest.mark.django_db tidak berfungsi dengan baik dengan setup_module()

Dibuat pada 14 Sep 2013  ·  15Komentar  ·  Sumber: pytest-dev/pytest-django

Ini kode pengujian saya:

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

Dan saya mendapatkan DatabaseError: relation "test" does not exist dari test_fetch_val() . saya juga mendapatkan

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

keluaran yang ditangkap. Sepertinya setup_module() dipanggil sebelum database dibuat.

Komentar yang paling membantu

+1 Bagi saya, hanya beralih dari beberapa pengujian unit Djano awal, ini adalah kelemahan utama, ketika menginisialisasi database untuk kasus pengujian API saya. Sebenarnya mendukung perlengkapan database sesi/modul harus menjadi fitur dasar. Ada saran bagaimana menyelesaikan ini?

Semua 15 komentar

Tanda Django_db didasarkan pada perlengkapan, saya tidak yakin bagaimana berkomunikasi antara perlengkapan dan metode setup_*.

Bisakah Anda menggunakan perlengkapan lingkup modul sebagai gantinya untuk mencapai hal yang sama? Yaitu sesuatu seperti

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

Baru saja mencoba. Tidak berhasil. Saya mendapatkan Database access not allowed, use the "django_db" mark to enable sekarang.
Juga, test_table() tidak berjalan (saya mencoba memunculkan pengecualian di sana)

Maaf, seharusnya menggunakan perlengkapan, bukan menggunakan perlengkapan:

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

Sekarang saya mendapatkan ScopeMismatchError: You tried to access the 'function' scoped funcarg 'db' with a 'module' scoped request object, involved factories .

Menghapus parameter db dari parameter mengakibatkan kegagalan perlengkapan, menghapus scope='module' make think work, tetapi kemudian test_table() dijalankan untuk setiap pengujian, yang tidak saya inginkan.

Saya juga mencoba

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

yang hampir berhasil, tetapi tes kedua gagal entah bagaimana dengan DatabaseError: relation "test" does not exist . Sebuah misteri yang lengkap bagi saya.

Django dan penanda django_db bekerja dengan cara setiap kasus uji berjalan dalam transaksinya sendiri, oleh karena itu menggunakan django_db dengan perlengkapan tingkat modul yang menyisipkan data ke dalam basis data tidak benar-benar masuk akal.

Apa kasus penggunaan Anda di sini? Mengapa Anda membuat tabel basis data "dengan tangan" dalam pengujian Anda, dan tidak dengan Django, tetapi masih ingin menggunakan basis data uji/kursor basis data uji Django?

Tidak bisakah Anda mencapai apa yang Anda cari hanya dengan membuat kursor basis data biasa?

(Contoh terakhir menghindari ScopeMismatchError, tetapi gagal dalam pengujian karena transaksi dibatalkan setelah pengujian pertama, oleh karena itu memutar kembali tabel pengujian.)

Saya mencoba menguji beberapa utilitas db tingkat rendah, yang menggunakan kursor Django secara internal - https://github.com/Suor/handy/blob/master/handy/db.py#L40

Dan saya merasa akan jauh lebih berantakan untuk mendefinisikan model dalam models.py dan kemudian memasang dalam beberapa format Django untuk mengujinya. Itu akan menjadi total 3 file untuk menguji fungsionalitas yang cukup mendasar.

Saya hanya ingin menjalankan beberapa kode inisialisasi sebelum menjalankan tes sehingga saya memiliki beberapa data untuk dimainkan.

Oh, saya membuatnya bekerja! Membungkus SQL inisialisasi menjadi begin; ... commit; membantu.

Terima kasih banyak untuk semua tips yang Anda berikan.

Itu adalah retasan yang terlihat agak rapuh bagi saya. Saya mungkin akan menyiapkan aplikasi tambahan yang hanya digunakan untuk pengujian dengan model sederhana yang kemudian dapat Anda gunakan untuk menjalankan fungsi-fungsi tersebut. Anda kemudian dapat dengan mudah menggunakan ORM Django untuk mengisi data dalam pengujian Anda. Ini sedikit lebih banyak mengetik dan beberapa file tambahan, tetapi seharusnya aman untuk kerusakan di masa mendatang.

Jika ada orang lain yang menemukan masalah ini: melakukan pengaturan basis data di setup_function/setup_class/setup_module tidak benar-benar didukung atau dimungkinkan dengan cara apa pun yang baik karena pengaturan basis data pytest-Django didasarkan pada perlengkapan.

Solusinya adalah dengan menggunakan perlengkapan yang dengan benar meminta perlengkapan db:
http://pytest-django.readthedocs.org/en/latest/helpers.html#db

@pelme
Dengan perlengkapan db dimungkinkan untuk menjalankan pengaturan seperti itu pada lingkup fungsi saja, bukan pada kelas, modul atau sesi. Misalnya jika kita perlu mengisi beberapa record ke dalam database sebelum class test dijalankan.

==================================== 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)

Apakah ada cara lain untuk menanganinya?

Ya, itu adalah batasan dari perlengkapan db seperti yang saat ini diterapkan. Di PR #258 ada beberapa pekerjaan yang memungkinkan untuk membuat status basis data yang terikat oleh ruang lingkup kelas/modul/sesi.

Meskipun masalah ini sudah cukup lama, saya merasa berguna untuk menemukan solusi untuk masalah yang saya alami dengan pytest dan pytest-django . Karena pytest 3.5.0 ada masalah saat menggunakan tanda django_db dan perlengkapan level module .

Di bawah ini berfungsi sebelum 3.5.0 (setidaknya itu tidak menyebabkan masalah apa pun).

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

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

Setelah 3.5.0 meningkat

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

Solusinya adalah menghapus scope='module' .

+1 Bagi saya, hanya beralih dari beberapa pengujian unit Djano awal, ini adalah kelemahan utama, ketika menginisialisasi database untuk kasus pengujian API saya. Sebenarnya mendukung perlengkapan database sesi/modul harus menjadi fitur dasar. Ada saran bagaimana menyelesaikan ini?

+1

Apakah halaman ini membantu?
0 / 5 - 0 peringkat