في 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-dbt-postgres، لم أحاول على الإطلاق.الدوافع والبدائل
يبدو أن هناك بعض ملحقات Pytest التي تعد بتركيبات PostgreSQL للاختبارات التي تعتمد على قواعد البيانات. قد تعمل بشكل جيد بالنسبة لك.
في مشروع بايثون الكلاسيكي، توجد المصادر في 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 ├── ...
ستحتاج أداة اختبار قاعدة البيانات الخاصة بنا إلى القليل جدًا من التكوين:
يتمتع 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())
يمكنك ضبط هذه القيم من متغير البيئة أو ما يناسب حالتك.
مع معرفة مكتبة 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.
آمل أن يكون هذا المقال قد ساعدك في مجموعة اختبار قاعدة البيانات الخاصة بك. لا تتردد في ترك سؤالك لي في التعليقات وترميز سعيد!
تنصل: جميع الموارد المقدمة هي جزئيًا من الإنترنت. إذا كان هناك أي انتهاك لحقوق الطبع والنشر الخاصة بك أو الحقوق والمصالح الأخرى، فيرجى توضيح الأسباب التفصيلية وتقديم دليل على حقوق الطبع والنشر أو الحقوق والمصالح ثم إرسالها إلى البريد الإلكتروني: [email protected]. سوف نتعامل مع الأمر لك في أقرب وقت ممكن.
Copyright© 2022 湘ICP备2022001581号-3