Set up testing with pytest and co
This commit is contained in:
83
tests/conftest.py
Normal file
83
tests/conftest.py
Normal file
@@ -0,0 +1,83 @@
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
import sqlparse
|
||||
from sqlalchemy import create_engine, event
|
||||
from sqlalchemy.exc import OperationalError
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from dibbler.models import Base
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--debug-sql",
|
||||
action="store_true",
|
||||
help="Enable SQLAlchemy 'echo' mode for debugging",
|
||||
)
|
||||
|
||||
|
||||
class SqlParseFormatter(logging.Formatter):
|
||||
def format(self, record):
|
||||
recordMessage = record.getMessage()
|
||||
if not recordMessage.startswith("[") and any(
|
||||
recordMessage.startswith(keyword)
|
||||
for keyword in [
|
||||
"SELECT",
|
||||
"INSERT",
|
||||
"UPDATE",
|
||||
"DELETE",
|
||||
"WITH",
|
||||
]
|
||||
):
|
||||
formatted_sql = sqlparse.format(recordMessage, reindent=True, keyword_case="upper")
|
||||
record.msg = "\n" + formatted_sql
|
||||
|
||||
return super().format(record)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
"""Setup pretty SQL logging if --debug-sql is enabled."""
|
||||
|
||||
logger = logging.getLogger("sqlalchemy.engine")
|
||||
|
||||
# TODO: it would be nice not to duplicate these logs.
|
||||
# logging.NullHandler() does not seem to work here
|
||||
handler = logging.StreamHandler()
|
||||
handler.setFormatter(SqlParseFormatter())
|
||||
logger.addHandler(handler)
|
||||
|
||||
if config.getoption("--debug-sql"):
|
||||
logger.setLevel(logging.INFO)
|
||||
|
||||
|
||||
@pytest.fixture(scope="function")
|
||||
def sql_session(request):
|
||||
"""Create a new SQLAlchemy session for testing."""
|
||||
|
||||
engine = create_engine("sqlite:///:memory:")
|
||||
|
||||
@event.listens_for(engine, "connect")
|
||||
def set_sqlite_pragma(dbapi_connection, _connection_record):
|
||||
cursor = dbapi_connection.cursor()
|
||||
cursor.execute("PRAGMA foreign_keys=ON")
|
||||
cursor.close()
|
||||
|
||||
Base.metadata.create_all(engine)
|
||||
with Session(engine) as sql_session:
|
||||
yield sql_session
|
||||
sql_session.close()
|
||||
|
||||
|
||||
# FIXME: Declaring this hook seems to have a side effect where the database does not
|
||||
# get reset between tests.
|
||||
# @pytest.hookimpl(trylast=True)
|
||||
# def pytest_runtest_call(item: pytest.Item):
|
||||
# """Hook to format SQL statements in OperationalError exceptions."""
|
||||
# try:
|
||||
# item.runtest()
|
||||
# except OperationalError as e:
|
||||
# if e.statement is not None:
|
||||
# formatted_sql = sqlparse.format(e.statement, reindent=True, keyword_case="upper")
|
||||
# e.statement = "\n" + formatted_sql + "\n"
|
||||
# raise e
|
||||
Reference in New Issue
Block a user