使用pytest_postgresql进行测试时,无法在测试数据库中创建表

vwhgwdsa  于 2023-06-22  发布在  PostgreSQL
关注(0)|答案(1)|浏览(218)

我正在尝试使用fixture和pytest_postgresql为Postgres中的模型和数据库编写一个pytest。
运行测试给出:

FAILED tests/test_model_with_test_db.py::test_authors - sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedTable) relation "authors" does not exist

为什么它不创建所有带有model.Base.metadata.create_all(con)的表?
我的测试代码如下:

import pytest
from pytest_postgresql import factories
from pytest_postgresql.janitor import DatabaseJanitor
from sqlalchemy import create_engine, select
from sqlalchemy.orm.session import sessionmaker

import model

test_db = factories.postgresql_proc(port=None, dbname="test_db")

@pytest.fixture(scope="session")
def db_session(test_db):
    pg_host = test_db.host
    pg_port = test_db.port
    pg_user = test_db.user
    pg_password = test_db.password
    pg_db = test_db.dbname

    with DatabaseJanitor(pg_user, pg_host, pg_port, pg_db, test_db.version, pg_password):
        connection_str = f"postgresql+psycopg2://{pg_user}:@{pg_host}:{pg_port}/{pg_db}"
        engine = create_engine(connection_str)
        with engine.connect() as con:
            model.Base.metadata.create_all(con)
            yield sessionmaker(bind=engine, expire_on_commit=False)

@pytest.fixture(scope="module")
def create_test_data():
    authors = [
        ["John", "Smith", "john@gmail.com"],
        ["Bill", "Miles", "bill@gmail.com"],
        ["Frank", "James", "frank@gmail.com"]
    ]
    return [model.Author(firstname=firstname, lastname=lastname, email=email)
            for firstname, lastname, email in authors]

def test_persons(db_session, create_test_data):
    s = db_session()
    for obj in create_test_data:
        s.add(obj)
    s.commit()

    query_result = s.execute(select(model.Author)).all()
    s.close()

    assert len(query_result) == len(create_test_data)

model.py:

from sqlalchemy import create_engine, Column, Integer, String, DateTime, Text, ForeignKey
from sqlalchemy.engine import URL
from sqlalchemy.orm import declarative_base, relationship, sessionmaker
from datetime import datetime

Base = declarative_base()

class Author(Base):
    __tablename__ = 'authors'

    id = Column(Integer(), primary_key=True)
    firstname = Column(String(100))
    lastname = Column(String(100))
    email = Column(String(255), nullable=False)
    joined = Column(DateTime(), default=datetime.now)

    articles = relationship('Article', backref='author')

class Article(Base):
    __tablename__ = 'articles'

    id = Column(Integer(), primary_key=True)
    slug = Column(String(100), nullable=False)
    title = Column(String(100), nullable=False)
    created_on = Column(DateTime(), default=datetime.now)
    updated_on = Column(DateTime(), default=datetime.now, onupdate=datetime.now)
    content = Column(Text)
    author_id = Column(Integer(), ForeignKey('authors.id'))

url = URL.create(
    drivername="postgresql",
    username="postgres",
    host="localhost",
    port=5433,
    database="andy"
)

engine = create_engine(url)
Session = sessionmaker(bind=engine)
pbgvytdp

pbgvytdp1#

我自己想出来的。修改db_session夹具如下:

@pytest.fixture(scope="session")
def db_session(test_db):
    pg_host = test_db.host
    pg_port = test_db.port
    pg_user = test_db.user
    pg_password = test_db.password
    pg_db = test_db.dbname

    with DatabaseJanitor(pg_user, pg_host, pg_port, pg_db, test_db.version, pg_password):
        connection_str = f"postgresql+psycopg2://{pg_user}:@{pg_host}:{pg_port}/{pg_db}"
        engine = create_engine(connection_str)
        model.Base.metadata.create_all(engine)
        yield sessionmaker(bind=engine, expire_on_commit=False)

测试通过。
但是为什么它不能用连接来代替呢?

相关问题