【问题标题】:Re-create postgresql database to do pytest重新创建 postgresql 数据库来做 pytest
【发布时间】:2021-07-21 21:55:57
【问题描述】:

我正在开发一个与这些库(以及其他)一起使用的项目

postgresql                10.5
pandas                    1.1.1
psycopg2                  2.7.5
pytest                    5.0.1
python                    3.7.1

我正在尝试在我们创建的使用 sqlalchemy 访问 postgresql 数据库的库上运行 pytest。

我想重新创建一个数据库来测试我们使用了几个月的方法。 我尝试了不同的方法,但没有成功。

我知道 postgresql 无法创建内存数据库,这就是我尝试使用 sqlite3 的原因。 .

我尝试运行测试的方法是:

DatabaseHelper.py

class DatabaseHelper(object):
    """
    Helps accessing database. 
    """

    def __init__(self):
        pass
    # ... 
        def create_engine(self, host_dns, dbname, port, user, password):
        """

        :param host_dns: dns route to the database
        :param dbname: name of the database to access to
        :param port: number or port of the database
        :param user: name of the user to access de database
        :param password: password to connect to the database
        """
        self.host = host_dns
        self.dbname = dbname
        self.port = port
        self.user = user
        self.password = password
        self.connection_str = f'postgresql://{self.user}:{self.password}@{self.host}:{self.port}/{self.dbname}'
        self.engine = create_engine(self.connection_str)
        # session_factory = sessionmaker(bind=self.engine)

        Session = sessionmaker(bind=self.engine)
        self.session = Session()
        # print("Agora objectec created ok")
    # ... 
    def read_db_to_df(self, **kwargs):  
        """ Reads a database and transforms into a pandas.DataFrame """
        try:
            default_reading_sql_args = {'con': self.session.connection()}
            reading_sql_args = utils.merge_two_dicts(default_reading_sql_args, kwargs)

            df = pd.read_sql(**reading_sql_args)
            return df
        except SQLAlchemyError as e:
            # self.logger.error("Error reading db to df")
            # self.logger.error(str(e).replace("\n", ""))
            print(e)
            return -20

MY_test_before_test.py

from sqlalchemy import MetaData, Column, Table, ForeignKey, select, PrimaryKeyConstraint, Index
from sqlalchemy import Integer, String
from sqlalchemy import create_engine
from sqlalchemy.schema import CreateTable, DropTable
from sqlalchemy.ext.declarative.api import DeclarativeMeta
from agora_db.agora_helper import AgoraHelper
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.sql.functions import current_timestamp, current_user


engine = create_engine('sqlite:///:memory:')

Session = sessionmaker(bind=engine)
session = Session()

Base = declarative_base()

#This is how the database models look like:

class Schema(object):
    """ A simple schema to provide a common argument for all tables """
    __table_args__ = {"schema": "ifsmtd"}


class AbstractTable(object):
    """
     A class that sets how the class is represents its objects as string.
    """

    def __repr__(self):
        """ Returns the object representation in string fromat in a way that can be used to reconstruct the object.

        This returns an 'official' string representation of the object.

        :Example:
        """
        from sqlalchemy.inspection import inspect
        table_inst = inspect(self)
        table_name = type(self).__name__
        column_key_value = [(c_attr.key, getattr(self, c_attr.key)) for c_attr in table_inst.mapper.column_attrs]
        fields_str = ", ".join(["%s='%s'" % (c[0], c[1]) for c in column_key_value])
        return "<" + table_name + "(" + fields_str + ")>"

class MyBasicTable(Base, Schema, AbstractTable):
    __tablename__ = "mybasic_table"

    timest_mov = Column(TIMESTAMP, primary_key=True, nullable=False, server_default=current_timestamp())
    id_info = Column(String, primary_key=True, nullable=False)
    id_wf = Column(String, primary_key=True, nullable=False)
    process_name = Column(String, primary_key=True, nullable=False)
    error_type = Column(String, primary_key=True, nullable=False)
    resolution_status = Column(Boolean)
    aud_timest_umo = Column(TIMESTAMP, server_default=current_timestamp())
    aud_id_user = Column(String, server_default=current_user())
    __table_args__ = (
        PrimaryKeyConstraint('timest_mov', 'id_info', 'id_wf', 'process_name', 'error_type', name='pk_idx_mybasic_table'),
        Index('pk_idx_mybasic_table', 'timest_mov', 'id_info', 'id_wf', 'process_name', 'error_type', unique=True),
        {"schema": "ifsmtd"}
    )



dbhelper = DatabaseHelper()
dbhelper.engine = engine
dbhelper.session = session

query = session.query(MyBasicTable.timest_mov.label("timest_mov"),
                      MyBasicTable.id_info .label("id_info "),
                                                 MyBasicTable.id_wf.label("id_wf"),
                                                 MyBasicTable.process_name.label("process_name"),
                                                 MyBasicTable.error_type.label("error_type"),
                                                 MyBasicTable.resolution_status.label("resolution_status")
                                                 )\
                .distinct(MyBasicTable.id_jira.label("id_jira"))
df = dbhelper.read_db_to_df(sql=query.statement)
print(df)

我得到的错误是:

(sqlite3.OperationalError) 没有这样的表:ifsmtd.mybasic_table

我怎么做测试。

【问题讨论】:

  • 我强烈建议反对使用一种数据库(SQLite)进行测试并在生产中使用另一种(Postgres)。这很方便,但 SQL 数据库非常古怪,您的测试将不切实际。 Postgres 是免费的,并且很容易在您的开发和测试服务器上运行。您的测试和生产应该使用相同的 SQLalchemy 代码来创建数据库和表。
  • 感谢您的推荐。如果这是我可以选择的东西,我会使用该环境进行开发,但恐怕目前不可能。
  • 一定要试试 pytest-postgresql。这有点复杂,但还不错

标签: python-3.x postgresql sqlalchemy


【解决方案1】:

查看代码,似乎缺少对 Base.metadata.create_all(engine) 的调用。这将创建初始数据库模式。在此调用之后,表为空,您需要填充它们。

在使用数据库之前添加上述语句,但在定义表之后。

Base.metadata.create_all(engine)  # This will create the schema!
dbhelper = DatabaseHelper()

关于 sqlite 的使用:我也走那条路,遇到了一个事实,即默认情况下 sqlite 不检查外键约束(它可以启用!)。可能会有更多不同!

【讨论】:

    猜你喜欢
    • 2011-08-09
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多