mirror of
https://github.com/fastapi/sqlmodel.git
synced 2025-08-17 20:01:41 +08:00
85 lines
3.1 KiB
Python
85 lines
3.1 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 create_engine, SQLModel, Session, delete # Ensure Session and delete
|
|
|
|
from ...conftest import get_testing_print_function, needs_py310, PrintMock
|
|
|
|
|
|
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
|