Files
sqlmodel/tests/test_tutorial/test_one/test_tutorial005.py
2025-06-20 13:15:47 +00:00

92 lines
3.2 KiB
Python

import importlib
import sys
import types
from typing import Any
from unittest.mock import patch
import pytest
from sqlalchemy.exc import NoResultFound # Keep this import
from sqlmodel import ( # Ensure Session and delete
Session,
create_engine,
delete,
)
from ...conftest import PrintMock, get_testing_print_function, needs_py310
expected_calls_tutorial005 = [
[
"Hero:",
{
"id": 1,
"name": "Test Hero",
"secret_name": "Secret Test Hero",
"age": 24,
},
]
]
@pytest.fixture(
name="module",
params=[
"tutorial005",
pytest.param("tutorial005_py310", marks=needs_py310),
],
)
def module_fixture(request: pytest.FixtureRequest, clear_sqlmodel: Any):
module_name = request.param
full_module_name = f"docs_src.tutorial.one.{module_name}"
if full_module_name in sys.modules:
mod = importlib.reload(sys.modules[full_module_name])
else:
mod = importlib.import_module(full_module_name)
mod.sqlite_url = "sqlite://"
mod.engine = create_engine(mod.sqlite_url)
# Table creation logic:
# tutorial005.py's main() attempts to select a hero, expecting NoResultFound.
# This implies the table should exist but be empty initially for that part of main().
# The create_db_and_tables() is called inside main() *after* the select that fails.
# So, the fixture should create tables.
if hasattr(mod, "SQLModel") and hasattr(mod.SQLModel, "metadata"):
mod.SQLModel.metadata.create_all(mod.engine) # Create tables
return mod
def test_tutorial(module: types.ModuleType, print_mock: PrintMock, clear_sqlmodel: Any):
# module.main() in tutorial005.py is structured to:
# 1. Try selecting a hero (expects NoResultFound).
# 2. Call create_db_and_tables().
# 3. Create a hero (this part is commented out in docs_src, but the test does it).
# The test then separately calls select_heroes().
# Phase 1: Test the NoResultFound part of main()
# The fixture already created tables, so main() trying to select might not fail with NoResultFound
# if create_db_and_tables() in main also populates.
# However, the original test has main() raise NoResultFound. This implies main() itself
# first tries a select on potentially empty (but existing) tables.
# The `clear_sqlmodel` fixture ensures the DB is clean (tables might be recreated by module_fixture).
with pytest.raises(NoResultFound):
module.main() # This should execute the part of main() that expects no results
# Phase 2: Test select_heroes() after manually adding a hero
# This part matches the original test's logic after the expected exception.
with Session(module.engine) as session:
session.exec(
delete(module.Hero)
) # Clear any heroes if main() somehow added them
session.add(
module.Hero(name="Test Hero", secret_name="Secret Test Hero", age=24)
)
session.commit()
with patch("builtins.print", new=get_testing_print_function(print_mock.calls)):
module.select_heroes() # This function is defined in the tutorial module
assert print_mock.calls == expected_calls_tutorial005