"إذا أراد العامل أن يؤدي عمله بشكل جيد، فعليه أولاً أن يشحذ أدواته." - كونفوشيوس، "مختارات كونفوشيوس. لو لينجونج"
الصفحة الأمامية > برمجة > Pytest وPostgreSQL: قاعدة بيانات جديدة لكل اختبار

Pytest وPostgreSQL: قاعدة بيانات جديدة لكل اختبار

تم النشر بتاريخ 2024-08-21
تصفح:726

Pytest and PostgreSQL: Fresh database for every test

في Pytest، إطار عمل اختبار Python المفضل لدى الجميع، التثبيت عبارة عن قطعة من التعليمات البرمجية قابلة لإعادة الاستخدام والتي ترتب شيء ما قبل دخول الاختبار، والتنظيف بعد انتهائه. على سبيل المثال، ملف أو مجلد مؤقت، بيئة الإعدادات، بدء تشغيل خادم ويب، وما إلى ذلك. في هذا المنشور، سننظر في كيفية إنشاء أداة Pytest التي تنشئ قاعدة بيانات اختبارية (فارغة أو ذات حالة معروفة) التي تحصل على تم تنظيفها، مما يسمح بتشغيل كل اختبار على قاعدة بيانات نظيفة تمامًا.

الأهداف

سنقوم بإنشاء أداة Pytest باستخدام Psycopg 3 لإعداد قاعدة بيانات الاختبار وتنظيفها. نظرًا لأن قاعدة البيانات الفارغة نادرًا ما تكون مفيدة للاختبار، فسنقوم بشكل اختياري بتطبيق عمليات ترحيل Yoyo (في وقت كتابة موقع الويب معطلاً، انتقل إلى لقطة archive.org) لملئها.

لذا، فإن متطلبات أداة Pytest المسماة test_db التي تم إنشاؤها في منشور المدونة هذا هي:

  • إسقاط قاعدة بيانات الاختبار إذا كانت موجودة قبل الاختبار
  • إنشاء قاعدة بيانات فارغة قبل الاختبار
  • اختياريًا تطبيق عمليات الترحيل أو إنشاء بيانات اختبار قبل الاختبار
  • توفير اتصال بقاعدة بيانات الاختبار للاختبار
  • إسقاط قاعدة بيانات الاختبار بعد الاختبار (حتى في حالة الفشل)

أي طريقة اختبار تطلبها عن طريق إدراج وسيطة طريقة اختبار:

def test_create_admin_table(test_db):
    ...

سيتلقى مثيل اتصال Psycopg عاديًا متصلاً بقاعدة بيانات الاختبار. يمكن للاختبار القيام بكل ما يحتاجه كما هو الحال مع الاستخدام الشائع لـ Psycopg، على سبيل المثال:

def test_create_admin_table(test_db):
    # Open a cursor to perform database operations
    cur = test_db.cursor()

    # Pass data to fill a query placeholders and let Psycopg perform
    # the correct conversion (no SQL injections!)
    cur.execute(
        "INSERT INTO test (num, data) VALUES (%s, %s)",
        (100, "abc'def"))

    # Query the database and obtain data as Python objects.
    cur.execute("SELECT * FROM test")
    cur.fetchone()
    # will return (1, 100, "abc'def")

    # You can use `cur.fetchmany()`, `cur.fetchall()` to return a list
    # of several records, or even iterate on the cursor
    for record in cur:
        print(record)

الدوافع والبدائل
يبدو أن هناك بعض ملحقات Pytest التي تعد بتركيبات PostgreSQL للاختبارات التي تعتمد على قواعد البيانات. قد تعمل بشكل جيد بالنسبة لك.

لقد حاولت pytest-postgresql الذي يعد بنفس الشيء. لقد جربته قبل أن أكتب تركيبتي الخاصة ولكن لم أتمكن من جعله يعمل لصالحي. ربما لأن مستنداتهم كانت مربكة للغاية بالنسبة لي.

أخرى، pytest-dbt-postgres، لم أحاول على الإطلاق.


تخطيط ملف المشروع

في مشروع بايثون الكلاسيكي، توجد المصادر في src/ والاختبارات في الاختبارات/:

├── src
│   └── tuvok
│       ├── __init__.py
│       └── sales
│           └── new_user.py
├── tests
│   ├── conftest.py
│   └── sales
│       └── test_new_user.py
├── requirements.txt
└── yoyo.ini

إذا كنت تستخدم مكتبة الترحيل مثل مكتبة Yoyo الخيالية، فمن المحتمل أن تكون البرامج النصية للترحيل في عمليات الترحيل/:

├── migrations
    ├── 20240816_01_Yn3Ca-sales-user-user-add-last-run-table.py
    ├── ...

إعدادات

ستحتاج أداة اختبار قاعدة البيانات الخاصة بنا إلى القليل جدًا من التكوين:

  • عنوان URL للاتصال - (بدون قاعدة بيانات)
  • اسم قاعدة بيانات الاختبار - سيتم إعادة إنشائه لكل اختبار
  • (اختياريًا) مجلد الترحيل - نصوص الترحيل التي سيتم تطبيقها على كل اختبار

يتمتع Pytest بمكان طبيعي conftest.py لمشاركة التركيبات عبر ملفات متعددة. سوف يذهب تكوين التركيبات إلى هناك أيضًا:

# Without DB name!
TEST_DB_URL = "postgresql://localhost"
TEST_DB_NAME = "test_tuvok"
TEST_DB_MIGRATIONS_DIR = str(Path(__file__, "../../migrations").resolve())

يمكنك ضبط هذه القيم من متغير البيئة أو ما يناسب حالتك.

إنشاء تركيبات test_db

مع معرفة مكتبة PostgreSQL وPsycopg، اكتب التركيبة في conftest.py:

@pytest.fixture
def test_db():
    # autocommit=True start no transaction because CREATE/DROP DATABASE
    # cannot be executed in a transaction block.
    with psycopg.connect(TEST_DB_URL, autocommit=True) as conn:
        cur = conn.cursor()

        # create test DB, drop before
        cur.execute(f'DROP DATABASE IF EXISTS "{TEST_DB_NAME}" WITH (FORCE)')
        cur.execute(f'CREATE DATABASE "{TEST_DB_NAME}"')

        # Return (a new) connection to just created test DB
        # Unfortunately, you cannot directly change the database for an existing Psycopg connection. Once a connection is established to a specific database, it's tied to that database.
        with psycopg.connect(TEST_DB_URL, dbname=TEST_DB_NAME) as conn:
            yield conn

        cur.execute(f'DROP DATABASE IF EXISTS "{TEST_DB_NAME}" WITH (FORCE)')

إنشاء لاعبا اساسيا للهجرات

في حالتنا، نستخدم ترحيلات Yoyo. اكتب تطبيق الترحيلات كتركيبة أخرى تسمى yoyo:

@pytest.fixture
def yoyo():
    # Yoyo expect `driver://user:pass@host:port/database_name?param=value`.
    # In passed URL we need to
    url = (
        urlparse(TEST_DB_URL)
        .
        # 1) Change driver (schema part) with `postgresql psycopg` to use
        # psycopg 3 (not 2 which is `postgresql psycopg2`)
        _replace(scheme="postgresql psycopg")
        .
        # 2) Change database to test db (in which migrations will apply)
        _replace(path=TEST_DB_NAME)
        .geturl()
    )

    backend = get_backend(url)
    migrations = read_migrations(TEST_DB_MIGRATIONS_DIR)

    if len(migrations) == 0:
        raise ValueError(f"No Yoyo migrations found in '{TEST_DB_MIGRATIONS_DIR}'")

    with backend.lock():
        backend.apply_migrations(backend.to_apply(migrations))

إذا كنت تريد تطبيق عمليات الترحيل على كل قاعدة بيانات اختبارية، فاطلب تثبيت yoyo لتركيبة test_db:

@pytest.fixture
def test_db(yoyo):
    ...

لـ تطبيق الترحيل على بعض الاختبارات فقط، يلزم استخدام yoyo بشكل فردي:

def test_create_admin_table(test_db, yoyo):
    ...

خاتمة

كان إنشاء تجهيزات خاصة لتزويد اختباراتك بقاعدة بيانات نظيفة بمثابة تجربة مجزية بالنسبة لي مما سمح لي بالتعمق في كل من Pytest وPostgres.

آمل أن يكون هذا المقال قد ساعدك في مجموعة اختبار قاعدة البيانات الخاصة بك. لا تتردد في ترك سؤالك لي في التعليقات وترميز سعيد!

بيان الافراج تم إعادة إنتاج هذه المقالة على: https://dev.to/liborjelinek/pytest-and-postgresql-fresh-database-for-every-test-4eni?1 إذا كان هناك أي انتهاك، يرجى الاتصال بـ [email protected] للحذف هو - هي
أحدث البرنامج التعليمي أكثر>

تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.

Copyright© 2022 湘ICP备2022001581号-3