Pytest-django: contoh pengaturan

Dibuat pada 12 Apr 2013  ·  8Komentar  ·  Sumber: pytest-dev/pytest-django

saya telah mencoba menemukan contoh tentang cara menggunakan tanda perlengkapan baru dengan pytest_Django.
sesuatu seperti:

import pytest
from django.contrib.sites.models import Site
from django.contrib.auth.models import User

@pytest.fixture(scope="session", autouse=True)
@pytest.mark.django_db
def project_setup(*args, **kwargs):
    user = User.objects.create(username="session user #1")
    assert User.objects.count(), 1
    site, created = Site.objects.get_or_create(id=1)
    site.domain = "testserver"
    site.save()

untuk melakukan beberapa modifikasi db setelah tes db siap.
ini gagal dengan kesalahan "Gagal: Akses basis data tidak diizinkan, gunakan tanda "Django_db" untuk mengaktifkan"

adakah yang bisa memberikan contoh tentang cara mengatur hal-hal tambahan setelah tes db siap?

documentation sprint-idea

Komentar yang paling membantu

Ini cukup lama, tetapi saya memiliki masalah yang sama dan menemukan solusi yang berhasil untuk saya, jadi jika ada orang lain yang menemukan ini:

@pytest.fixture(autouse=True, scope='session')
def post_db_setup(_django_db_setup, _django_cursor_wrapper):
    with _django_cursor_wrapper:
        call_command('loaddata', *settings.STATIC_FIXTURES, interactive=False)

Saya menyadari perlengkapan bukanlah cara yang lebih disukai untuk melakukan sesuatu, tetapi jika Anda _benar-benar_ perlu mengisi DB Anda dengan beberapa nilai sebelum salah satu tes dijalankan... dan hanya sekali, maka itu bekerja dengan cukup baik. Itu memastikan _django_db_setup telah selesai dan Anda mendapatkan _django_cursor_wrapper untuk menulisnya (saya menduga setiap pembuatan model akan berfungsi dalam konteks itu, tetapi belum mencobanya).

Semua 8 komentar

Ini jelas perlu didokumentasikan dengan lebih baik dengan contoh, saya akan mencoba meningkatkan dokumen.

Sementara itu, saya harap ini dapat membantu Anda:
1) Perlengkapan yang berhubungan dengan modifikasi basis data harus menggunakan cakupan default 'fungsi' - basis data akan diatur ulang setelah setiap pengujian.

2) Anda dapat meminta perlengkapan db untuk perlengkapan Anda sendiri. Secara praktis ini berarti:

@pytest.fixture(autouse=True)
def project_setup(db):  # the db argument will make sure the database access is requested for this fixture
    User.objects.create(username="foo")

Anda mungkin memikirkan sesuatu yang spesifik, tetapi saya hanya ingin memberi Anda peringatan: Saya biasanya menyarankan agar tidak secara otomatis meminta akses basis data untuk _semua_ pengujian Anda. Anda tidak akan dapat mengubah ini nanti! Anda tidak akan bisa menulis tes unit yang tidak menggunakan database. Tes Anda akan lambat! Pengaturan pengujian global seperti ini juga cenderung berkembang dari waktu ke waktu - hal ini memperlambat pengujian dan menjadi sangat sulit untuk dipertahankan dalam jangka panjang.

(Saya sangat menderita karena ini dalam proyek saya saat ini, saya memiliki banyak tes "warisan" yang menggunakan pengaturan global, yang sangat lambat dan selalu rusak.)

Saya hanya memberi tahu Anda apa yang harus _tidak_ lakukan. Inilah yang dapat Anda lakukan sebagai gantinya. :-) Solusinya adalah menggunakan factory boy untuk membantu membuat objek untuk pengujian. Itu memudahkan untuk mendapatkan objek yang Anda butuhkan untuk pengujian tertentu, tanpa harus menggunakan pengaturan global. Ini membantu membuat pengaturan pengujian yang rumit menjadi eksplisit, mudah dan pada saat yang sama menghindari perlengkapan global.

Semoga ini membantu!

apakah ini cara terbaik untuk menguji proyek/aplikasi Django dengan pengaturan yang berbeda?

import pytest
from django.conf import settings

@pytest.fixture
def basic_settings():
    settings... # change something in settings

@pytest.fixture
def other_settings():
    settings... # change something in settings

def test_basic(basic_settings):
    pass

def test_other(other_settings):
    pass

Ada perlengkapan pengaturan yang dapat digunakan untuk mengembalikan pengaturan secara otomatis:

@pytest.fixture
def basic_settings(settings):
    settings.SOME_SETTING = 1234
    # SOME_SETTING will be automatically restored

Ini hanya berfungsi untuk pengaturan _some_. Pengaturan tertentu memiliki efek samping yang benar-benar tidak dapat dibatalkan karena cara mereka digunakan di dalam Django dan aplikasi lainnya. Contohnya adalah INSTALLED_APPS - setelah aplikasi dimuat, sebenarnya tidak ada cara untuk mengubahnya.

Jadi tergantung pada pengaturan apa yang ingin Anda ubah - ini mungkin atau mungkin tidak berfungsi, tetapi begitulah cara kerja Django.

Sayangnya perlengkapan pengaturan belum didokumentasikan, saya telah membuka #36 untuk tidak melupakannya.

jika itu ada di dokumen, itu akan menyelamatkan orang-orang selama berjam-jam sampai mereka menemukan masalah ini di sini. :)

@pytest.fixture(autouse=True)  # only works with function scope (default)
def project_setup(db):  # the db argument will make sure the database access is requested for this fixture
    User.objects.create(username="foo")

@ThomasWaldmann

Akan sangat bagus untuk memiliki contoh itu dalam dokumentasi.

Mungkin harus ada halaman dalam dokumentasi dengan contoh/pola umum? Saya pikir contoh seperti ini akan cocok.

Permintaan tarik yang menambahkan contoh ini ke dokumen akan sangat bagus!

Ini cukup lama, tetapi saya memiliki masalah yang sama dan menemukan solusi yang berhasil untuk saya, jadi jika ada orang lain yang menemukan ini:

@pytest.fixture(autouse=True, scope='session')
def post_db_setup(_django_db_setup, _django_cursor_wrapper):
    with _django_cursor_wrapper:
        call_command('loaddata', *settings.STATIC_FIXTURES, interactive=False)

Saya menyadari perlengkapan bukanlah cara yang lebih disukai untuk melakukan sesuatu, tetapi jika Anda _benar-benar_ perlu mengisi DB Anda dengan beberapa nilai sebelum salah satu tes dijalankan... dan hanya sekali, maka itu bekerja dengan cukup baik. Itu memastikan _django_db_setup telah selesai dan Anda mendapatkan _django_cursor_wrapper untuk menulisnya (saya menduga setiap pembuatan model akan berfungsi dalam konteks itu, tetapi belum mencobanya).

Punya masalah yang sama persis, agak frustasi. Akan sangat bagus jika ini didokumentasikan, ini benar-benar pola umum untuk mengisi DB sebelum menjalankan tes, dan kemudian membersihkan file, lampiran, log, dll. :)

Solusi yang diperbarui saat ini untuk pytest==3.0.7 pytest-Django==3.1.2

@pytest.fixture(scope='session')
def populate_nodes(request, django_db_setup, django_db_blocker):
    from project.app.models import Attachment
    call_command('populate', verbosity=0, interactive=False)

    files = list(Attachment.objects.all().values_list('file', flat=True))
    django_db_blocker.unblock()

    # Cleanup
    def teardown():
        for file_path in files:
            path, ext = os.path.splitext(file_path)
            for path in glob.glob(f'{path}*'):
                os.unlink(path)

        django_db_blocker.restore()

    request.addfinalizer(teardown)
    return request

@mariocesar Apakah Anda melihat contoh ini di dokumen?

https://pytest-django.readthedocs.io/en/latest/database.html#populate -the-database-with-initial-test-data

Saya menutup masalah untuk saat ini (seharusnya ditutup ketika contoh itu ditambahkan). Silakan buka kembali dengan detail tambahan atau buka masalah lain jika ini perlu diklarifikasi atau ditingkatkan lebih lanjut!

Apakah halaman ini membantu?
0 / 5 - 0 peringkat