From d57549fb64378433a597a401b963d7aeac997f1e Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 12:56:23 +0100 Subject: [PATCH 01/79] Simplify tests for `docs_src.tutorial.code_structure.tutorial002*` --- .../test_code_structure/test_tutorial002.py | 47 ++++++++++++++----- .../test_tutorial002_py310.py | 38 --------------- .../test_tutorial002_py39.py | 38 --------------- 3 files changed, 34 insertions(+), 89 deletions(-) delete mode 100644 tests/test_tutorial/test_code_structure/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_code_structure/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_code_structure/test_tutorial002.py b/tests/test_tutorial/test_code_structure/test_tutorial002.py index ccbb849097..f1d4043e85 100644 --- a/tests/test_tutorial/test_code_structure/test_tutorial002.py +++ b/tests/test_tutorial/test_code_structure/test_tutorial002.py @@ -1,8 +1,11 @@ -from unittest.mock import patch +import importlib +from dataclasses import dataclass +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py39, needs_py310 expected_calls = [ [ @@ -22,16 +25,34 @@ ] -def test_tutorial(): - from docs_src.tutorial.code_structure.tutorial002 import app, database +@dataclass +class Modules: + app: ModuleType + database: ModuleType - database.sqlite_url = "sqlite://" - database.engine = create_engine(database.sqlite_url) - app.engine = database.engine - calls = [] - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - app.main() - assert calls == expected_calls +@pytest.fixture( + name="modules", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_modules(request: pytest.FixtureRequest) -> Modules: + app_module = importlib.import_module( + f"docs_src.tutorial.code_structure.{request.param}.app" + ) + database_module = importlib.import_module( + f"docs_src.tutorial.code_structure.{request.param}.database" + ) + database_module.sqlite_url = "sqlite://" + database_module.engine = create_engine(database_module.sqlite_url) + app_module.engine = database_module.engine + + return Modules(app=app_module, database=database_module) + + +def test_tutorial(print_mock: PrintMock, modules: Modules): + modules.app.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_code_structure/test_tutorial002_py310.py b/tests/test_tutorial/test_code_structure/test_tutorial002_py310.py deleted file mode 100644 index be28486652..0000000000 --- a/tests/test_tutorial/test_code_structure/test_tutorial002_py310.py +++ /dev/null @@ -1,38 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "id": 1, - "name": "Deadpond", - "age": None, - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Hero's team:", - {"name": "Z-Force", "headquarters": "Sister Margaret's Bar", "id": 1}, - ], -] - - -@needs_py310 -def test_tutorial(): - from docs_src.tutorial.code_structure.tutorial002_py310 import app, database - - database.sqlite_url = "sqlite://" - database.engine = create_engine(database.sqlite_url) - app.engine = database.engine - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - app.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_code_structure/test_tutorial002_py39.py b/tests/test_tutorial/test_code_structure/test_tutorial002_py39.py deleted file mode 100644 index 55f6a435dc..0000000000 --- a/tests/test_tutorial/test_code_structure/test_tutorial002_py39.py +++ /dev/null @@ -1,38 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "id": 1, - "name": "Deadpond", - "age": None, - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Hero's team:", - {"name": "Z-Force", "headquarters": "Sister Margaret's Bar", "id": 1}, - ], -] - - -@needs_py39 -def test_tutorial(): - from docs_src.tutorial.code_structure.tutorial002_py39 import app, database - - database.sqlite_url = "sqlite://" - database.engine = create_engine(database.sqlite_url) - app.engine = database.engine - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - app.main() - assert calls == expected_calls From e07f7d2c37a065b0d4448242dde39b86c3571acf Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 12:57:08 +0100 Subject: [PATCH 02/79] Simplify tests for `docs_src.tutorial.connect.create_tables.tutorial001*` --- .../test_tutorial001.py | 34 ++++++++++++++----- .../test_tutorial001_py310.py | 17 ---------- 2 files changed, 26 insertions(+), 25 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001.py b/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001.py index 265a05931c..49d4acfa00 100644 --- a/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001.py +++ b/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001.py @@ -1,14 +1,32 @@ +import importlib +from types import ModuleType + +import pytest from sqlalchemy import inspect from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine +from tests.conftest import needs_py310 + + +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.create_tables.{request.param}" + ) + return module -def test_tutorial001(): - from docs_src.tutorial.connect.create_tables import tutorial001 as mod - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) - assert insp.has_table(str(mod.Team.__tablename__)) +def test_tutorial001(module: ModuleType): + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + module.main() + insp: Inspector = inspect(module.engine) + assert insp.has_table(str(module.Hero.__tablename__)) + assert insp.has_table(str(module.Team.__tablename__)) diff --git a/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001_py310.py b/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001_py310.py deleted file mode 100644 index 95f15a4266..0000000000 --- a/tests/test_tutorial/test_connect/test_create_connected_tables/test_tutorial001_py310.py +++ /dev/null @@ -1,17 +0,0 @@ -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial001(): - from docs_src.tutorial.connect.create_tables import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) - assert insp.has_table(str(mod.Team.__tablename__)) From 32050152aea926cc837777096749f8b21ff6a4f1 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 13:04:18 +0100 Subject: [PATCH 03/79] Simplify tests for `docs_src.tutorial.connect.delete.tutorial001*` --- .../test_delete/test_tutorial001.py | 33 ++++++--- .../test_delete/test_tutorial001_py310.py | 73 ------------------- 2 files changed, 21 insertions(+), 85 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_delete/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_connect/test_delete/test_tutorial001.py b/tests/test_tutorial/test_connect/test_delete/test_tutorial001.py index 1a9fe293ba..cc25dd42e3 100644 --- a/tests/test_tutorial/test_connect/test_delete/test_tutorial001.py +++ b/tests/test_tutorial/test_connect/test_delete/test_tutorial001.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -58,15 +60,22 @@ ] -def test_tutorial(): - from docs_src.tutorial.connect.delete import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.delete.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_delete/test_tutorial001_py310.py b/tests/test_tutorial/test_connect/test_delete/test_tutorial001_py310.py deleted file mode 100644 index f1bef3ed02..0000000000 --- a/tests/test_tutorial/test_connect/test_delete/test_tutorial001_py310.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 1, - "name": "Spider-Boy", - }, - ], - [ - "No longer Preventer:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], -] - - -@needs_py310 -def test_tutorial(): - from docs_src.tutorial.connect.delete import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From f22df69e2a6ca68657f86d7e63ecf828d8124594 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 13:07:49 +0100 Subject: [PATCH 04/79] Simplify tests for `docs_src.tutorial.connect.insert.tutorial001*` --- .../test_insert/test_tutorial001.py | 37 ++++++++----- .../test_insert/test_tutorial001_py310.py | 53 ------------------- 2 files changed, 23 insertions(+), 67 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_insert/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_connect/test_insert/test_tutorial001.py b/tests/test_tutorial/test_connect/test_insert/test_tutorial001.py index cfc08ee854..6c4ec3ab1c 100644 --- a/tests/test_tutorial/test_connect/test_insert/test_tutorial001.py +++ b/tests/test_tutorial/test_connect/test_insert/test_tutorial001.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -38,15 +40,22 @@ ] -def test_tutorial001(): - from docs_src.tutorial.connect.insert import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.insert.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module + + +def test_tutorial001(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_insert/test_tutorial001_py310.py b/tests/test_tutorial/test_connect/test_insert/test_tutorial001_py310.py deleted file mode 100644 index 6dabc10b80..0000000000 --- a/tests/test_tutorial/test_connect/test_insert/test_tutorial001_py310.py +++ /dev/null @@ -1,53 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], -] - - -@needs_py310 -def test_tutorial001(): - from docs_src.tutorial.connect.insert import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From b9958f01a668e4177ead3ab5450b54b3dd7388ae Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:00:24 +0100 Subject: [PATCH 05/79] Simplify tests for `docs_src.tutorial.connect.select.tutorial001*` and `docs_src.tutorial.connect.select.tutorial002*` --- ...est_tutorial001_py310_tutorial002_py310.py | 92 ------------------- .../test_tutorial001_tutorial002.py | 58 +++++++----- 2 files changed, 34 insertions(+), 116 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_select/test_tutorial001_py310_tutorial002_py310.py diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial001_py310_tutorial002_py310.py b/tests/test_tutorial/test_connect/test_select/test_tutorial001_py310_tutorial002_py310.py deleted file mode 100644 index 4809d79b68..0000000000 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial001_py310_tutorial002_py310.py +++ /dev/null @@ -1,92 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - "Team:", - {"id": 2, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - ], - [ - "Hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - "Team:", - {"id": 1, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], -] - - -@needs_py310 -def test_tutorial001(): - from docs_src.tutorial.connect.select import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -@needs_py310 -def test_tutorial002(): - from docs_src.tutorial.connect.select import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_connect/test_select/test_tutorial001_tutorial002.py index c0d6b59dd9..6553bc1ae6 100644 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_connect/test_select/test_tutorial001_tutorial002.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -62,29 +64,37 @@ ] -def test_tutorial001(): - from docs_src.tutorial.connect.select import tutorial001 as mod +@pytest.fixture(name="module") +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.select.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -def test_tutorial002(): - from docs_src.tutorial.connect.select import tutorial002 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.mark.parametrize( + "module", + [ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial001(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +@pytest.mark.parametrize( + "module", + [ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial002(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls From a0e1063c7398a73872887f2c5e7d40e125c1154a Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:01:00 +0100 Subject: [PATCH 06/79] Simplify tests for `docs_src.tutorial.connect.select.tutorial003*` --- .../test_select/test_tutorial003.py | 33 ++++--- .../test_select/test_tutorial003_py310.py | 89 ------------------- 2 files changed, 21 insertions(+), 101 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_select/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial003.py b/tests/test_tutorial/test_connect/test_select/test_tutorial003.py index f309e1c44e..6036b672a3 100644 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial003.py +++ b/tests/test_tutorial/test_connect/test_select/test_tutorial003.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -74,15 +76,22 @@ ] -def test_tutorial(): - from docs_src.tutorial.connect.select import tutorial003 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.fixture( + name="module", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.select.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial003_py310.py b/tests/test_tutorial/test_connect/test_select/test_tutorial003_py310.py deleted file mode 100644 index e826ce44ae..0000000000 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial003_py310.py +++ /dev/null @@ -1,89 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - "Team:", - {"id": 2, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - ], - [ - "Hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - "Team:", - {"id": 1, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - [ - "Hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - "Team:", - None, - ], -] - - -@needs_py310 -def test_tutorial(): - from docs_src.tutorial.connect.select import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 508e80b61758a94cce66b8efa732169ea9d819a7 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:03:54 +0100 Subject: [PATCH 07/79] Simplify tests for `docs_src.tutorial.connect.select.tutorial004*` --- .../test_select/test_tutorial004.py | 33 ++++++---- .../test_select/test_tutorial004_py310.py | 63 ------------------- 2 files changed, 21 insertions(+), 75 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_select/test_tutorial004_py310.py diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial004.py b/tests/test_tutorial/test_connect/test_select/test_tutorial004.py index a33c814856..c9fa695eda 100644 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial004.py +++ b/tests/test_tutorial/test_connect/test_select/test_tutorial004.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -48,15 +50,22 @@ ] -def test_tutorial(): - from docs_src.tutorial.connect.select import tutorial004 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.fixture( + name="module", + params=[ + "tutorial004", + pytest.param("tutorial004_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.select.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial004_py310.py b/tests/test_tutorial/test_connect/test_select/test_tutorial004_py310.py deleted file mode 100644 index 33dd8a4329..0000000000 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial004_py310.py +++ /dev/null @@ -1,63 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Preventer Hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], -] - - -@needs_py310 -def test_tutorial(): - from docs_src.tutorial.connect.select import tutorial004_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 129a54ca3145748e23dd943fea31f93538720497 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:05:23 +0100 Subject: [PATCH 08/79] Simplify tests for `docs_src.tutorial.connect.select.tutorial005*` --- .../test_select/test_tutorial005.py | 33 ++++++---- .../test_select/test_tutorial005_py310.py | 65 ------------------- 2 files changed, 21 insertions(+), 77 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_select/test_tutorial005_py310.py diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial005.py b/tests/test_tutorial/test_connect/test_select/test_tutorial005.py index f7ad78dc65..12d98b7e66 100644 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial005.py +++ b/tests/test_tutorial/test_connect/test_select/test_tutorial005.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -50,15 +52,22 @@ ] -def test_tutorial(): - from docs_src.tutorial.connect.select import tutorial005 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.fixture( + name="module", + params=[ + "tutorial005", + pytest.param("tutorial005_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.select.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_select/test_tutorial005_py310.py b/tests/test_tutorial/test_connect/test_select/test_tutorial005_py310.py deleted file mode 100644 index 8cddb6455a..0000000000 --- a/tests/test_tutorial/test_connect/test_select/test_tutorial005_py310.py +++ /dev/null @@ -1,65 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Preventer Hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - "Team:", - {"id": 1, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], -] - - -@needs_py310 -def test_tutorial(): - from docs_src.tutorial.connect.select import tutorial005_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From e9e34352f88518640fea7d2648ec0d482e6c61fe Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:12:41 +0100 Subject: [PATCH 09/79] Simplify tests for `docs_src.tutorial.connect.update.tutorial001*` --- .../test_update/test_tutorial001.py | 33 ++++++---- .../test_update/test_tutorial001_py310.py | 63 ------------------- 2 files changed, 21 insertions(+), 75 deletions(-) delete mode 100644 tests/test_tutorial/test_connect/test_update/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_connect/test_update/test_tutorial001.py b/tests/test_tutorial/test_connect/test_update/test_tutorial001.py index d6875946c1..aa94c91216 100644 --- a/tests/test_tutorial/test_connect/test_update/test_tutorial001.py +++ b/tests/test_tutorial/test_connect/test_update/test_tutorial001.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -48,15 +50,22 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.connect.update import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.connect.update.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_connect/test_update/test_tutorial001_py310.py b/tests/test_tutorial/test_connect/test_update/test_tutorial001_py310.py deleted file mode 100644 index f3702654c2..0000000000 --- a/tests/test_tutorial/test_connect/test_update/test_tutorial001_py310.py +++ /dev/null @@ -1,63 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 2, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 1, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 1, - "name": "Spider-Boy", - }, - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.connect.update import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 8c8fc8bed7ecc7a1d79497eedb4a1e634cd53e9c Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:19:38 +0100 Subject: [PATCH 10/79] Simplify tests for `docs_src.tutorial.create_db_and_table.tutorial001*` --- .../test_tutorial001.py | 15 ++++++++++++--- .../test_tutorial001_py310.py | 19 ------------------- 2 files changed, 12 insertions(+), 22 deletions(-) delete mode 100644 tests/test_tutorial/test_create_db_and_table/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_create_db_and_table/test_tutorial001.py b/tests/test_tutorial/test_create_db_and_table/test_tutorial001.py index b6a2e72628..4aeeb64b6c 100644 --- a/tests/test_tutorial/test_create_db_and_table/test_tutorial001.py +++ b/tests/test_tutorial/test_create_db_and_table/test_tutorial001.py @@ -1,10 +1,19 @@ from pathlib import Path -from ...conftest import coverage_run +import pytest +from ...conftest import coverage_run, needs_py310 -def test_create_db_and_table(cov_tmp_path: Path): - module = "docs_src.tutorial.create_db_and_table.tutorial001" + +@pytest.mark.parametrize( + "module_name", + [ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def test_create_db_and_table(cov_tmp_path: Path, module_name: str): + module = f"docs_src.tutorial.create_db_and_table.{module_name}" result = coverage_run(module=module, cwd=cov_tmp_path) assert "BEGIN" in result.stdout assert 'PRAGMA main.table_info("hero")' in result.stdout diff --git a/tests/test_tutorial/test_create_db_and_table/test_tutorial001_py310.py b/tests/test_tutorial/test_create_db_and_table/test_tutorial001_py310.py deleted file mode 100644 index 465b9f9d58..0000000000 --- a/tests/test_tutorial/test_create_db_and_table/test_tutorial001_py310.py +++ /dev/null @@ -1,19 +0,0 @@ -from pathlib import Path - -from ...conftest import coverage_run, needs_py310 - - -@needs_py310 -def test_create_db_and_table(cov_tmp_path: Path): - module = "docs_src.tutorial.create_db_and_table.tutorial001_py310" - result = coverage_run(module=module, cwd=cov_tmp_path) - assert "BEGIN" in result.stdout - assert 'PRAGMA main.table_info("hero")' in result.stdout - assert "CREATE TABLE hero (" in result.stdout - assert "id INTEGER NOT NULL," in result.stdout - assert "name VARCHAR NOT NULL," in result.stdout - assert "secret_name VARCHAR NOT NULL," in result.stdout - assert "age INTEGER," in result.stdout - assert "PRIMARY KEY (id)" in result.stdout - assert ")" in result.stdout - assert "COMMIT" in result.stdout From 89d56acd0b41b3a630cbb946ea67c4773488fdc9 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:28:06 +0100 Subject: [PATCH 11/79] Simplify tests for `docs_src.tutorial.create_db_and_table.tutorial002*` --- .../test_tutorial002.py | 32 +++++++++++++++---- .../test_tutorial002_py310.py | 16 ---------- 2 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 tests/test_tutorial/test_create_db_and_table/test_tutorial002_py310.py diff --git a/tests/test_tutorial/test_create_db_and_table/test_tutorial002.py b/tests/test_tutorial/test_create_db_and_table/test_tutorial002.py index 3a24ae1609..0f1ad85fe9 100644 --- a/tests/test_tutorial/test_create_db_and_table/test_tutorial002.py +++ b/tests/test_tutorial/test_create_db_and_table/test_tutorial002.py @@ -1,13 +1,31 @@ +import importlib +from types import ModuleType + +import pytest from sqlalchemy import inspect from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine +from ...conftest import needs_py310 + + +@pytest.fixture( + name="module", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.create_db_and_table.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module -def test_create_db_and_table(clear_sqlmodel): - from docs_src.tutorial.create_db_and_table import tutorial002 as mod - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.create_db_and_tables() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) +def test_create_db_and_table(module: ModuleType): + module.create_db_and_tables() + insp: Inspector = inspect(module.engine) + assert insp.has_table(str(module.Hero.__tablename__)) diff --git a/tests/test_tutorial/test_create_db_and_table/test_tutorial002_py310.py b/tests/test_tutorial/test_create_db_and_table/test_tutorial002_py310.py deleted file mode 100644 index 3ca3186b9e..0000000000 --- a/tests/test_tutorial/test_create_db_and_table/test_tutorial002_py310.py +++ /dev/null @@ -1,16 +0,0 @@ -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ...conftest import needs_py310 - - -@needs_py310 -def test_create_db_and_table(clear_sqlmodel): - from docs_src.tutorial.create_db_and_table import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.create_db_and_tables() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) From 06716f44b5cc93d2539532a758ea7074496a74ef Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:29:51 +0100 Subject: [PATCH 12/79] Simplify tests for `docs_src.tutorial.create_db_and_table.tutorial003*` --- .../test_tutorial003.py | 32 +++++++++++++++---- .../test_tutorial003_py310.py | 16 ---------- 2 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 tests/test_tutorial/test_create_db_and_table/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_create_db_and_table/test_tutorial003.py b/tests/test_tutorial/test_create_db_and_table/test_tutorial003.py index e5c55c70f3..446feae71a 100644 --- a/tests/test_tutorial/test_create_db_and_table/test_tutorial003.py +++ b/tests/test_tutorial/test_create_db_and_table/test_tutorial003.py @@ -1,13 +1,31 @@ +import importlib +from types import ModuleType + +import pytest from sqlalchemy import inspect from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine +from ...conftest import needs_py310 + + +@pytest.fixture( + name="module", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.create_db_and_table.{request.param}" + ) + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module -def test_create_db_and_table(clear_sqlmodel): - from docs_src.tutorial.create_db_and_table import tutorial003 as mod - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.create_db_and_tables() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) +def test_create_db_and_table(module: ModuleType): + module.create_db_and_tables() + insp: Inspector = inspect(module.engine) + assert insp.has_table(str(module.Hero.__tablename__)) diff --git a/tests/test_tutorial/test_create_db_and_table/test_tutorial003_py310.py b/tests/test_tutorial/test_create_db_and_table/test_tutorial003_py310.py deleted file mode 100644 index a1806ce250..0000000000 --- a/tests/test_tutorial/test_create_db_and_table/test_tutorial003_py310.py +++ /dev/null @@ -1,16 +0,0 @@ -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ...conftest import needs_py310 - - -@needs_py310 -def test_create_db_and_table(clear_sqlmodel): - from docs_src.tutorial.create_db_and_table import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.create_db_and_tables() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) From 4c601263452994655f37d48d1284a2eecab3b0c4 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:34:26 +0100 Subject: [PATCH 13/79] Simplify tests for `docs_src.tutorial.delete.tutorial001*` and `docs_src.tutorial.delete.tutorial002*` --- ...est_tutorial001_py310_tutorial002_py310.py | 88 ------------------- .../test_tutorial001_tutorial002.py | 56 +++++++----- 2 files changed, 32 insertions(+), 112 deletions(-) delete mode 100644 tests/test_tutorial/test_delete/test_tutorial001_py310_tutorial002_py310.py diff --git a/tests/test_tutorial/test_delete/test_tutorial001_py310_tutorial002_py310.py b/tests/test_tutorial/test_delete/test_tutorial001_py310_tutorial002_py310.py deleted file mode 100644 index 0f97e7489f..0000000000 --- a/tests/test_tutorial/test_delete/test_tutorial001_py310_tutorial002_py310.py +++ /dev/null @@ -1,88 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Hero 1:", - {"id": 2, "name": "Spider-Boy", "secret_name": "Pedro Parqueador", "age": None}, - ], - [ - "Hero 2:", - { - "id": 7, - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - }, - ], - [ - "Updated hero 1:", - { - "id": 2, - "name": "Spider-Youngster", - "secret_name": "Pedro Parqueador", - "age": 16, - }, - ], - [ - "Updated hero 2:", - { - "id": 7, - "name": "Captain North America Except Canada", - "secret_name": "Esteban Rogelios", - "age": 110, - }, - ], - [ - "Hero: ", - { - "id": 2, - "name": "Spider-Youngster", - "secret_name": "Pedro Parqueador", - "age": 16, - }, - ], - [ - "Deleted hero:", - { - "id": 2, - "name": "Spider-Youngster", - "secret_name": "Pedro Parqueador", - "age": 16, - }, - ], - ["There's no hero named Spider-Youngster"], -] - - -@needs_py310 -def test_tutorial001(clear_sqlmodel): - from docs_src.tutorial.delete import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -@needs_py310 -def test_tutorial002(clear_sqlmodel): - from docs_src.tutorial.delete import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_delete/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_delete/test_tutorial001_tutorial002.py index 1d6497b327..3d755ae027 100644 --- a/tests/test_tutorial/test_delete/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_delete/test_tutorial001_tutorial002.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -58,29 +60,35 @@ ] -def test_tutorial001(clear_sqlmodel): - from docs_src.tutorial.delete import tutorial001 as mod +@pytest.fixture(name="module") +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module(f"docs_src.tutorial.delete.{request.param}") + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -def test_tutorial002(clear_sqlmodel): - from docs_src.tutorial.delete import tutorial002 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.mark.parametrize( + "module", + [ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial001(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +@pytest.mark.parametrize( + "module", + [ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial002(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls From 8f7c3cbe02b92ccb5c0f77d736b0fe69072c8ed3 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 14:53:58 +0100 Subject: [PATCH 14/79] Simplify tests for `docs_src.tutorial.fastapi.app_testing.tutorial001*.tests_main` --- .../test_tutorial001_py310_tests_main.py | 25 ------------------- .../test_tutorial001_py39_tests_main.py | 25 ------------------- .../test_tutorial001_tests_main.py | 25 ++++++++++++++++--- 3 files changed, 22 insertions(+), 53 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py310_tests_main.py delete mode 100644 tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py39_tests_main.py diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py310_tests_main.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py310_tests_main.py deleted file mode 100644 index 781de7c772..0000000000 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py310_tests_main.py +++ /dev/null @@ -1,25 +0,0 @@ -import subprocess -from pathlib import Path - -from ....conftest import needs_py310 - - -@needs_py310 -def test_run_tests(clear_sqlmodel): - from docs_src.tutorial.fastapi.app_testing.tutorial001_py310 import test_main as mod - - test_path = Path(mod.__file__).resolve().parent - top_level_path = Path(__file__).resolve().parent.parent.parent.parent.parent - result = subprocess.run( - [ - "coverage", - "run", - "--parallel-mode", - "-m", - "pytest", - test_path, - ], - cwd=top_level_path, - capture_output=True, - ) - assert result.returncode == 0, result.stdout.decode("utf-8") diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py39_tests_main.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py39_tests_main.py deleted file mode 100644 index 6dbcc80d56..0000000000 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_py39_tests_main.py +++ /dev/null @@ -1,25 +0,0 @@ -import subprocess -from pathlib import Path - -from ....conftest import needs_py39 - - -@needs_py39 -def test_run_tests(clear_sqlmodel): - from docs_src.tutorial.fastapi.app_testing.tutorial001_py39 import test_main as mod - - test_path = Path(mod.__file__).resolve().parent - top_level_path = Path(__file__).resolve().parent.parent.parent.parent.parent - result = subprocess.run( - [ - "coverage", - "run", - "--parallel-mode", - "-m", - "pytest", - test_path, - ], - cwd=top_level_path, - capture_output=True, - ) - assert result.returncode == 0, result.stdout.decode("utf-8") diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py index d7c1329b38..28959f79d8 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests_main.py @@ -1,11 +1,30 @@ +import importlib import subprocess from pathlib import Path +from types import ModuleType +import pytest -def test_run_tests(clear_sqlmodel): - from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main as mod +from ....conftest import needs_py39, needs_py310 - test_path = Path(mod.__file__).resolve().parent + +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module( + f"docs_src.tutorial.fastapi.app_testing.{request.param}.test_main" + ) + return module + + +def test_run_tests(module: ModuleType): + test_path = Path(module.__file__).resolve().parent top_level_path = Path(__file__).resolve().parent.parent.parent.parent.parent result = subprocess.run( [ From d4add524829ccf1b5591a478175b3510e7be07f2 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 16:49:32 +0100 Subject: [PATCH 15/79] Parametrize `docs_src.tutorial.fastapi.app_testing.tutorial001_tests_00X` (X: 1-4) to tests variants --- .../test_tutorial001_tests001.py | 42 +++++++++++++++---- .../test_tutorial001_tests002.py | 42 +++++++++++++++---- .../test_tutorial001_tests003.py | 42 +++++++++++++++---- .../test_tutorial001_tests004.py | 42 +++++++++++++++---- 4 files changed, 136 insertions(+), 32 deletions(-) diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py index 4da11c2121..95be986fc9 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests001.py @@ -1,18 +1,44 @@ import importlib +import sys +from dataclasses import dataclass +from types import ModuleType import pytest -from docs_src.tutorial.fastapi.app_testing.tutorial001 import main as app_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main_001 as test_mod +from tests.conftest import needs_py39, needs_py310 -@pytest.fixture(name="prepare", autouse=True) -def prepare_fixture(clear_sqlmodel): +@dataclass +class Modules: + app: ModuleType + test: ModuleType + + +@pytest.fixture( + name="modules_path", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_modules_path(request: pytest.FixtureRequest) -> str: + return f"docs_src.tutorial.fastapi.app_testing.{request.param}" + + +@pytest.fixture(name="modules") +def load_modules(clear_sqlmodel, modules_path: str) -> Modules: # Trigger side effects of registering table models in SQLModel # This has to be called after clear_sqlmodel - importlib.reload(app_mod) - importlib.reload(test_mod) + app_mod_path = f"{modules_path}.main" + if app_mod_path in sys.modules: + app_mod = sys.modules[app_mod_path] + importlib.reload(app_mod) + else: + app_mod = importlib.import_module(app_mod_path) + test_mod = importlib.import_module(f"{modules_path}.test_main_001") + return Modules(app=app_mod, test=test_mod) -def test_tutorial(): - test_mod.test_create_hero() +def test_tutorial(modules: Modules): + modules.test.test_create_hero() diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py index 241e92323b..1f360c6f12 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests002.py @@ -1,18 +1,44 @@ import importlib +import sys +from dataclasses import dataclass +from types import ModuleType import pytest -from docs_src.tutorial.fastapi.app_testing.tutorial001 import main as app_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main_002 as test_mod +from tests.conftest import needs_py39, needs_py310 -@pytest.fixture(name="prepare", autouse=True) -def prepare_fixture(clear_sqlmodel): +@dataclass +class Modules: + app: ModuleType + test: ModuleType + + +@pytest.fixture( + name="modules_path", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_modules_path(request: pytest.FixtureRequest) -> str: + return f"docs_src.tutorial.fastapi.app_testing.{request.param}" + + +@pytest.fixture(name="modules") +def load_modules(clear_sqlmodel, modules_path: str) -> Modules: # Trigger side effects of registering table models in SQLModel # This has to be called after clear_sqlmodel - importlib.reload(app_mod) - importlib.reload(test_mod) + app_mod_path = f"{modules_path}.main" + if app_mod_path in sys.modules: + app_mod = sys.modules[app_mod_path] + importlib.reload(app_mod) + else: + app_mod = importlib.import_module(app_mod_path) + test_mod = importlib.import_module(f"{modules_path}.test_main_002") + return Modules(app=app_mod, test=test_mod) -def test_tutorial(): - test_mod.test_create_hero() +def test_tutorial(modules: Modules): + modules.test.test_create_hero() diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py index 32e0161bad..4911173b62 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests003.py @@ -1,18 +1,44 @@ import importlib +import sys +from dataclasses import dataclass +from types import ModuleType import pytest -from docs_src.tutorial.fastapi.app_testing.tutorial001 import main as app_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main_003 as test_mod +from tests.conftest import needs_py39, needs_py310 -@pytest.fixture(name="prepare", autouse=True) -def prepare_fixture(clear_sqlmodel): +@dataclass +class Modules: + app: ModuleType + test: ModuleType + + +@pytest.fixture( + name="modules_path", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_modules_path(request: pytest.FixtureRequest) -> str: + return f"docs_src.tutorial.fastapi.app_testing.{request.param}" + + +@pytest.fixture(name="modules") +def load_modules(clear_sqlmodel, modules_path: str) -> Modules: # Trigger side effects of registering table models in SQLModel # This has to be called after clear_sqlmodel - importlib.reload(app_mod) - importlib.reload(test_mod) + app_mod_path = f"{modules_path}.main" + if app_mod_path in sys.modules: + app_mod = sys.modules[app_mod_path] + importlib.reload(app_mod) + else: + app_mod = importlib.import_module(app_mod_path) + test_mod = importlib.import_module(f"{modules_path}.test_main_003") + return Modules(app=app_mod, test=test_mod) -def test_tutorial(): - test_mod.test_create_hero() +def test_tutorial(modules: Modules): + modules.test.test_create_hero() diff --git a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py index c6402b2429..b3ca441d24 100644 --- a/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py +++ b/tests/test_tutorial/test_fastapi/test_app_testing/test_tutorial001_tests004.py @@ -1,18 +1,44 @@ import importlib +import sys +from dataclasses import dataclass +from types import ModuleType import pytest -from docs_src.tutorial.fastapi.app_testing.tutorial001 import main as app_mod -from docs_src.tutorial.fastapi.app_testing.tutorial001 import test_main_004 as test_mod +from tests.conftest import needs_py39, needs_py310 -@pytest.fixture(name="prepare", autouse=True) -def prepare_fixture(clear_sqlmodel): +@dataclass +class Modules: + app: ModuleType + test: ModuleType + + +@pytest.fixture( + name="modules_path", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_modules_path(request: pytest.FixtureRequest) -> str: + return f"docs_src.tutorial.fastapi.app_testing.{request.param}" + + +@pytest.fixture(name="modules") +def load_modules(clear_sqlmodel, modules_path: str) -> Modules: # Trigger side effects of registering table models in SQLModel # This has to be called after clear_sqlmodel - importlib.reload(app_mod) - importlib.reload(test_mod) + app_mod_path = f"{modules_path}.main" + if app_mod_path in sys.modules: + app_mod = sys.modules[app_mod_path] + importlib.reload(app_mod) + else: + app_mod = importlib.import_module(app_mod_path) + test_mod = importlib.import_module(f"{modules_path}.test_main_004") + return Modules(app=app_mod, test=test_mod) -def test_tutorial(): - test_mod.test_create_hero() +def test_tutorial(modules: Modules): + modules.test.test_create_hero() From f60f0f92f6a37709ebcf9b807e1d308f45c4b369 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:42:25 +0100 Subject: [PATCH 16/79] Simplify tests for `docs_src.tutorial.fastapi.delete.tutorial001*` --- .../test_delete/test_tutorial001.py | 22 +- .../test_delete/test_tutorial001_py310.py | 377 ------------------ .../test_delete/test_tutorial001_py39.py | 377 ------------------ 3 files changed, 19 insertions(+), 757 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py index f293199b40..1480a06f54 100644 --- a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001.py @@ -1,18 +1,34 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.delete import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.fastapi.delete.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py310.py deleted file mode 100644 index 2757c878bc..0000000000 --- a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py310.py +++ /dev/null @@ -1,377 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.delete import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py39.py deleted file mode 100644 index 3299086bd0..0000000000 --- a/tests/test_tutorial/test_fastapi/test_delete/test_tutorial001_py39.py +++ /dev/null @@ -1,377 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.delete import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 37c5caee4b91edb6bcf7686eb93f02ece6909b31 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:45:09 +0100 Subject: [PATCH 17/79] Simplify tests for `docs_src.tutorial.fastapi.limit_and_offset.tutorial001*` --- .../test_limit_and_offset/test_tutorial001.py | 24 +- .../test_tutorial001_py310.py | 274 ------------------ .../test_tutorial001_py39.py | 274 ------------------ 3 files changed, 21 insertions(+), 551 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py index 4047539f0a..dc3db8b5b0 100644 --- a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001.py @@ -1,18 +1,36 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.limit_and_offset import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.limit_and_offset.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py310.py deleted file mode 100644 index 480b92a121..0000000000 --- a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py310.py +++ /dev/null @@ -1,274 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.limit_and_offset import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - - response = client.get("/heroes/", params={"limit": 2}) - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[1]["name"] == hero2_data["name"] - - response = client.get("/heroes/", params={"offset": 1}) - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - assert data[0]["name"] == hero2_data["name"] - assert data[1]["name"] == hero3_data["name"] - - response = client.get("/heroes/", params={"offset": 1, "limit": 1}) - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 1 - assert data[0]["name"] == hero2_data["name"] - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py39.py deleted file mode 100644 index 0a9d5c9ef0..0000000000 --- a/tests/test_tutorial/test_fastapi/test_limit_and_offset/test_tutorial001_py39.py +++ /dev/null @@ -1,274 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.limit_and_offset import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - - response = client.get("/heroes/", params={"limit": 2}) - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[1]["name"] == hero2_data["name"] - - response = client.get("/heroes/", params={"offset": 1}) - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - assert data[0]["name"] == hero2_data["name"] - assert data[1]["name"] == hero3_data["name"] - - response = client.get("/heroes/", params={"offset": 1, "limit": 1}) - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 1 - assert data[0]["name"] == hero2_data["name"] - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 783ba9b45e900731a1cc43ce7b1e0034339e483a Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:48:17 +0100 Subject: [PATCH 18/79] Simplify tests for `docs_src.tutorial.fastapi.multiple_models.tutorial001*` --- .../test_multiple_models/test_tutorial001.py | 28 ++- .../test_tutorial001_py310.py | 220 ----------------- .../test_tutorial001_py39.py | 221 ------------------ 3 files changed, 23 insertions(+), 446 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py index 276a021c54..27629c891d 100644 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001.py @@ -1,3 +1,7 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlalchemy import inspect @@ -5,16 +9,30 @@ from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.multiple_models import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.multiple_models.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", @@ -195,8 +213,8 @@ def test_tutorial(clear_sqlmodel): } # Test inherited indexes - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) + insp: Inspector = inspect(module.engine) + indexes = insp.get_indexes(str(module.Hero.__tablename__)) expected_indexes = [ { "name": "ix_hero_name", diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py310.py deleted file mode 100644 index b6f082a0f8..0000000000 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py310.py +++ /dev/null @@ -1,220 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.multiple_models import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero1_data["name"] - assert data["secret_name"] == hero1_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.post("/heroes/", json=hero2_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"] - assert data["secret_name"] == hero2_data["secret_name"] - assert data["id"] != hero2_data["id"], ( - "Now it's not possible to predefine the ID from the request, " - "it's now set by the database" - ) - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[0]["secret_name"] == hero1_data["secret_name"] - assert data[1]["name"] == hero2_data["name"] - assert data[1]["secret_name"] == hero2_data["secret_name"] - assert data[1]["id"] != hero2_data["id"] - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["id", "name", "secret_name"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "integer"}, - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } - - # Test inherited indexes - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) - expected_indexes = [ - { - "name": "ix_hero_name", - "dialect_options": {}, - "column_names": ["name"], - "unique": 0, - }, - { - "name": "ix_hero_age", - "dialect_options": {}, - "column_names": ["age"], - "unique": 0, - }, - ] - for index in expected_indexes: - assert index in indexes, "This expected index should be in the indexes in DB" - # Now that this index was checked, remove it from the list of indexes - indexes.pop(indexes.index(index)) - assert len(indexes) == 0, "The database should only have the expected indexes" diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py39.py deleted file mode 100644 index 82365ced61..0000000000 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial001_py39.py +++ /dev/null @@ -1,221 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.multiple_models import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero1_data["name"] - assert data["secret_name"] == hero1_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.post("/heroes/", json=hero2_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"] - assert data["secret_name"] == hero2_data["secret_name"] - assert data["id"] != hero2_data["id"], ( - "Now it's not possible to predefine the ID from the request, " - "it's now set by the database" - ) - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[0]["secret_name"] == hero1_data["secret_name"] - assert data[1]["name"] == hero2_data["name"] - assert data[1]["secret_name"] == hero2_data["secret_name"] - assert data[1]["id"] != hero2_data["id"] - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["id", "name", "secret_name"], - "type": "object", - "properties": { - "id": {"title": "Id", "type": "integer"}, - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } - - # Test inherited indexes - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) - expected_indexes = [ - { - "name": "ix_hero_name", - "dialect_options": {}, - "column_names": ["name"], - "unique": 0, - }, - { - "name": "ix_hero_age", - "dialect_options": {}, - "column_names": ["age"], - "unique": 0, - }, - ] - for index in expected_indexes: - assert index in indexes, "This expected index should be in the indexes in DB" - # Now that this index was checked, remove it from the list of indexes - indexes.pop(indexes.index(index)) - assert len(indexes) == 0, "The database should only have the expected indexes" From da07e7b7a2479783daf42a5170fbbd7ddc4a8291 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:50:12 +0100 Subject: [PATCH 19/79] Simplify tests for `docs_src.tutorial.fastapi.multiple_models.tutorial002*` --- .../test_multiple_models/test_tutorial002.py | 28 ++- .../test_tutorial002_py310.py | 221 ------------------ .../test_tutorial002_py39.py | 221 ------------------ 3 files changed, 23 insertions(+), 447 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py index 8327c6d566..c840bde253 100644 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py +++ b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002.py @@ -1,3 +1,7 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlalchemy import inspect @@ -5,16 +9,30 @@ from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.multiple_models import tutorial002 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.multiple_models.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", @@ -195,8 +213,8 @@ def test_tutorial(clear_sqlmodel): } # Test inherited indexes - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) + insp: Inspector = inspect(module.engine) + indexes = insp.get_indexes(str(module.Hero.__tablename__)) expected_indexes = [ { "name": "ix_hero_age", diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py310.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py310.py deleted file mode 100644 index 30edc4dea3..0000000000 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py310.py +++ /dev/null @@ -1,221 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.multiple_models import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero1_data["name"] - assert data["secret_name"] == hero1_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.post("/heroes/", json=hero2_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"] - assert data["secret_name"] == hero2_data["secret_name"] - assert data["id"] != hero2_data["id"], ( - "Now it's not possible to predefine the ID from the request, " - "it's now set by the database" - ) - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[0]["secret_name"] == hero1_data["secret_name"] - assert data[1]["name"] == hero2_data["name"] - assert data[1]["secret_name"] == hero2_data["secret_name"] - assert data[1]["id"] != hero2_data["id"] - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } - - # Test inherited indexes - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) - expected_indexes = [ - { - "name": "ix_hero_age", - "dialect_options": {}, - "column_names": ["age"], - "unique": 0, - }, - { - "name": "ix_hero_name", - "dialect_options": {}, - "column_names": ["name"], - "unique": 0, - }, - ] - for index in expected_indexes: - assert index in indexes, "This expected index should be in the indexes in DB" - # Now that this index was checked, remove it from the list of indexes - indexes.pop(indexes.index(index)) - assert len(indexes) == 0, "The database should only have the expected indexes" diff --git a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py39.py b/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py39.py deleted file mode 100644 index 2b86d3facc..0000000000 --- a/tests/test_tutorial/test_fastapi/test_multiple_models/test_tutorial002_py39.py +++ /dev/null @@ -1,221 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.multiple_models import tutorial002_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero1_data["name"] - assert data["secret_name"] == hero1_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.post("/heroes/", json=hero2_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"] - assert data["secret_name"] == hero2_data["secret_name"] - assert data["id"] != hero2_data["id"], ( - "Now it's not possible to predefine the ID from the request, " - "it's now set by the database" - ) - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[0]["secret_name"] == hero1_data["secret_name"] - assert data[1]["name"] == hero2_data["name"] - assert data[1]["secret_name"] == hero2_data["secret_name"] - assert data[1]["id"] != hero2_data["id"] - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } - - # Test inherited indexes - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) - expected_indexes = [ - { - "name": "ix_hero_age", - "dialect_options": {}, - "column_names": ["age"], - "unique": 0, - }, - { - "name": "ix_hero_name", - "dialect_options": {}, - "column_names": ["name"], - "unique": 0, - }, - ] - for index in expected_indexes: - assert index in indexes, "This expected index should be in the indexes in DB" - # Now that this index was checked, remove it from the list of indexes - indexes.pop(indexes.index(index)) - assert len(indexes) == 0, "The database should only have the expected indexes" From 8d79c91fba593649a86ac5d94979050e60f1bf8d Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:52:44 +0100 Subject: [PATCH 20/79] Simplify tests for `docs_src.tutorial.fastapi.read_one.tutorial001*` --- .../test_read_one/test_tutorial001.py | 22 +- .../test_read_one/test_tutorial001_py310.py | 219 ------------------ .../test_read_one/test_tutorial001_py39.py | 219 ------------------ 3 files changed, 19 insertions(+), 441 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py index 9b1d527565..affea513dd 100644 --- a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001.py @@ -1,18 +1,34 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.read_one import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.fastapi.read_one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py310.py deleted file mode 100644 index f18b0d65cf..0000000000 --- a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py310.py +++ /dev/null @@ -1,219 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.read_one import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - - hero_id = hero2["id"] - response = client.get(f"/heroes/{hero_id}") - assert response.status_code == 200, response.text - data = response.json() - assert data == hero2 - - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py39.py deleted file mode 100644 index 4423d1a713..0000000000 --- a/tests/test_tutorial/test_fastapi/test_read_one/test_tutorial001_py39.py +++ /dev/null @@ -1,219 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.read_one import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - - hero_id = hero2["id"] - response = client.get(f"/heroes/{hero_id}") - assert response.status_code == 200, response.text - data = response.json() - assert data == hero2 - - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - } - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 53e4259b03cec5f16c049b4e8c3e6c567de15d3b Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:54:59 +0100 Subject: [PATCH 21/79] Simplify tests for `docs_src.tutorial.fastapi.relationships.tutorial001*` --- .../test_relationships/test_tutorial001.py | 24 +- .../test_tutorial001_py310.py | 767 ------------------ .../test_tutorial001_py39.py | 767 ------------------ 3 files changed, 21 insertions(+), 1537 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py index 4b4f47b762..1d0446ed41 100644 --- a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001.py @@ -1,18 +1,36 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.relationships import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.relationships.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} response = client.post("/teams/", json=team_preventers) diff --git a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py310.py deleted file mode 100644 index dcb78f597d..0000000000 --- a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py310.py +++ /dev/null @@ -1,767 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.relationships import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} - team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} - response = client.post("/teams/", json=team_preventers) - assert response.status_code == 200, response.text - team_preventers_data = response.json() - team_preventers_id = team_preventers_data["id"] - response = client.post("/teams/", json=team_z_force) - assert response.status_code == 200, response.text - team_z_force_data = response.json() - team_z_force_id = team_z_force_data["id"] - response = client.get("/teams/") - data = response.json() - assert len(data) == 2 - response = client.get("/teams/9000") - assert response.status_code == 404, response.text - response = client.patch( - f"/teams/{team_preventers_id}", json={"headquarters": "Preventers Tower"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == team_preventers["name"] - assert data["headquarters"] == "Preventers Tower" - response = client.patch("/teams/9000", json={"name": "Freedom League"}) - assert response.status_code == 404, response.text - - hero1_data = { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": team_z_force_id, - } - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - "team_id": team_preventers_id, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - hero1 = response.json() - hero1_id = hero1["id"] - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.get(f"/heroes/{hero1_id}") - assert response.status_code == 200, response.text - data = response.json() - assert data["name"] == hero1_data["name"] - assert data["team"]["name"] == team_z_force["name"] - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get(f"/teams/{team_preventers_id}") - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == team_preventers_data["name"] - assert data["heroes"][0]["name"] == hero3_data["name"] - - response = client.delete(f"/teams/{team_preventers_id}") - assert response.status_code == 200, response.text - response = client.delete("/teams/9000") - assert response.status_code == 404, response.text - response = client.get("/teams/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 1 - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublicWithTeam" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/": { - "get": { - "summary": "Read Teams", - "operationId": "read_teams_teams__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Teams Teams Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Team", - "operationId": "create_team_teams__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/{team_id}": { - "get": { - "summary": "Read Team", - "operationId": "read_team_teams__team_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublicWithHeroes" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Team", - "operationId": "delete_team_teams__team_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Team", - "operationId": "update_team_teams__team_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroPublicWithTeam": { - "title": "HeroPublicWithTeam", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - "team": IsDict( - { - "anyOf": [ - {"$ref": "#/components/schemas/TeamPublic"}, - {"type": "null"}, - ] - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"$ref": "#/components/schemas/TeamPublic"} - ), - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "TeamCreate": { - "title": "TeamCreate", - "required": ["name", "headquarters"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - }, - }, - "TeamPublic": { - "title": "TeamPublic", - "required": ["name", "headquarters", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - "id": {"title": "Id", "type": "integer"}, - }, - }, - "TeamPublicWithHeroes": { - "title": "TeamPublicWithHeroes", - "required": ["name", "headquarters", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - "id": {"title": "Id", "type": "integer"}, - "heroes": { - "title": "Heroes", - "type": "array", - "items": {"$ref": "#/components/schemas/HeroPublic"}, - "default": [], - }, - }, - }, - "TeamUpdate": { - "title": "TeamUpdate", - "type": "object", - "properties": { - "id": IsDict( - { - "title": "Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Id", "type": "integer"} - ), - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "headquarters": IsDict( - { - "title": "Headquarters", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Headquarters", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py39.py deleted file mode 100644 index 5ef7338d44..0000000000 --- a/tests/test_tutorial/test_fastapi/test_relationships/test_tutorial001_py39.py +++ /dev/null @@ -1,767 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.relationships import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} - team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} - response = client.post("/teams/", json=team_preventers) - assert response.status_code == 200, response.text - team_preventers_data = response.json() - team_preventers_id = team_preventers_data["id"] - response = client.post("/teams/", json=team_z_force) - assert response.status_code == 200, response.text - team_z_force_data = response.json() - team_z_force_id = team_z_force_data["id"] - response = client.get("/teams/") - data = response.json() - assert len(data) == 2 - response = client.get("/teams/9000") - assert response.status_code == 404, response.text - response = client.patch( - f"/teams/{team_preventers_id}", json={"headquarters": "Preventers Tower"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == team_preventers["name"] - assert data["headquarters"] == "Preventers Tower" - response = client.patch("/teams/9000", json={"name": "Freedom League"}) - assert response.status_code == 404, response.text - - hero1_data = { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": team_z_force_id, - } - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - "team_id": team_preventers_id, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - hero1 = response.json() - hero1_id = hero1["id"] - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.get(f"/heroes/{hero1_id}") - assert response.status_code == 200, response.text - data = response.json() - assert data["name"] == hero1_data["name"] - assert data["team"]["name"] == team_z_force["name"] - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get(f"/teams/{team_preventers_id}") - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == team_preventers_data["name"] - assert data["heroes"][0]["name"] == hero3_data["name"] - - response = client.delete(f"/teams/{team_preventers_id}") - assert response.status_code == 200, response.text - response = client.delete("/teams/9000") - assert response.status_code == 404, response.text - response = client.get("/teams/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 1 - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublicWithTeam" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/": { - "get": { - "summary": "Read Teams", - "operationId": "read_teams_teams__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Teams Teams Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Team", - "operationId": "create_team_teams__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/{team_id}": { - "get": { - "summary": "Read Team", - "operationId": "read_team_teams__team_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublicWithHeroes" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Team", - "operationId": "delete_team_teams__team_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Team", - "operationId": "update_team_teams__team_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroPublicWithTeam": { - "title": "HeroPublicWithTeam", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - "team": IsDict( - { - "anyOf": [ - {"$ref": "#/components/schemas/TeamPublic"}, - {"type": "null"}, - ] - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"$ref": "#/components/schemas/TeamPublic"} - ), - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "TeamCreate": { - "title": "TeamCreate", - "required": ["name", "headquarters"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - }, - }, - "TeamPublic": { - "title": "TeamPublic", - "required": ["name", "headquarters", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - "id": {"title": "Id", "type": "integer"}, - }, - }, - "TeamPublicWithHeroes": { - "title": "TeamPublicWithHeroes", - "required": ["name", "headquarters", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - "id": {"title": "Id", "type": "integer"}, - "heroes": { - "title": "Heroes", - "type": "array", - "items": {"$ref": "#/components/schemas/HeroPublic"}, - "default": [], - }, - }, - }, - "TeamUpdate": { - "title": "TeamUpdate", - "type": "object", - "properties": { - "id": IsDict( - { - "title": "Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Id", "type": "integer"} - ), - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "headquarters": IsDict( - { - "title": "Headquarters", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Headquarters", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From db4c13257a339817d13c097012727e804a12fb78 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:56:42 +0100 Subject: [PATCH 22/79] Simplify tests for `docs_src.tutorial.fastapi.response_model.tutorial001*` --- .../test_response_model/test_tutorial001.py | 24 ++- .../test_tutorial001_py310.py | 162 ------------------ .../test_tutorial001_py39.py | 162 ------------------ 3 files changed, 21 insertions(+), 327 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py index 8f273bbd93..186a120311 100644 --- a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001.py @@ -1,18 +1,36 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.response_model import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.response_model.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} response = client.post("/heroes/", json=hero_data) data = response.json() diff --git a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py310.py deleted file mode 100644 index d249cc4e90..0000000000 --- a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py310.py +++ /dev/null @@ -1,162 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.response_model import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - response = client.post("/heroes/", json=hero_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero_data["name"] - assert data["secret_name"] == hero_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 1 - assert data[0]["name"] == hero_data["name"] - assert data[0]["secret_name"] == hero_data["secret_name"] - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/Hero" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Hero"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Hero"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "Hero": { - "title": "Hero", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "id": IsDict( - { - "title": "Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Id", "type": "integer"} - ), - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py39.py deleted file mode 100644 index b9fb2be03f..0000000000 --- a/tests/test_tutorial/test_fastapi/test_response_model/test_tutorial001_py39.py +++ /dev/null @@ -1,162 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.response_model import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - response = client.post("/heroes/", json=hero_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero_data["name"] - assert data["secret_name"] == hero_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 1 - assert data[0]["name"] == hero_data["name"] - assert data[0]["secret_name"] == hero_data["secret_name"] - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/Hero" - }, - } - } - }, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Hero"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Hero"} - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "Hero": { - "title": "Hero", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "id": IsDict( - { - "title": "Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Id", "type": "integer"} - ), - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 2c4659fc03c0f5e8ba0acaa671762ec37e2e5445 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 18:58:32 +0100 Subject: [PATCH 23/79] Simplify tests for `docs_src.tutorial.fastapi.session_with_dependency.tutorial001*` --- .../test_tutorial001.py | 24 +- .../test_tutorial001_py310.py | 379 ------------------ .../test_tutorial001_py39.py | 379 ------------------ 3 files changed, 21 insertions(+), 761 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py index 388cfa9b2b..184fb219a9 100644 --- a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001.py @@ -1,18 +1,36 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.session_with_dependency import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.session_with_dependency.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py310.py deleted file mode 100644 index 65bab47735..0000000000 --- a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py310.py +++ /dev/null @@ -1,379 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.session_with_dependency import ( - tutorial001_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py39.py deleted file mode 100644 index cdab85df17..0000000000 --- a/tests/test_tutorial/test_fastapi/test_session_with_dependency/test_tutorial001_py39.py +++ /dev/null @@ -1,379 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.session_with_dependency import ( - tutorial001_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 433f0e5f243fc001e3741b63fe731acc6c7f2d59 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:01:00 +0100 Subject: [PATCH 24/79] Simplify tests for `docs_src.tutorial.fastapi.simple_hero_api.tutorial001*` --- .../test_simple_hero_api/test_tutorial001.py | 23 ++- .../test_tutorial001_py310.py | 168 ------------------ 2 files changed, 20 insertions(+), 171 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py index 9df7e50b81..dba7bc3879 100644 --- a/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001.py @@ -1,18 +1,35 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.simple_hero_api import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.fastapi.simple_hero_api.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001_py310.py deleted file mode 100644 index a47513dde2..0000000000 --- a/tests/test_tutorial/test_fastapi/test_simple_hero_api/test_tutorial001_py310.py +++ /dev/null @@ -1,168 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.simple_hero_api import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - response = client.post("/heroes/", json=hero1_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero1_data["name"] - assert data["secret_name"] == hero1_data["secret_name"] - assert data["id"] is not None - assert data["age"] is None - - response = client.post("/heroes/", json=hero2_data) - data = response.json() - - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"] - assert data["secret_name"] == hero2_data["secret_name"] - assert data["id"] == hero2_data["id"], ( - "Up to this point it's still possible to " - "set the ID of the hero in the request" - ) - assert data["age"] is None - - response = client.get("/heroes/") - data = response.json() - - assert response.status_code == 200, response.text - assert len(data) == 2 - assert data[0]["name"] == hero1_data["name"] - assert data[0]["secret_name"] == hero1_data["secret_name"] - assert data[1]["name"] == hero2_data["name"] - assert data[1]["secret_name"] == hero2_data["secret_name"] - assert data[1]["id"] == hero2_data["id"] - - response = client.get("/openapi.json") - - assert response.status_code == 200, response.text - - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - } - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": {"$ref": "#/components/schemas/Hero"} - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - } - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "Hero": { - "title": "Hero", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "id": IsDict( - { - "title": "Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Id", "type": "integer"} - ), - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 9faafbde9956cf85ff417f5f49f84e2b269a88d4 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:02:55 +0100 Subject: [PATCH 25/79] Simplify tests for `docs_src.tutorial.fastapi.teams.tutorial001*` --- .../test_teams/test_tutorial001.py | 22 +- .../test_teams/test_tutorial001_py310.py | 686 ------------------ .../test_teams/test_tutorial001_py39.py | 686 ------------------ 3 files changed, 19 insertions(+), 1375 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py index 25daadf74b..2e7d66a036 100644 --- a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001.py @@ -1,18 +1,34 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.teams import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.fastapi.teams.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py310.py deleted file mode 100644 index 63f8a1d70b..0000000000 --- a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py310.py +++ /dev/null @@ -1,686 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.teams import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} - team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} - response = client.post("/teams/", json=team_preventers) - assert response.status_code == 200, response.text - team_preventers_data = response.json() - team_preventers_id = team_preventers_data["id"] - response = client.post("/teams/", json=team_z_force) - assert response.status_code == 200, response.text - team_z_force_data = response.json() - team_z_force_data["id"] - response = client.get("/teams/") - data = response.json() - assert len(data) == 2 - response = client.get(f"/teams/{team_preventers_id}") - data = response.json() - assert response.status_code == 200, response.text - assert data == team_preventers_data - response = client.get("/teams/9000") - assert response.status_code == 404, response.text - response = client.patch( - f"/teams/{team_preventers_id}", json={"headquarters": "Preventers Tower"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == team_preventers["name"] - assert data["headquarters"] == "Preventers Tower" - response = client.patch("/teams/9000", json={"name": "Freedom League"}) - assert response.status_code == 404, response.text - response = client.delete(f"/teams/{team_preventers_id}") - assert response.status_code == 200, response.text - response = client.delete("/teams/9000") - assert response.status_code == 404, response.text - response = client.get("/teams/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 1 - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/": { - "get": { - "summary": "Read Teams", - "operationId": "read_teams_teams__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Teams Teams Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Team", - "operationId": "create_team_teams__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/{team_id}": { - "get": { - "summary": "Read Team", - "operationId": "read_team_teams__team_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Team", - "operationId": "delete_team_teams__team_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Team", - "operationId": "update_team_teams__team_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "TeamCreate": { - "title": "TeamCreate", - "required": ["name", "headquarters"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - }, - }, - "TeamPublic": { - "title": "TeamPublic", - "required": ["name", "headquarters", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - "id": {"title": "Id", "type": "integer"}, - }, - }, - "TeamUpdate": { - "title": "TeamUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "headquarters": IsDict( - { - "title": "Headquarters", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Headquarters", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py39.py deleted file mode 100644 index 30b68e0ed9..0000000000 --- a/tests/test_tutorial/test_fastapi/test_teams/test_tutorial001_py39.py +++ /dev/null @@ -1,686 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.teams import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - assert response.status_code == 200, response.text - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - response = client.delete(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 2 - response = client.delete("/heroes/9000") - assert response.status_code == 404, response.text - - team_preventers = {"name": "Preventers", "headquarters": "Sharp Tower"} - team_z_force = {"name": "Z-Force", "headquarters": "Sister Margaret's Bar"} - response = client.post("/teams/", json=team_preventers) - assert response.status_code == 200, response.text - team_preventers_data = response.json() - team_preventers_id = team_preventers_data["id"] - response = client.post("/teams/", json=team_z_force) - assert response.status_code == 200, response.text - team_z_force_data = response.json() - team_z_force_data["id"] - response = client.get("/teams/") - data = response.json() - assert len(data) == 2 - response = client.get(f"/teams/{team_preventers_id}") - data = response.json() - assert response.status_code == 200, response.text - assert data == team_preventers_data - response = client.get("/teams/9000") - assert response.status_code == 404, response.text - response = client.patch( - f"/teams/{team_preventers_id}", json={"headquarters": "Preventers Tower"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == team_preventers["name"] - assert data["headquarters"] == "Preventers Tower" - response = client.patch("/teams/9000", json={"name": "Freedom League"}) - assert response.status_code == 404, response.text - response = client.delete(f"/teams/{team_preventers_id}") - assert response.status_code == 200, response.text - response = client.delete("/teams/9000") - assert response.status_code == 404, response.text - response = client.get("/teams/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 1 - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Hero", - "operationId": "delete_hero_heroes__hero_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/": { - "get": { - "summary": "Read Teams", - "operationId": "read_teams_teams__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Teams Teams Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/TeamPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Team", - "operationId": "create_team_teams__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/teams/{team_id}": { - "get": { - "summary": "Read Team", - "operationId": "read_team_teams__team_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "delete": { - "summary": "Delete Team", - "operationId": "delete_team_teams__team_id__delete", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": {"application/json": {"schema": {}}}, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Team", - "operationId": "update_team_teams__team_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Team Id", "type": "integer"}, - "name": "team_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/TeamPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "team_id": IsDict( - { - "title": "Team Id", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Team Id", "type": "integer"} - ), - }, - }, - "TeamCreate": { - "title": "TeamCreate", - "required": ["name", "headquarters"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - }, - }, - "TeamPublic": { - "title": "TeamPublic", - "required": ["name", "headquarters", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "headquarters": {"title": "Headquarters", "type": "string"}, - "id": {"title": "Id", "type": "integer"}, - }, - }, - "TeamUpdate": { - "title": "TeamUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "headquarters": IsDict( - { - "title": "Headquarters", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Headquarters", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 00a1ae71e936784d849a4ecc15439ca41bf1d4e2 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:04:28 +0100 Subject: [PATCH 26/79] Simplify tests for `docs_src.tutorial.fastapi.update.tutorial001*` --- .../test_update/test_tutorial001.py | 22 +- .../test_update/test_tutorial001_py310.py | 356 ------------------ .../test_update/test_tutorial001_py39.py | 356 ------------------ 3 files changed, 19 insertions(+), 715 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py index 6f3856912e..b6ee27611f 100644 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py +++ b/tests/test_tutorial/test_fastapi/test_update/test_tutorial001.py @@ -1,18 +1,34 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.update import tutorial001 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.fastapi.update.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} hero2_data = { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py310.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py310.py deleted file mode 100644 index 119634dc1e..0000000000 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py310.py +++ /dev/null @@ -1,356 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.update import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - hero3 = response.json() - hero3_id = hero3["id"] - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"], "The name should not be set to none" - assert data["secret_name"] == "Spider-Youngster", ( - "The secret name should be updated" - ) - - response = client.patch(f"/heroes/{hero3_id}", json={"age": None}) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero3_data["name"] - assert data["age"] is None, ( - "A field should be updatable to None, even if that's the default" - ) - - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py39.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py39.py deleted file mode 100644 index 455480f735..0000000000 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial001_py39.py +++ /dev/null @@ -1,356 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.update import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = {"name": "Deadpond", "secret_name": "Dive Wilson"} - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - hero3 = response.json() - hero3_id = hero3["id"] - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"], "The name should not be set to none" - assert data["secret_name"] == "Spider-Youngster", ( - "The secret name should be updated" - ) - - response = client.patch(f"/heroes/{hero3_id}", json={"age": None}) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero3_data["name"] - assert data["age"] is None, ( - "A field should be updatable to None, even if that's the default" - ) - - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100.0, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "title": "Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "title": "Secret Name", - "anyOf": [{"type": "string"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "title": "Age", - "anyOf": [{"type": "integer"}, {"type": "null"}], - } - ) - | IsDict( - # TODO: remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 27ae4eeb4890e064e13e452d1413a75eb0c96799 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:06:56 +0100 Subject: [PATCH 27/79] Simplify tests for `docs_src.tutorial.fastapi.update.tutorial002*` --- .../test_update/test_tutorial002.py | 42 +- .../test_update/test_tutorial002_py310.py | 430 ------------------ .../test_update/test_tutorial002_py39.py | 430 ------------------ 3 files changed, 29 insertions(+), 873 deletions(-) delete mode 100644 tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py index 2a929f6dae..a9312651b7 100644 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py +++ b/tests/test_tutorial/test_fastapi/test_update/test_tutorial002.py @@ -1,18 +1,34 @@ +import importlib +from types import ModuleType + +import pytest from dirty_equals import IsDict from fastapi.testclient import TestClient from sqlmodel import Session, create_engine from sqlmodel.pool import StaticPool +from tests.conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.update import tutorial002 as mod +@pytest.fixture( + name="module", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.fastapi.update.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine( mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool ) + return mod + - with TestClient(mod.app) as client: +def test_tutorial(module: ModuleType): + with TestClient(module.app) as client: hero1_data = { "name": "Deadpond", "secret_name": "Dive Wilson", @@ -60,16 +76,16 @@ def test_tutorial(clear_sqlmodel): assert "hashed_password" not in response_hero # Test hashed passwords - with Session(mod.engine) as session: - hero1_db = session.get(mod.Hero, hero1_id) + with Session(module.engine) as session: + hero1_db = session.get(module.Hero, hero1_id) assert hero1_db assert not hasattr(hero1_db, "password") assert hero1_db.hashed_password == "not really hashed chimichanga hehehe" - hero2_db = session.get(mod.Hero, hero2_id) + hero2_db = session.get(module.Hero, hero2_id) assert hero2_db assert not hasattr(hero2_db, "password") assert hero2_db.hashed_password == "not really hashed auntmay hehehe" - hero3_db = session.get(mod.Hero, hero3_id) + hero3_db = session.get(module.Hero, hero3_id) assert hero3_db assert not hasattr(hero3_db, "password") assert hero3_db.hashed_password == "not really hashed bestpreventer hehehe" @@ -85,8 +101,8 @@ def test_tutorial(clear_sqlmodel): ) assert "password" not in data assert "hashed_password" not in data - with Session(mod.engine) as session: - hero2b_db = session.get(mod.Hero, hero2_id) + with Session(module.engine) as session: + hero2b_db = session.get(module.Hero, hero2_id) assert hero2b_db assert not hasattr(hero2b_db, "password") assert hero2b_db.hashed_password == "not really hashed auntmay hehehe" @@ -100,8 +116,8 @@ def test_tutorial(clear_sqlmodel): ) assert "password" not in data assert "hashed_password" not in data - with Session(mod.engine) as session: - hero3b_db = session.get(mod.Hero, hero3_id) + with Session(module.engine) as session: + hero3b_db = session.get(module.Hero, hero3_id) assert hero3b_db assert not hasattr(hero3b_db, "password") assert hero3b_db.hashed_password == "not really hashed bestpreventer hehehe" @@ -116,8 +132,8 @@ def test_tutorial(clear_sqlmodel): assert data["age"] is None assert "password" not in data assert "hashed_password" not in data - with Session(mod.engine) as session: - hero3b_db = session.get(mod.Hero, hero3_id) + with Session(module.engine) as session: + hero3b_db = session.get(module.Hero, hero3_id) assert hero3b_db assert not hasattr(hero3b_db, "password") assert ( diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py310.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py310.py deleted file mode 100644 index 7617f14996..0000000000 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py310.py +++ /dev/null @@ -1,430 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import Session, create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.update import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "password": "chimichanga", - } - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - "password": "auntmay", - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - "password": "bestpreventer", - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - hero1 = response.json() - assert "password" not in hero1 - assert "hashed_password" not in hero1 - hero1_id = hero1["id"] - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - hero3 = response.json() - hero3_id = hero3["id"] - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - fetched_hero2 = response.json() - assert "password" not in fetched_hero2 - assert "hashed_password" not in fetched_hero2 - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - for response_hero in data: - assert "password" not in response_hero - assert "hashed_password" not in response_hero - - # Test hashed passwords - with Session(mod.engine) as session: - hero1_db = session.get(mod.Hero, hero1_id) - assert hero1_db - assert not hasattr(hero1_db, "password") - assert hero1_db.hashed_password == "not really hashed chimichanga hehehe" - hero2_db = session.get(mod.Hero, hero2_id) - assert hero2_db - assert not hasattr(hero2_db, "password") - assert hero2_db.hashed_password == "not really hashed auntmay hehehe" - hero3_db = session.get(mod.Hero, hero3_id) - assert hero3_db - assert not hasattr(hero3_db, "password") - assert hero3_db.hashed_password == "not really hashed bestpreventer hehehe" - - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"], "The name should not be set to none" - assert data["secret_name"] == "Spider-Youngster", ( - "The secret name should be updated" - ) - assert "password" not in data - assert "hashed_password" not in data - with Session(mod.engine) as session: - hero2b_db = session.get(mod.Hero, hero2_id) - assert hero2b_db - assert not hasattr(hero2b_db, "password") - assert hero2b_db.hashed_password == "not really hashed auntmay hehehe" - - response = client.patch(f"/heroes/{hero3_id}", json={"age": None}) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero3_data["name"] - assert data["age"] is None, ( - "A field should be updatable to None, even if that's the default" - ) - assert "password" not in data - assert "hashed_password" not in data - with Session(mod.engine) as session: - hero3b_db = session.get(mod.Hero, hero3_id) - assert hero3b_db - assert not hasattr(hero3b_db, "password") - assert hero3b_db.hashed_password == "not really hashed bestpreventer hehehe" - - # Test update dict, hashed_password - response = client.patch( - f"/heroes/{hero3_id}", json={"password": "philantroplayboy"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero3_data["name"] - assert data["age"] is None - assert "password" not in data - assert "hashed_password" not in data - with Session(mod.engine) as session: - hero3b_db = session.get(mod.Hero, hero3_id) - assert hero3b_db - assert not hasattr(hero3b_db, "password") - assert ( - hero3b_db.hashed_password == "not really hashed philantroplayboy hehehe" - ) - - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name", "password"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Age", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "password": {"type": "string", "title": "Password"}, - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Age", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Name", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Secret Name", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Age", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "password": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Password", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Password", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } diff --git a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py39.py b/tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py39.py deleted file mode 100644 index dc788a29f7..0000000000 --- a/tests/test_tutorial/test_fastapi/test_update/test_tutorial002_py39.py +++ /dev/null @@ -1,430 +0,0 @@ -from dirty_equals import IsDict -from fastapi.testclient import TestClient -from sqlmodel import Session, create_engine -from sqlmodel.pool import StaticPool - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.fastapi.update import tutorial002_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine( - mod.sqlite_url, connect_args=mod.connect_args, poolclass=StaticPool - ) - - with TestClient(mod.app) as client: - hero1_data = { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "password": "chimichanga", - } - hero2_data = { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "id": 9000, - "password": "auntmay", - } - hero3_data = { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - "password": "bestpreventer", - } - response = client.post("/heroes/", json=hero1_data) - assert response.status_code == 200, response.text - hero1 = response.json() - assert "password" not in hero1 - assert "hashed_password" not in hero1 - hero1_id = hero1["id"] - response = client.post("/heroes/", json=hero2_data) - assert response.status_code == 200, response.text - hero2 = response.json() - hero2_id = hero2["id"] - response = client.post("/heroes/", json=hero3_data) - assert response.status_code == 200, response.text - hero3 = response.json() - hero3_id = hero3["id"] - response = client.get(f"/heroes/{hero2_id}") - assert response.status_code == 200, response.text - fetched_hero2 = response.json() - assert "password" not in fetched_hero2 - assert "hashed_password" not in fetched_hero2 - response = client.get("/heroes/9000") - assert response.status_code == 404, response.text - response = client.get("/heroes/") - assert response.status_code == 200, response.text - data = response.json() - assert len(data) == 3 - for response_hero in data: - assert "password" not in response_hero - assert "hashed_password" not in response_hero - - # Test hashed passwords - with Session(mod.engine) as session: - hero1_db = session.get(mod.Hero, hero1_id) - assert hero1_db - assert not hasattr(hero1_db, "password") - assert hero1_db.hashed_password == "not really hashed chimichanga hehehe" - hero2_db = session.get(mod.Hero, hero2_id) - assert hero2_db - assert not hasattr(hero2_db, "password") - assert hero2_db.hashed_password == "not really hashed auntmay hehehe" - hero3_db = session.get(mod.Hero, hero3_id) - assert hero3_db - assert not hasattr(hero3_db, "password") - assert hero3_db.hashed_password == "not really hashed bestpreventer hehehe" - - response = client.patch( - f"/heroes/{hero2_id}", json={"secret_name": "Spider-Youngster"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero2_data["name"], "The name should not be set to none" - assert data["secret_name"] == "Spider-Youngster", ( - "The secret name should be updated" - ) - assert "password" not in data - assert "hashed_password" not in data - with Session(mod.engine) as session: - hero2b_db = session.get(mod.Hero, hero2_id) - assert hero2b_db - assert not hasattr(hero2b_db, "password") - assert hero2b_db.hashed_password == "not really hashed auntmay hehehe" - - response = client.patch(f"/heroes/{hero3_id}", json={"age": None}) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero3_data["name"] - assert data["age"] is None, ( - "A field should be updatable to None, even if that's the default" - ) - assert "password" not in data - assert "hashed_password" not in data - with Session(mod.engine) as session: - hero3b_db = session.get(mod.Hero, hero3_id) - assert hero3b_db - assert not hasattr(hero3b_db, "password") - assert hero3b_db.hashed_password == "not really hashed bestpreventer hehehe" - - # Test update dict, hashed_password - response = client.patch( - f"/heroes/{hero3_id}", json={"password": "philantroplayboy"} - ) - data = response.json() - assert response.status_code == 200, response.text - assert data["name"] == hero3_data["name"] - assert data["age"] is None - assert "password" not in data - assert "hashed_password" not in data - with Session(mod.engine) as session: - hero3b_db = session.get(mod.Hero, hero3_id) - assert hero3b_db - assert not hasattr(hero3b_db, "password") - assert ( - hero3b_db.hashed_password == "not really hashed philantroplayboy hehehe" - ) - - response = client.patch("/heroes/9001", json={"name": "Dragon Cube X"}) - assert response.status_code == 404, response.text - - response = client.get("/openapi.json") - assert response.status_code == 200, response.text - assert response.json() == { - "openapi": "3.1.0", - "info": {"title": "FastAPI", "version": "0.1.0"}, - "paths": { - "/heroes/": { - "get": { - "summary": "Read Heroes", - "operationId": "read_heroes_heroes__get", - "parameters": [ - { - "required": False, - "schema": { - "title": "Offset", - "type": "integer", - "default": 0, - }, - "name": "offset", - "in": "query", - }, - { - "required": False, - "schema": { - "title": "Limit", - "maximum": 100, - "type": "integer", - "default": 100, - }, - "name": "limit", - "in": "query", - }, - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "title": "Response Read Heroes Heroes Get", - "type": "array", - "items": { - "$ref": "#/components/schemas/HeroPublic" - }, - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "post": { - "summary": "Create Hero", - "operationId": "create_hero_heroes__post", - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroCreate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - "/heroes/{hero_id}": { - "get": { - "summary": "Read Hero", - "operationId": "read_hero_heroes__hero_id__get", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - "patch": { - "summary": "Update Hero", - "operationId": "update_hero_heroes__hero_id__patch", - "parameters": [ - { - "required": True, - "schema": {"title": "Hero Id", "type": "integer"}, - "name": "hero_id", - "in": "path", - } - ], - "requestBody": { - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroUpdate" - } - } - }, - "required": True, - }, - "responses": { - "200": { - "description": "Successful Response", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HeroPublic" - } - } - }, - }, - "422": { - "description": "Validation Error", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/HTTPValidationError" - } - } - }, - }, - }, - }, - }, - }, - "components": { - "schemas": { - "HTTPValidationError": { - "title": "HTTPValidationError", - "type": "object", - "properties": { - "detail": { - "title": "Detail", - "type": "array", - "items": { - "$ref": "#/components/schemas/ValidationError" - }, - } - }, - }, - "HeroCreate": { - "title": "HeroCreate", - "required": ["name", "secret_name", "password"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Age", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "password": {"type": "string", "title": "Password"}, - }, - }, - "HeroPublic": { - "title": "HeroPublic", - "required": ["name", "secret_name", "id"], - "type": "object", - "properties": { - "name": {"title": "Name", "type": "string"}, - "secret_name": {"title": "Secret Name", "type": "string"}, - "age": IsDict( - { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Age", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "id": {"title": "Id", "type": "integer"}, - }, - }, - "HeroUpdate": { - "title": "HeroUpdate", - "type": "object", - "properties": { - "name": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Name", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Name", "type": "string"} - ), - "secret_name": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Secret Name", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Secret Name", "type": "string"} - ), - "age": IsDict( - { - "anyOf": [{"type": "integer"}, {"type": "null"}], - "title": "Age", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Age", "type": "integer"} - ), - "password": IsDict( - { - "anyOf": [{"type": "string"}, {"type": "null"}], - "title": "Password", - } - ) - | IsDict( - # TODO: Remove when deprecating Pydantic v1 - {"title": "Password", "type": "string"} - ), - }, - }, - "ValidationError": { - "title": "ValidationError", - "required": ["loc", "msg", "type"], - "type": "object", - "properties": { - "loc": { - "title": "Location", - "type": "array", - "items": { - "anyOf": [{"type": "string"}, {"type": "integer"}] - }, - }, - "msg": {"title": "Message", "type": "string"}, - "type": {"title": "Error Type", "type": "string"}, - }, - }, - } - }, - } From 131c0163cef856eccb58f7f9d096ec3085601f2c Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:13:10 +0100 Subject: [PATCH 28/79] Simplify tests for `docs_src.tutorial.indexes.tutorial001*` --- .../test_indexes/test_tutorial001.py | 27 +++++++---- .../test_indexes/test_tutorial001_py310.py | 46 ------------------- 2 files changed, 17 insertions(+), 56 deletions(-) delete mode 100644 tests/test_tutorial/test_indexes/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_indexes/test_tutorial001.py b/tests/test_tutorial/test_indexes/test_tutorial001.py index f33db5bcc7..b71f7ebd85 100644 --- a/tests/test_tutorial/test_indexes/test_tutorial001.py +++ b/tests/test_tutorial/test_indexes/test_tutorial001.py @@ -1,24 +1,31 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlalchemy import inspect from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.indexes import tutorial001 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.indexes.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"secret_name": "Dive Wilson", "age": None, "id": 1, "name": "Deadpond"}] ] diff --git a/tests/test_tutorial/test_indexes/test_tutorial001_py310.py b/tests/test_tutorial/test_indexes/test_tutorial001_py310.py deleted file mode 100644 index cfee262b2b..0000000000 --- a/tests/test_tutorial/test_indexes/test_tutorial001_py310.py +++ /dev/null @@ -1,46 +0,0 @@ -from unittest.mock import patch - -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.indexes import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"secret_name": "Dive Wilson", "age": None, "id": 1, "name": "Deadpond"}] - ] - - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) - expected_indexes = [ - { - "name": "ix_hero_name", - "dialect_options": {}, - "column_names": ["name"], - "unique": 0, - }, - { - "name": "ix_hero_age", - "dialect_options": {}, - "column_names": ["age"], - "unique": 0, - }, - ] - for index in expected_indexes: - assert index in indexes, "This expected index should be in the indexes in DB" - # Now that this index was checked, remove it from the list of indexes - indexes.pop(indexes.index(index)) - assert len(indexes) == 0, "The database should only have the expected indexes" From 5c2067b9b9cdccea300105c1364d11e9c3bf13e4 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:17:27 +0100 Subject: [PATCH 29/79] Simplify tests for `docs_src.tutorial.indexes.tutorial002*` --- .../test_indexes/test_tutorial002.py | 27 +++++++---- .../test_indexes/test_tutorial002_py310.py | 47 ------------------- 2 files changed, 17 insertions(+), 57 deletions(-) delete mode 100644 tests/test_tutorial/test_indexes/test_tutorial002_py310.py diff --git a/tests/test_tutorial/test_indexes/test_tutorial002.py b/tests/test_tutorial/test_indexes/test_tutorial002.py index 893043dad1..0aa88ea5dd 100644 --- a/tests/test_tutorial/test_indexes/test_tutorial002.py +++ b/tests/test_tutorial/test_indexes/test_tutorial002.py @@ -1,24 +1,31 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlalchemy import inspect from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.indexes import tutorial002 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.indexes.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], ] diff --git a/tests/test_tutorial/test_indexes/test_tutorial002_py310.py b/tests/test_tutorial/test_indexes/test_tutorial002_py310.py deleted file mode 100644 index 089b6828e9..0000000000 --- a/tests/test_tutorial/test_indexes/test_tutorial002_py310.py +++ /dev/null @@ -1,47 +0,0 @@ -from unittest.mock import patch - -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.indexes import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], - [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], - ] - - insp: Inspector = inspect(mod.engine) - indexes = insp.get_indexes(str(mod.Hero.__tablename__)) - expected_indexes = [ - { - "name": "ix_hero_name", - "dialect_options": {}, - "column_names": ["name"], - "unique": 0, - }, - { - "name": "ix_hero_age", - "dialect_options": {}, - "column_names": ["age"], - "unique": 0, - }, - ] - for index in expected_indexes: - assert index in indexes, "This expected index should be in the indexes in DB" - # Now that this index was checked, remove it from the list of indexes - indexes.pop(indexes.index(index)) - assert len(indexes) == 0, "The database should only have the expected indexes" From 0bafd0efd47b18cda0236f19e0450931a2614e2a Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:19:55 +0100 Subject: [PATCH 30/79] Simplify tests for `docs_src.tutorial.insert.tutorial001*` --- .../test_insert/test_tutorial001.py | 20 +++++++++++-- .../test_insert/test_tutorial001_py310.py | 30 ------------------- 2 files changed, 18 insertions(+), 32 deletions(-) delete mode 100644 tests/test_tutorial/test_insert/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_insert/test_tutorial001.py b/tests/test_tutorial/test_insert/test_tutorial001.py index 3a5162c08a..1673a70753 100644 --- a/tests/test_tutorial/test_insert/test_tutorial001.py +++ b/tests/test_tutorial/test_insert/test_tutorial001.py @@ -1,11 +1,27 @@ +import importlib +from types import ModuleType + +import pytest from sqlmodel import Session, create_engine, select +from ...conftest import needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.insert import tutorial001 as mod +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.insert.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) + return mod + + +def test_tutorial(mod: ModuleType): mod.main() with Session(mod.engine) as session: heroes = session.exec(select(mod.Hero)).all() diff --git a/tests/test_tutorial/test_insert/test_tutorial001_py310.py b/tests/test_tutorial/test_insert/test_tutorial001_py310.py deleted file mode 100644 index 47cbc4cde6..0000000000 --- a/tests/test_tutorial/test_insert/test_tutorial001_py310.py +++ /dev/null @@ -1,30 +0,0 @@ -from sqlmodel import Session, create_engine, select - -from ...conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.insert import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - with Session(mod.engine) as session: - heroes = session.exec(select(mod.Hero)).all() - heroes_by_name = {hero.name: hero for hero in heroes} - deadpond = heroes_by_name["Deadpond"] - spider_boy = heroes_by_name["Spider-Boy"] - rusty_man = heroes_by_name["Rusty-Man"] - assert deadpond.name == "Deadpond" - assert deadpond.age is None - assert deadpond.id is not None - assert deadpond.secret_name == "Dive Wilson" - assert spider_boy.name == "Spider-Boy" - assert spider_boy.age is None - assert spider_boy.id is not None - assert spider_boy.secret_name == "Pedro Parqueador" - assert rusty_man.name == "Rusty-Man" - assert rusty_man.age == 48 - assert rusty_man.id is not None - assert rusty_man.secret_name == "Tommy Sharp" From e23931290c233b133966c5e7754157bec20fe442 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:21:38 +0100 Subject: [PATCH 31/79] Simplify tests for `docs_src.tutorial.insert.tutorial002*` --- .../test_insert/test_tutorial002.py | 20 +++++++++++-- .../test_insert/test_tutorial002_py310.py | 30 ------------------- 2 files changed, 18 insertions(+), 32 deletions(-) delete mode 100644 tests/test_tutorial/test_insert/test_tutorial002_py310.py diff --git a/tests/test_tutorial/test_insert/test_tutorial002.py b/tests/test_tutorial/test_insert/test_tutorial002.py index c450ec044d..0cee7ef3b1 100644 --- a/tests/test_tutorial/test_insert/test_tutorial002.py +++ b/tests/test_tutorial/test_insert/test_tutorial002.py @@ -1,11 +1,27 @@ +import importlib +from types import ModuleType + +import pytest from sqlmodel import Session, create_engine, select +from ...conftest import needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.insert import tutorial002 as mod +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.insert.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) + return mod + + +def test_tutorial(mod: ModuleType): mod.main() with Session(mod.engine) as session: heroes = session.exec(select(mod.Hero)).all() diff --git a/tests/test_tutorial/test_insert/test_tutorial002_py310.py b/tests/test_tutorial/test_insert/test_tutorial002_py310.py deleted file mode 100644 index fb62810baf..0000000000 --- a/tests/test_tutorial/test_insert/test_tutorial002_py310.py +++ /dev/null @@ -1,30 +0,0 @@ -from sqlmodel import Session, create_engine, select - -from ...conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.insert import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - with Session(mod.engine) as session: - heroes = session.exec(select(mod.Hero)).all() - heroes_by_name = {hero.name: hero for hero in heroes} - deadpond = heroes_by_name["Deadpond"] - spider_boy = heroes_by_name["Spider-Boy"] - rusty_man = heroes_by_name["Rusty-Man"] - assert deadpond.name == "Deadpond" - assert deadpond.age is None - assert deadpond.id is not None - assert deadpond.secret_name == "Dive Wilson" - assert spider_boy.name == "Spider-Boy" - assert spider_boy.age is None - assert spider_boy.id is not None - assert spider_boy.secret_name == "Pedro Parqueador" - assert rusty_man.name == "Rusty-Man" - assert rusty_man.age == 48 - assert rusty_man.id is not None - assert rusty_man.secret_name == "Tommy Sharp" From 8660f2c5561579faa87879e534ad15b00cc7b7c2 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:23:01 +0100 Subject: [PATCH 32/79] Simplify tests for `docs_src.tutorial.insert.tutorial003*` --- .../test_insert/test_tutorial003.py | 20 +++++++++++-- .../test_insert/test_tutorial003_py310.py | 30 ------------------- 2 files changed, 18 insertions(+), 32 deletions(-) delete mode 100644 tests/test_tutorial/test_insert/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_insert/test_tutorial003.py b/tests/test_tutorial/test_insert/test_tutorial003.py index df2112b25a..7f80585875 100644 --- a/tests/test_tutorial/test_insert/test_tutorial003.py +++ b/tests/test_tutorial/test_insert/test_tutorial003.py @@ -1,11 +1,27 @@ +import importlib +from types import ModuleType + +import pytest from sqlmodel import Session, create_engine, select +from ...conftest import needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.insert import tutorial003 as mod +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.insert.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) + return mod + + +def test_tutorial(mod: ModuleType): mod.main() with Session(mod.engine) as session: heroes = session.exec(select(mod.Hero)).all() diff --git a/tests/test_tutorial/test_insert/test_tutorial003_py310.py b/tests/test_tutorial/test_insert/test_tutorial003_py310.py deleted file mode 100644 index 5bca713e60..0000000000 --- a/tests/test_tutorial/test_insert/test_tutorial003_py310.py +++ /dev/null @@ -1,30 +0,0 @@ -from sqlmodel import Session, create_engine, select - -from ...conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.insert import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - with Session(mod.engine) as session: - heroes = session.exec(select(mod.Hero)).all() - heroes_by_name = {hero.name: hero for hero in heroes} - deadpond = heroes_by_name["Deadpond"] - spider_boy = heroes_by_name["Spider-Boy"] - rusty_man = heroes_by_name["Rusty-Man"] - assert deadpond.name == "Deadpond" - assert deadpond.age is None - assert deadpond.id is not None - assert deadpond.secret_name == "Dive Wilson" - assert spider_boy.name == "Spider-Boy" - assert spider_boy.age is None - assert spider_boy.id is not None - assert spider_boy.secret_name == "Pedro Parqueador" - assert rusty_man.name == "Rusty-Man" - assert rusty_man.age == 48 - assert rusty_man.id is not None - assert rusty_man.secret_name == "Tommy Sharp" From 71004f0eca97807a98fd0baec26b94adb6fa615b Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:25:56 +0100 Subject: [PATCH 33/79] Simplify tests for `docs_src.tutorial.offset_and_limit.tutorial001*` --- .../test_limit_and_offset/test_tutorial001.py | 36 +++++++++++-------- .../test_tutorial001_py310.py | 35 ------------------ 2 files changed, 22 insertions(+), 49 deletions(-) delete mode 100644 tests/test_tutorial/test_limit_and_offset/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial001.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial001.py index 244f91083f..d33713cde3 100644 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial001.py +++ b/tests/test_tutorial/test_limit_and_offset/test_tutorial001.py @@ -1,8 +1,25 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.offset_and_limit.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -20,15 +37,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial001_py310.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial001_py310.py deleted file mode 100644 index 4f4974c853..0000000000 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial001_py310.py +++ /dev/null @@ -1,35 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - [ - {"id": 1, "name": "Deadpond", "secret_name": "Dive Wilson", "age": None}, - { - "id": 2, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - }, - {"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}, - ] - ] -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 2bb99bc1533a01953ba4abd1565fdc68fa2726a2 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:27:42 +0100 Subject: [PATCH 34/79] Simplify tests for `docs_src.tutorial.offset_and_limit.tutorial002*` --- .../test_limit_and_offset/test_tutorial002.py | 36 +++++++++++-------- .../test_tutorial002_py310.py | 35 ------------------ 2 files changed, 22 insertions(+), 49 deletions(-) delete mode 100644 tests/test_tutorial/test_limit_and_offset/test_tutorial002_py310.py diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial002.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial002.py index e9dee0cb35..c73f701cd1 100644 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial002.py +++ b/tests/test_tutorial/test_limit_and_offset/test_tutorial002.py @@ -1,8 +1,25 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.offset_and_limit.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -20,15 +37,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial002 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial002_py310.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial002_py310.py deleted file mode 100644 index 1f86d1960e..0000000000 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial002_py310.py +++ /dev/null @@ -1,35 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - [ - { - "id": 4, - "name": "Tarantula", - "secret_name": "Natalia Roman-on", - "age": 32, - }, - {"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}, - {"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}, - ] - ] -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 49310e56aaadc442b23fdde1510497d1772b21eb Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:29:20 +0100 Subject: [PATCH 35/79] Simplify tests for `docs_src.tutorial.offset_and_limit.tutorial003*` --- .../test_limit_and_offset/test_tutorial003.py | 36 +++++++++++-------- .../test_tutorial003_py310.py | 33 ----------------- 2 files changed, 22 insertions(+), 47 deletions(-) delete mode 100644 tests/test_tutorial/test_limit_and_offset/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial003.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial003.py index 7192f7ef43..a33cf49f06 100644 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial003.py +++ b/tests/test_tutorial/test_limit_and_offset/test_tutorial003.py @@ -1,8 +1,25 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.offset_and_limit.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -18,15 +35,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial003 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial003_py310.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial003_py310.py deleted file mode 100644 index 993999156d..0000000000 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial003_py310.py +++ /dev/null @@ -1,33 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - [ - { - "id": 7, - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - } - ] - ] -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From b3313577edacc1d1c2bd0c249d8207da0f855c7d Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:40:51 +0100 Subject: [PATCH 36/79] Simplify tests for `docs_src.tutorial.offset_and_limit.tutorial004*` --- .../test_limit_and_offset/test_tutorial004.py | 27 ++++++++++++------- .../test_tutorial004_py310.py | 27 ------------------- 2 files changed, 17 insertions(+), 37 deletions(-) delete mode 100644 tests/test_tutorial/test_limit_and_offset/test_tutorial004_py310.py diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial004.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial004.py index eb15a1560e..15322c4089 100644 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial004.py +++ b/tests/test_tutorial/test_limit_and_offset/test_tutorial004.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial004 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial004", + pytest.param("tutorial004_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.offset_and_limit.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ [ {"name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36, "id": 6}, diff --git a/tests/test_tutorial/test_limit_and_offset/test_tutorial004_py310.py b/tests/test_tutorial/test_limit_and_offset/test_tutorial004_py310.py deleted file mode 100644 index 4ca736589f..0000000000 --- a/tests/test_tutorial/test_limit_and_offset/test_tutorial004_py310.py +++ /dev/null @@ -1,27 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.offset_and_limit import tutorial004_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - [ - {"name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36, "id": 6}, - {"name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48, "id": 3}, - ] - ] - ] From c78ec3b1d28a20f168227213b6d39eff1637cff4 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:43:07 +0100 Subject: [PATCH 37/79] Simplify tests for `docs_src.tutorial.many_to_many.tutorial001*` --- .../test_many_to_many/test_tutorial001.py | 37 ++++++++------ .../test_tutorial001_py310.py | 50 ------------------- .../test_tutorial001_py39.py | 50 ------------------- 3 files changed, 23 insertions(+), 114 deletions(-) delete mode 100644 tests/test_tutorial/test_many_to_many/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_many_to_many/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial001.py b/tests/test_tutorial/test_many_to_many/test_tutorial001.py index 70bfe9a649..b84626d9cf 100644 --- a/tests/test_tutorial/test_many_to_many/test_tutorial001.py +++ b/tests/test_tutorial/test_many_to_many/test_tutorial001.py @@ -1,8 +1,26 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.many_to_many.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -35,15 +53,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial001_py310.py b/tests/test_tutorial/test_many_to_many/test_tutorial001_py310.py deleted file mode 100644 index bf31d9c695..0000000000 --- a/tests/test_tutorial/test_many_to_many/test_tutorial001_py310.py +++ /dev/null @@ -1,50 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Deadpond:", - {"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}, - ], - [ - "Deadpond teams:", - [ - {"id": 1, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - ], - [ - "Rusty-Man:", - {"id": 2, "secret_name": "Tommy Sharp", "age": 48, "name": "Rusty-Man"}, - ], - [ - "Rusty-Man Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], - [ - "Spider-Boy:", - {"id": 3, "secret_name": "Pedro Parqueador", "age": None, "name": "Spider-Boy"}, - ], - [ - "Spider-Boy Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial001_py39.py b/tests/test_tutorial/test_many_to_many/test_tutorial001_py39.py deleted file mode 100644 index cb7a4d8456..0000000000 --- a/tests/test_tutorial/test_many_to_many/test_tutorial001_py39.py +++ /dev/null @@ -1,50 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Deadpond:", - {"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}, - ], - [ - "Deadpond teams:", - [ - {"id": 1, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - ], - [ - "Rusty-Man:", - {"id": 2, "secret_name": "Tommy Sharp", "age": 48, "name": "Rusty-Man"}, - ], - [ - "Rusty-Man Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], - [ - "Spider-Boy:", - {"id": 3, "secret_name": "Pedro Parqueador", "age": None, "name": "Spider-Boy"}, - ], - [ - "Spider-Boy Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial001_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From c6c827eb38477014b150da950273517e187a326e Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:44:51 +0100 Subject: [PATCH 38/79] Simplify tests for `docs_src.tutorial.many_to_many.tutorial002*` --- .../test_many_to_many/test_tutorial002.py | 37 +++++---- .../test_tutorial002_py310.py | 77 ------------------- .../test_tutorial002_py39.py | 77 ------------------- 3 files changed, 23 insertions(+), 168 deletions(-) delete mode 100644 tests/test_tutorial/test_many_to_many/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_many_to_many/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial002.py b/tests/test_tutorial/test_many_to_many/test_tutorial002.py index d4d7d95e89..b5562f416d 100644 --- a/tests/test_tutorial/test_many_to_many/test_tutorial002.py +++ b/tests/test_tutorial/test_many_to_many/test_tutorial002.py @@ -1,8 +1,26 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.many_to_many.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -62,15 +80,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial002 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial002_py310.py b/tests/test_tutorial/test_many_to_many/test_tutorial002_py310.py deleted file mode 100644 index ad7c892fcd..0000000000 --- a/tests/test_tutorial/test_many_to_many/test_tutorial002_py310.py +++ /dev/null @@ -1,77 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Deadpond:", - {"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}, - ], - [ - "Deadpond teams:", - [ - {"id": 1, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - ], - [ - "Rusty-Man:", - {"id": 2, "secret_name": "Tommy Sharp", "age": 48, "name": "Rusty-Man"}, - ], - [ - "Rusty-Man Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], - [ - "Spider-Boy:", - {"id": 3, "secret_name": "Pedro Parqueador", "age": None, "name": "Spider-Boy"}, - ], - [ - "Spider-Boy Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], - [ - "Updated Spider-Boy's Teams:", - [ - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - {"id": 1, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - ], - ], - [ - "Z-Force heroes:", - [ - {"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}, - { - "id": 3, - "secret_name": "Pedro Parqueador", - "age": None, - "name": "Spider-Boy", - }, - ], - ], - [ - "Reverted Z-Force's heroes:", - [{"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}], - ], - [ - "Reverted Spider-Boy's teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial002_py39.py b/tests/test_tutorial/test_many_to_many/test_tutorial002_py39.py deleted file mode 100644 index c0df48d73c..0000000000 --- a/tests/test_tutorial/test_many_to_many/test_tutorial002_py39.py +++ /dev/null @@ -1,77 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Deadpond:", - {"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}, - ], - [ - "Deadpond teams:", - [ - {"id": 1, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - ], - [ - "Rusty-Man:", - {"id": 2, "secret_name": "Tommy Sharp", "age": 48, "name": "Rusty-Man"}, - ], - [ - "Rusty-Man Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], - [ - "Spider-Boy:", - {"id": 3, "secret_name": "Pedro Parqueador", "age": None, "name": "Spider-Boy"}, - ], - [ - "Spider-Boy Teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], - [ - "Updated Spider-Boy's Teams:", - [ - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - {"id": 1, "name": "Z-Force", "headquarters": "Sister Margaret's Bar"}, - ], - ], - [ - "Z-Force heroes:", - [ - {"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}, - { - "id": 3, - "secret_name": "Pedro Parqueador", - "age": None, - "name": "Spider-Boy", - }, - ], - ], - [ - "Reverted Z-Force's heroes:", - [{"id": 1, "secret_name": "Dive Wilson", "age": None, "name": "Deadpond"}], - ], - [ - "Reverted Spider-Boy's teams:", - [{"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}], - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial002_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 373769dd522fbc39915fa463ca6395a6254998e5 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:47:51 +0100 Subject: [PATCH 39/79] Simplify tests for `docs_src.tutorial.many_to_many.tutorial003*` --- .../test_many_to_many/test_tutorial003.py | 37 ++++++---- .../test_tutorial003_py310.py | 73 ------------------- .../test_tutorial003_py39.py | 73 ------------------- 3 files changed, 23 insertions(+), 160 deletions(-) delete mode 100644 tests/test_tutorial/test_many_to_many/test_tutorial003_py310.py delete mode 100644 tests/test_tutorial/test_many_to_many/test_tutorial003_py39.py diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial003.py b/tests/test_tutorial/test_many_to_many/test_tutorial003.py index 35489b01ce..ad1168e3ba 100644 --- a/tests/test_tutorial/test_many_to_many/test_tutorial003.py +++ b/tests/test_tutorial/test_many_to_many/test_tutorial003.py @@ -1,8 +1,26 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py39", marks=needs_py39), + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.many_to_many.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -58,15 +76,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial003 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial003_py310.py b/tests/test_tutorial/test_many_to_many/test_tutorial003_py310.py deleted file mode 100644 index 78a699c741..0000000000 --- a/tests/test_tutorial/test_many_to_many/test_tutorial003_py310.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Z-Force hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "id": 1, "age": None}, - "is training:", - False, - ], - [ - "Preventers hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "id": 1, "age": None}, - "is training:", - True, - ], - [ - "Preventers hero:", - {"name": "Spider-Boy", "secret_name": "Pedro Parqueador", "id": 2, "age": None}, - "is training:", - True, - ], - [ - "Preventers hero:", - {"name": "Rusty-Man", "secret_name": "Tommy Sharp", "id": 3, "age": 48}, - "is training:", - False, - ], - [ - "Updated Spider-Boy's Teams:", - [ - {"team_id": 2, "is_training": True, "hero_id": 2}, - {"team_id": 1, "is_training": True, "hero_id": 2}, - ], - ], - [ - "Z-Force heroes:", - [ - {"team_id": 1, "is_training": False, "hero_id": 1}, - {"team_id": 1, "is_training": True, "hero_id": 2}, - ], - ], - [ - "Spider-Boy team:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - "is training:", - False, - ], - [ - "Spider-Boy team:", - {"headquarters": "Sister Margaret's Bar", "id": 1, "name": "Z-Force"}, - "is training:", - True, - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_many_to_many/test_tutorial003_py39.py b/tests/test_tutorial/test_many_to_many/test_tutorial003_py39.py deleted file mode 100644 index 8fed921d82..0000000000 --- a/tests/test_tutorial/test_many_to_many/test_tutorial003_py39.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Z-Force hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "id": 1, "age": None}, - "is training:", - False, - ], - [ - "Preventers hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "id": 1, "age": None}, - "is training:", - True, - ], - [ - "Preventers hero:", - {"name": "Spider-Boy", "secret_name": "Pedro Parqueador", "id": 2, "age": None}, - "is training:", - True, - ], - [ - "Preventers hero:", - {"name": "Rusty-Man", "secret_name": "Tommy Sharp", "id": 3, "age": 48}, - "is training:", - False, - ], - [ - "Updated Spider-Boy's Teams:", - [ - {"team_id": 2, "is_training": True, "hero_id": 2}, - {"team_id": 1, "is_training": True, "hero_id": 2}, - ], - ], - [ - "Z-Force heroes:", - [ - {"team_id": 1, "is_training": False, "hero_id": 1}, - {"team_id": 1, "is_training": True, "hero_id": 2}, - ], - ], - [ - "Spider-Boy team:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - "is training:", - False, - ], - [ - "Spider-Boy team:", - {"headquarters": "Sister Margaret's Bar", "id": 1, "name": "Z-Force"}, - "is training:", - True, - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.many_to_many import tutorial003_py39 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From bc893d64b5fb83456caf0e735b6cc132c99dcbc3 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:49:37 +0100 Subject: [PATCH 40/79] Simplify tests for `docs_src.tutorial.one.tutorial001*` --- .../test_one/test_tutorial001.py | 27 ++++++++++------- .../test_one/test_tutorial001_py310.py | 30 ------------------- 2 files changed, 17 insertions(+), 40 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial001.py b/tests/test_tutorial/test_one/test_tutorial001.py index deb133b985..2f6f1c9e89 100644 --- a/tests/test_tutorial/test_one/test_tutorial001.py +++ b/tests/test_tutorial/test_one/test_tutorial001.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial001 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Hero:", { diff --git a/tests/test_tutorial/test_one/test_tutorial001_py310.py b/tests/test_tutorial/test_one/test_tutorial001_py310.py deleted file mode 100644 index 6de878087f..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial001_py310.py +++ /dev/null @@ -1,30 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Hero:", - { - "name": "Tarantula", - "secret_name": "Natalia Roman-on", - "age": 32, - "id": 4, - }, - ] - ] From 1a597bb193c34fb17bf47096da8590377ddab26f Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:51:18 +0100 Subject: [PATCH 41/79] Simplify tests for `docs_src.tutorial.one.tutorial002*` --- .../test_one/test_tutorial002.py | 27 ++++++++++++------- .../test_one/test_tutorial002_py310.py | 20 -------------- 2 files changed, 17 insertions(+), 30 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial002_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial002.py b/tests/test_tutorial/test_one/test_tutorial002.py index 7106564122..267ead8939 100644 --- a/tests/test_tutorial/test_one/test_tutorial002.py +++ b/tests/test_tutorial/test_one/test_tutorial002.py @@ -1,19 +1,26 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial002 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [["Hero:", None]] +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [["Hero:", None]] diff --git a/tests/test_tutorial/test_one/test_tutorial002_py310.py b/tests/test_tutorial/test_one/test_tutorial002_py310.py deleted file mode 100644 index afdfc54593..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial002_py310.py +++ /dev/null @@ -1,20 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [["Hero:", None]] From c491cde492b3a8be2e771cd78e428db6ec65ea7d Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:52:36 +0100 Subject: [PATCH 42/79] Simplify tests for `docs_src.tutorial.one.tutorial003*` --- .../test_one/test_tutorial003.py | 27 ++++++++++++------- .../test_one/test_tutorial003_py310.py | 25 ----------------- 2 files changed, 17 insertions(+), 35 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial003.py b/tests/test_tutorial/test_one/test_tutorial003.py index 40a73d042b..de2e529aea 100644 --- a/tests/test_tutorial/test_one/test_tutorial003.py +++ b/tests/test_tutorial/test_one/test_tutorial003.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial003 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Hero:", {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, diff --git a/tests/test_tutorial/test_one/test_tutorial003_py310.py b/tests/test_tutorial/test_one/test_tutorial003_py310.py deleted file mode 100644 index 8eb8b8612b..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial003_py310.py +++ /dev/null @@ -1,25 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, - ] - ] From c0bcf14e1be22216b4de80a843ac22705886d221 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 19:56:29 +0100 Subject: [PATCH 43/79] Simplify tests for `docs_src.tutorial.one.tutorial004*` --- .../test_one/test_tutorial004.py | 30 ++++++++------ .../test_one/test_tutorial004_py310.py | 41 ------------------- 2 files changed, 18 insertions(+), 53 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial004_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial004.py b/tests/test_tutorial/test_one/test_tutorial004.py index 5bd652577d..9df91fbb41 100644 --- a/tests/test_tutorial/test_one/test_tutorial004.py +++ b/tests/test_tutorial/test_one/test_tutorial004.py @@ -1,17 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType import pytest from sqlalchemy.exc import MultipleResultsFound from sqlmodel import Session, create_engine, delete -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial004 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial004", + pytest.param("tutorial004_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) + return mod + + +def test_tutorial(print_mock: PrintMock, mod: ModuleType): with pytest.raises(MultipleResultsFound): mod.main() with Session(mod.engine) as session: @@ -21,13 +32,8 @@ def test_tutorial(clear_sqlmodel): session.add(mod.Hero(name="Test Hero", secret_name="Secret Test Hero", age=24)) session.commit() - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.select_heroes() - assert calls == [ + mod.select_heroes() + assert print_mock.calls == [ [ "Hero:", { diff --git a/tests/test_tutorial/test_one/test_tutorial004_py310.py b/tests/test_tutorial/test_one/test_tutorial004_py310.py deleted file mode 100644 index cf365a4fe5..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial004_py310.py +++ /dev/null @@ -1,41 +0,0 @@ -from unittest.mock import patch - -import pytest -from sqlalchemy.exc import MultipleResultsFound -from sqlmodel import Session, create_engine, delete - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial004_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - with pytest.raises(MultipleResultsFound): - mod.main() - with Session(mod.engine) as session: - # TODO: create delete() function - # TODO: add overloads for .exec() with delete object - session.exec(delete(mod.Hero)) - session.add(mod.Hero(name="Test Hero", secret_name="Secret Test Hero", age=24)) - session.commit() - - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.select_heroes() - assert calls == [ - [ - "Hero:", - { - "id": 1, - "name": "Test Hero", - "secret_name": "Secret Test Hero", - "age": 24, - }, - ] - ] From efc9cf01b6b893acc8c0d7086a7cdbf583b71b8a Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:00:14 +0100 Subject: [PATCH 44/79] Simplify tests for `docs_src.tutorial.one.tutorial005*` --- .../test_one/test_tutorial005.py | 30 ++++++++------ .../test_one/test_tutorial005_py310.py | 41 ------------------- 2 files changed, 18 insertions(+), 53 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial005_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial005.py b/tests/test_tutorial/test_one/test_tutorial005.py index 0c25ffa39d..fa569020a1 100644 --- a/tests/test_tutorial/test_one/test_tutorial005.py +++ b/tests/test_tutorial/test_one/test_tutorial005.py @@ -1,17 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType import pytest from sqlalchemy.exc import NoResultFound from sqlmodel import Session, create_engine, delete -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial005 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial005", + pytest.param("tutorial005_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) + return mod + + +def test_tutorial(print_mock: PrintMock, mod: ModuleType): with pytest.raises(NoResultFound): mod.main() with Session(mod.engine) as session: @@ -21,13 +32,8 @@ def test_tutorial(clear_sqlmodel): session.add(mod.Hero(name="Test Hero", secret_name="Secret Test Hero", age=24)) session.commit() - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.select_heroes() - assert calls == [ + mod.select_heroes() + assert print_mock.calls == [ [ "Hero:", { diff --git a/tests/test_tutorial/test_one/test_tutorial005_py310.py b/tests/test_tutorial/test_one/test_tutorial005_py310.py deleted file mode 100644 index f1fce7d764..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial005_py310.py +++ /dev/null @@ -1,41 +0,0 @@ -from unittest.mock import patch - -import pytest -from sqlalchemy.exc import NoResultFound -from sqlmodel import Session, create_engine, delete - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial005_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - with pytest.raises(NoResultFound): - mod.main() - with Session(mod.engine) as session: - # TODO: create delete() function - # TODO: add overloads for .exec() with delete object - session.exec(delete(mod.Hero)) - session.add(mod.Hero(name="Test Hero", secret_name="Secret Test Hero", age=24)) - session.commit() - - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.select_heroes() - assert calls == [ - [ - "Hero:", - { - "id": 1, - "name": "Test Hero", - "secret_name": "Secret Test Hero", - "age": 24, - }, - ] - ] From 4751497b77966cf646cb44f5fcc5324c4080171e Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:01:29 +0100 Subject: [PATCH 45/79] Simplify tests for `docs_src.tutorial.one.tutorial006*` --- .../test_one/test_tutorial006.py | 27 ++++++++++++------- .../test_one/test_tutorial006_py310.py | 25 ----------------- 2 files changed, 17 insertions(+), 35 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial006_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial006.py b/tests/test_tutorial/test_one/test_tutorial006.py index 01c1af4602..1c6c663dc5 100644 --- a/tests/test_tutorial/test_one/test_tutorial006.py +++ b/tests/test_tutorial/test_one/test_tutorial006.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial006 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial006", + pytest.param("tutorial006_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Hero:", {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, diff --git a/tests/test_tutorial/test_one/test_tutorial006_py310.py b/tests/test_tutorial/test_one/test_tutorial006_py310.py deleted file mode 100644 index ad8577c7ae..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial006_py310.py +++ /dev/null @@ -1,25 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial006_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, - ] - ] From f242b518419fade4a2aa663e8ab93c57bccf3bce Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:02:25 +0100 Subject: [PATCH 46/79] Simplify tests for `docs_src.tutorial.one.tutorial007*` --- .../test_one/test_tutorial007.py | 27 ++++++++++++------- .../test_one/test_tutorial007_py310.py | 25 ----------------- 2 files changed, 17 insertions(+), 35 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial007_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial007.py b/tests/test_tutorial/test_one/test_tutorial007.py index e8b984b050..ca4a5310a5 100644 --- a/tests/test_tutorial/test_one/test_tutorial007.py +++ b/tests/test_tutorial/test_one/test_tutorial007.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial007 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial007", + pytest.param("tutorial007_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Hero:", {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, diff --git a/tests/test_tutorial/test_one/test_tutorial007_py310.py b/tests/test_tutorial/test_one/test_tutorial007_py310.py deleted file mode 100644 index 15b2306fc6..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial007_py310.py +++ /dev/null @@ -1,25 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial007_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, - ] - ] From e7bf6c0d866339746a228a16f694cd6eb3facefa Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:03:22 +0100 Subject: [PATCH 47/79] Simplify tests for `docs_src.tutorial.one.tutorial008*` --- .../test_one/test_tutorial008.py | 27 ++++++++++++------- .../test_one/test_tutorial008_py310.py | 25 ----------------- 2 files changed, 17 insertions(+), 35 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial008_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial008.py b/tests/test_tutorial/test_one/test_tutorial008.py index e0ea766f37..da451fbaa2 100644 --- a/tests/test_tutorial/test_one/test_tutorial008.py +++ b/tests/test_tutorial/test_one/test_tutorial008.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial008 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial008", + pytest.param("tutorial008_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Hero:", {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, diff --git a/tests/test_tutorial/test_one/test_tutorial008_py310.py b/tests/test_tutorial/test_one/test_tutorial008_py310.py deleted file mode 100644 index c7d1fe55c9..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial008_py310.py +++ /dev/null @@ -1,25 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial008_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Hero:", - {"name": "Deadpond", "secret_name": "Dive Wilson", "age": None, "id": 1}, - ] - ] From b15690b470306967546345c441debf276cf0f167 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:04:41 +0100 Subject: [PATCH 48/79] Simplify tests for `docs_src.tutorial.one.tutorial009*` --- .../test_one/test_tutorial009.py | 27 ++++++++++++------- .../test_one/test_tutorial009_py310.py | 20 -------------- 2 files changed, 17 insertions(+), 30 deletions(-) delete mode 100644 tests/test_tutorial/test_one/test_tutorial009_py310.py diff --git a/tests/test_tutorial/test_one/test_tutorial009.py b/tests/test_tutorial/test_one/test_tutorial009.py index 63e01fe741..0cf3a6267f 100644 --- a/tests/test_tutorial/test_one/test_tutorial009.py +++ b/tests/test_tutorial/test_one/test_tutorial009.py @@ -1,19 +1,26 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial009 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial009", + pytest.param("tutorial009_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.one.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [["Hero:", None]] +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [["Hero:", None]] diff --git a/tests/test_tutorial/test_one/test_tutorial009_py310.py b/tests/test_tutorial/test_one/test_tutorial009_py310.py deleted file mode 100644 index 8e9fda5f73..0000000000 --- a/tests/test_tutorial/test_one/test_tutorial009_py310.py +++ /dev/null @@ -1,20 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.one import tutorial009_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [["Hero:", None]] From 3b00b3d702962aa6d5039dddcea05c85c24dc66c Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:08:10 +0100 Subject: [PATCH 49/79] Simplify tests for `docs_src.tutorial.relationship_attributes.back_populates.tutorial001*` --- .../test_back_populates/test_tutorial001.py | 42 ++- .../test_tutorial001_py310.py | 290 ------------------ .../test_tutorial001_py39.py | 290 ------------------ 3 files changed, 25 insertions(+), 597 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py index 30ec9fdc36..f49c516911 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py +++ b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py @@ -1,10 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType import pytest from sqlalchemy.exc import SAWarning from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.back_populates.{request.param}" + ) + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -272,18 +291,7 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial001 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - with pytest.warns(SAWarning): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + with pytest.warns(SAWarning): + mod.main() + assert print_mock.calls == expected_calls \ No newline at end of file diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py310.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py310.py deleted file mode 100644 index 384056ad7b..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py310.py +++ /dev/null @@ -1,290 +0,0 @@ -from unittest.mock import patch - -import pytest -from sqlalchemy.exc import SAWarning -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Preventers heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Hero Spider-Boy:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - ], - [ - "Preventers Team Heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Spider-Boy without team:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes again:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - ["After committing"], - [ - "Spider-Boy after commit:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes after commit:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial001_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - with pytest.warns(SAWarning): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py39.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py39.py deleted file mode 100644 index 0597a88e89..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001_py39.py +++ /dev/null @@ -1,290 +0,0 @@ -from unittest.mock import patch - -import pytest -from sqlalchemy.exc import SAWarning -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Preventers heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Hero Spider-Boy:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - ], - [ - "Preventers Team Heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Spider-Boy without team:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes again:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - ["After committing"], - [ - "Spider-Boy after commit:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes after commit:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial001_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - with pytest.warns(SAWarning): - mod.main() - assert calls == expected_calls From 75e91bbfd463c36ed75364c401455649d1eecb62 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:09:56 +0100 Subject: [PATCH 50/79] Simplify tests for `docs_src.tutorial.relationship_attributes.back_populates.tutorial002*` --- .../test_back_populates/test_tutorial002.py | 41 ++- .../test_tutorial002_py310.py | 280 ------------------ .../test_tutorial002_py39.py | 280 ------------------ 3 files changed, 25 insertions(+), 576 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002.py index 98c01a9d54..8ce54be46c 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002.py +++ b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002.py @@ -1,8 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.back_populates.{request.param}" + ) + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -263,17 +283,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial002 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py310.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py310.py deleted file mode 100644 index 50a891f310..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py310.py +++ /dev/null @@ -1,280 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"id": 3, "name": "Wakaland", "headquarters": "Wakaland Capital City"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Preventers heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Hero Spider-Boy:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team:", - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - [ - "Preventers Team Heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Spider-Boy without team:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes again:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - ["After committing"], - [ - "Spider-Boy after commit:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes after commit:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial002_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py39.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py39.py deleted file mode 100644 index 3da6ce4aac..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial002_py39.py +++ /dev/null @@ -1,280 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"id": 3, "name": "Wakaland", "headquarters": "Wakaland Capital City"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Preventers heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Hero Spider-Boy:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team:", - {"id": 2, "name": "Preventers", "headquarters": "Sharp Tower"}, - ], - [ - "Preventers Team Heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Spider-Boy without team:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes again:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - ["After committing"], - [ - "Spider-Boy after commit:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Preventers Team Heroes after commit:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial002_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From d1f190cc08771fc97b0f2be8bbdc905bfa4b21e6 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:33:22 +0100 Subject: [PATCH 51/79] Simplify tests for `docs_src.tutorial.relationship_attributes.back_populates.tutorial003*` --- .../test_back_populates/test_tutorial003.py | 25 ++++++++++++++++--- .../test_tutorial003_py310.py | 21 ---------------- .../test_tutorial003_py39.py | 21 ---------------- 3 files changed, 21 insertions(+), 46 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003.py index 2ed66f76ca..d30c71c3c2 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003.py +++ b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003.py @@ -1,15 +1,32 @@ +import importlib +from types import ModuleType + +import pytest from sqlalchemy import inspect from sqlalchemy.engine.reflection import Inspector from sqlmodel import create_engine +from ....conftest import needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial003 as mod, - ) +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py39", marks=needs_py39), + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.back_populates.{request.param}" + ) mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) + return mod + + +def test_tutorial(mod: ModuleType): mod.main() insp: Inspector = inspect(mod.engine) assert insp.has_table(str(mod.Hero.__tablename__)) diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py310.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py310.py deleted file mode 100644 index 82e0c1c03b..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py310.py +++ /dev/null @@ -1,21 +0,0 @@ -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ....conftest import needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial003_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) - assert insp.has_table(str(mod.Weapon.__tablename__)) - assert insp.has_table(str(mod.Power.__tablename__)) - assert insp.has_table(str(mod.Team.__tablename__)) diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py39.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py39.py deleted file mode 100644 index d6059cb485..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial003_py39.py +++ /dev/null @@ -1,21 +0,0 @@ -from sqlalchemy import inspect -from sqlalchemy.engine.reflection import Inspector -from sqlmodel import create_engine - -from ....conftest import needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.back_populates import ( - tutorial003_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - mod.main() - insp: Inspector = inspect(mod.engine) - assert insp.has_table(str(mod.Hero.__tablename__)) - assert insp.has_table(str(mod.Weapon.__tablename__)) - assert insp.has_table(str(mod.Power.__tablename__)) - assert insp.has_table(str(mod.Team.__tablename__)) From 8eda95fc58337fcc0a7181f03b2d13ecb6c37c5c Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:36:23 +0100 Subject: [PATCH 52/79] Simplify tests for `docs_src.tutorial.relationship_attributes.create_and_update_relationships.tutorial001*` --- .../test_tutorial001.py | 41 +++++--- .../test_tutorial001_py310.py | 99 ------------------- .../test_tutorial001_py39.py | 99 ------------------- 3 files changed, 25 insertions(+), 214 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001.py b/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001.py index 7ced57c835..0c6a229178 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001.py +++ b/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001.py @@ -1,8 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.create_and_update_relationships.{request.param}" + ) + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -82,17 +102,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.create_and_update_relationships import ( - tutorial001 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py310.py b/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py310.py deleted file mode 100644 index c239b6d55c..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py310.py +++ /dev/null @@ -1,99 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.create_and_update_relationships import ( - tutorial001_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py39.py b/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py39.py deleted file mode 100644 index c569eed0d5..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_create_and_update_relationships/test_tutorial001_py39.py +++ /dev/null @@ -1,99 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.create_and_update_relationships import ( - tutorial001_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 087f8cd81116f79828d073128a0b2942de30b037 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:39:01 +0100 Subject: [PATCH 53/79] Simplify tests for `docs_src.tutorial.relationship_attributes.define_relationship_attributes.tutorial001*` --- .../test_tutorial001.py | 41 ++++++++------ .../test_tutorial001_py310.py | 55 ------------------- .../test_tutorial001_py39.py | 55 ------------------- 3 files changed, 25 insertions(+), 126 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001.py b/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001.py index 14b38ca52e..96cf8bcc49 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001.py +++ b/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001.py @@ -1,8 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.define_relationship_attributes.{request.param}" + ) + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -38,17 +58,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.define_relationship_attributes import ( - tutorial001 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py310.py b/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py310.py deleted file mode 100644 index f595dcaa04..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py310.py +++ /dev/null @@ -1,55 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "name": "Deadpond", - "age": None, - "team_id": 1, - "id": 1, - "secret_name": "Dive Wilson", - }, - ], - [ - "Created hero:", - { - "name": "Rusty-Man", - "age": 48, - "team_id": 2, - "id": 2, - "secret_name": "Tommy Sharp", - }, - ], - [ - "Created hero:", - { - "name": "Spider-Boy", - "age": None, - "team_id": None, - "id": 3, - "secret_name": "Pedro Parqueador", - }, - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.define_relationship_attributes import ( - tutorial001_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py39.py b/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py39.py deleted file mode 100644 index d54c610d19..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_define_relationship_attributes/test_tutorial001_py39.py +++ /dev/null @@ -1,55 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "name": "Deadpond", - "age": None, - "team_id": 1, - "id": 1, - "secret_name": "Dive Wilson", - }, - ], - [ - "Created hero:", - { - "name": "Rusty-Man", - "age": 48, - "team_id": 2, - "id": 2, - "secret_name": "Tommy Sharp", - }, - ], - [ - "Created hero:", - { - "name": "Spider-Boy", - "age": None, - "team_id": None, - "id": 3, - "secret_name": "Pedro Parqueador", - }, - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.define_relationship_attributes import ( - tutorial001_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From edd5f48a709f8a682056085f25bc06b85a251327 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:41:24 +0100 Subject: [PATCH 54/79] Simplify tests for `docs_src.tutorial.relationship_attributes.cascade_delete_relationships.tutorial001*` --- .../test_tutorial001.py | 30 +++++--- .../test_tutorial001_py310.py | 73 ------------------- .../test_tutorial001_py39.py | 73 ------------------- 3 files changed, 19 insertions(+), 157 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001.py index 863a84eb1c..5e43f80c4c 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001.py +++ b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001.py @@ -1,24 +1,32 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial001 as mod, +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.cascade_delete_relationships.{request.param}" ) - mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Created hero:", { diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py310.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py310.py deleted file mode 100644 index 3262d2b244..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py310.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial001_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - "id": 1, - "age": None, - }, - ], - [ - "Created hero:", - { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - "id": 2, - "age": 48, - }, - ], - [ - "Created hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - "id": 3, - "age": None, - }, - ], - [ - "Updated hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - "id": 3, - "age": None, - }, - ], - [ - "Team Wakaland:", - {"name": "Wakaland", "id": 3, "headquarters": "Wakaland Capital City"}, - ], - [ - "Deleted team:", - {"name": "Wakaland", "id": 3, "headquarters": "Wakaland Capital City"}, - ], - ["Black Lion not found:", None], - ["Princess Sure-E not found:", None], - ] diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py39.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py39.py deleted file mode 100644 index 840c354e83..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial001_py39.py +++ /dev/null @@ -1,73 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial001_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - "id": 1, - "age": None, - }, - ], - [ - "Created hero:", - { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - "id": 2, - "age": 48, - }, - ], - [ - "Created hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - "id": 3, - "age": None, - }, - ], - [ - "Updated hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - "id": 3, - "age": None, - }, - ], - [ - "Team Wakaland:", - {"name": "Wakaland", "id": 3, "headquarters": "Wakaland Capital City"}, - ], - [ - "Deleted team:", - {"name": "Wakaland", "id": 3, "headquarters": "Wakaland Capital City"}, - ], - ["Black Lion not found:", None], - ["Princess Sure-E not found:", None], - ] From e689ae163c533a10e3d28321bbc5f64e94f5bfbd Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:42:41 +0100 Subject: [PATCH 55/79] Simplify tests for `docs_src.tutorial.relationship_attributes.cascade_delete_relationships.tutorial002*` --- .../test_tutorial002.py | 30 +++--- .../test_tutorial002_py310.py | 91 ------------------- .../test_tutorial002_py39.py | 91 ------------------- 3 files changed, 19 insertions(+), 193 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002.py index a7d7a26364..cb3907afd7 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002.py +++ b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002.py @@ -1,24 +1,32 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial002 as mod, +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.cascade_delete_relationships.{request.param}" ) - mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Created hero:", { diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py310.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py310.py deleted file mode 100644 index 5c755f3a29..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py310.py +++ /dev/null @@ -1,91 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial002_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Deleted team:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "age": 35, - "id": 4, - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": None, - }, - ], - [ - "Princess Sure-E has no team:", - { - "age": None, - "id": 5, - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": None, - }, - ], - ] diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py39.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py39.py deleted file mode 100644 index 9937f6da4c..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial002_py39.py +++ /dev/null @@ -1,91 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial002_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Deleted team:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "age": 35, - "id": 4, - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": None, - }, - ], - [ - "Princess Sure-E has no team:", - { - "age": None, - "id": 5, - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": None, - }, - ], - ] From ae924371270ba0f54293d4788b9f61f5169943db Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:43:53 +0100 Subject: [PATCH 56/79] Simplify tests for `docs_src.tutorial.relationship_attributes.cascade_delete_relationships.tutorial003*` --- .../test_tutorial003.py | 30 +++--- .../test_tutorial003_py310.py | 91 ------------------- .../test_tutorial003_py39.py | 91 ------------------- 3 files changed, 19 insertions(+), 193 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003.py index a3d3bc0f05..e063630f96 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003.py +++ b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003.py @@ -1,24 +1,32 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from tests.conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial003 as mod, +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py39", marks=needs_py39), + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.cascade_delete_relationships.{request.param}" ) - mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Created hero:", { diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py310.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py310.py deleted file mode 100644 index f9975f25f7..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py310.py +++ /dev/null @@ -1,91 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial003_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - }, - ], - [ - "Team Wakaland:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Deleted team:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "age": 35, - "id": 4, - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": None, - }, - ], - [ - "Princess Sure-E has no team:", - { - "age": None, - "id": 5, - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": None, - }, - ], - ] diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py39.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py39.py deleted file mode 100644 index b68bc6237d..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial003_py39.py +++ /dev/null @@ -1,91 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial003_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - }, - ], - [ - "Team Wakaland:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Deleted team:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "age": 35, - "id": 4, - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": None, - }, - ], - [ - "Princess Sure-E has no team:", - { - "age": None, - "id": 5, - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": None, - }, - ], - ] From 845e6c5d3e89ef957033601e8851c9dc965dc5c7 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:45:59 +0100 Subject: [PATCH 57/79] Simplify tests for `docs_src.tutorial.relationship_attributes.cascade_delete_relationships.tutorial004*` --- .../test_tutorial004.py | 47 ++++---- .../test_tutorial004_py310.py | 107 ------------------ .../test_tutorial004_py39.py | 107 ------------------ 3 files changed, 26 insertions(+), 235 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004.py index d5da12e6a5..8b6c101fb8 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004.py +++ b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004.py @@ -1,36 +1,41 @@ -from unittest.mock import patch +import importlib +from types import ModuleType import pytest from sqlalchemy.exc import IntegrityError from sqlmodel import Session, create_engine, select -from tests.conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial004 as mod, +@pytest.fixture( + name="mod", + params=[ + "tutorial004", + pytest.param("tutorial004_py39", marks=needs_py39), + pytest.param("tutorial004_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.cascade_delete_relationships.{request.param}" ) - mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.create_db_and_tables() - mod.create_heroes() - mod.select_deleted_heroes() - with Session(mod.engine) as session: - team = session.exec( - select(mod.Team).where(mod.Team.name == "Wakaland") - ).one() - team.heroes.clear() - session.add(team) - session.commit() - mod.delete_team() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.create_db_and_tables() + mod.create_heroes() + mod.select_deleted_heroes() + with Session(mod.engine) as session: + team = session.exec(select(mod.Team).where(mod.Team.name == "Wakaland")).one() + team.heroes.clear() + session.add(team) + session.commit() + mod.delete_team() + assert print_mock.calls == [ [ "Created hero:", { diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py310.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py310.py deleted file mode 100644 index 3ce37700cf..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py310.py +++ /dev/null @@ -1,107 +0,0 @@ -from unittest.mock import patch - -import pytest -from sqlalchemy.exc import IntegrityError -from sqlmodel import Session, create_engine, select - -from tests.conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial004_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.create_db_and_tables() - mod.create_heroes() - mod.select_deleted_heroes() - with Session(mod.engine) as session: - team = session.exec( - select(mod.Team).where(mod.Team.name == "Wakaland") - ).one() - team.heroes.clear() - session.add(team) - session.commit() - mod.delete_team() - assert calls == [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "age": 35, - "id": 4, - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": 3, - }, - ], - [ - "Princess Sure-E has no team:", - { - "age": None, - "id": 5, - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": 3, - }, - ], - [ - "Deleted team:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - ] - - with pytest.raises(IntegrityError) as exc: - mod.main() - assert "FOREIGN KEY constraint failed" in str(exc.value) diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py39.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py39.py deleted file mode 100644 index 1c51fc0c90..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial004_py39.py +++ /dev/null @@ -1,107 +0,0 @@ -from unittest.mock import patch - -import pytest -from sqlalchemy.exc import IntegrityError -from sqlmodel import Session, create_engine, select - -from tests.conftest import get_testing_print_function, needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial004_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.create_db_and_tables() - mod.create_heroes() - mod.select_deleted_heroes() - with Session(mod.engine) as session: - team = session.exec( - select(mod.Team).where(mod.Team.name == "Wakaland") - ).one() - team.heroes.clear() - session.add(team) - session.commit() - mod.delete_team() - assert calls == [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "age": 35, - "id": 4, - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": 3, - }, - ], - [ - "Princess Sure-E has no team:", - { - "age": None, - "id": 5, - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": 3, - }, - ], - [ - "Deleted team:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - ] - - with pytest.raises(IntegrityError) as exc: - mod.main() - assert "FOREIGN KEY constraint failed" in str(exc.value) From 363abcee98ebad46ebdc361d126532267a3597c0 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:47:20 +0100 Subject: [PATCH 58/79] Simplify tests for `docs_src.tutorial.relationship_attributes.cascade_delete_relationships.tutorial005*` --- .../test_tutorial005.py | 30 +++--- .../test_tutorial005_py310.py | 95 ------------------- .../test_tutorial005_py39.py | 95 ------------------- 3 files changed, 19 insertions(+), 201 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005.py index a6a00608a9..273007770b 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005.py +++ b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005.py @@ -1,24 +1,32 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from tests.conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial005 as mod, +@pytest.fixture( + name="mod", + params=[ + "tutorial005", + pytest.param("tutorial005_py39", marks=needs_py39), + pytest.param("tutorial005_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.cascade_delete_relationships.{request.param}" ) - mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ "Created hero:", { diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py310.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py310.py deleted file mode 100644 index 54ad1b79de..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py310.py +++ /dev/null @@ -1,95 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from tests.conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial005_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - "id": 1, - "age": None, - }, - ], - [ - "Created hero:", - { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - "id": 2, - "age": 48, - }, - ], - [ - "Created hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - "id": 3, - "age": None, - }, - ], - [ - "Updated hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - "id": 3, - "age": None, - }, - ], - [ - "Team Wakaland:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Team with removed heroes:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Deleted team:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": None, - "id": 4, - "age": 35, - }, - ], - [ - "Princess Sure-E has no team:", - { - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": None, - "id": 5, - "age": None, - }, - ], - ] diff --git a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py39.py b/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py39.py deleted file mode 100644 index 8151ab9232..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_delete_records_relationship/test_tutorial005_py39.py +++ /dev/null @@ -1,95 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from tests.conftest import get_testing_print_function, needs_py39 - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.cascade_delete_relationships import ( - tutorial005_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - "Created hero:", - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "team_id": 1, - "id": 1, - "age": None, - }, - ], - [ - "Created hero:", - { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "team_id": 2, - "id": 2, - "age": 48, - }, - ], - [ - "Created hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": None, - "id": 3, - "age": None, - }, - ], - [ - "Updated hero:", - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "team_id": 2, - "id": 3, - "age": None, - }, - ], - [ - "Team Wakaland:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Team with removed heroes:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Deleted team:", - {"id": 3, "headquarters": "Wakaland Capital City", "name": "Wakaland"}, - ], - [ - "Black Lion has no team:", - { - "name": "Black Lion", - "secret_name": "Trevor Challa", - "team_id": None, - "id": 4, - "age": 35, - }, - ], - [ - "Princess Sure-E has no team:", - { - "name": "Princess Sure-E", - "secret_name": "Sure-E", - "team_id": None, - "id": 5, - "age": None, - }, - ], - ] From 636e227485189ca9e29e5f79382b60fa58155d65 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:49:08 +0100 Subject: [PATCH 59/79] Simplify tests for `docs_src.tutorial.relationship_attributes.read_relationships.tutorial001*` --- .../test_tutorial001.py | 41 ++++--- .../test_tutorial001_py310.py | 107 ------------------ .../test_tutorial001_py39.py | 107 ------------------ 3 files changed, 25 insertions(+), 230 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001.py b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001.py index 9fc70012d8..1b2caaa9c5 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001.py +++ b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001.py @@ -1,8 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py39", marks=needs_py39), + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.read_relationships.{request.param}" + ) + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -90,17 +110,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.read_relationships import ( - tutorial001 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py310.py b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py310.py deleted file mode 100644 index 9a4e3cc53b..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py310.py +++ /dev/null @@ -1,107 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Spider-Boy's team:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - ], - [ - "Spider-Boy's team again:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.read_relationships import ( - tutorial001_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py39.py b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py39.py deleted file mode 100644 index 6b23980665..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial001_py39.py +++ /dev/null @@ -1,107 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"headquarters": "Wakaland Capital City", "id": 3, "name": "Wakaland"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Spider-Boy's team:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - ], - [ - "Spider-Boy's team again:", - {"headquarters": "Sharp Tower", "id": 2, "name": "Preventers"}, - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.read_relationships import ( - tutorial001_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 36af468c8292c5bed0b609275e5dae8ac052020e Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:50:29 +0100 Subject: [PATCH 60/79] Simplify tests for `docs_src.tutorial.relationship_attributes.read_relationships.tutorial002*` --- .../test_tutorial002.py | 41 +++-- .../test_tutorial002_py310.py | 149 ------------------ .../test_tutorial002_py39.py | 149 ------------------ 3 files changed, 25 insertions(+), 314 deletions(-) delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py310.py delete mode 100644 tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py39.py diff --git a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002.py b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002.py index d827b1ff15..68ee2cc1d8 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002.py +++ b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002.py @@ -1,8 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ....conftest import get_testing_print_function +from ....conftest import PrintMock, needs_py39, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py39", marks=needs_py39), + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module( + f"docs_src.tutorial.relationship_attributes.read_relationships.{request.param}" + ) + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -132,17 +152,6 @@ ] -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.read_relationships import ( - tutorial002 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py310.py b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py310.py deleted file mode 100644 index 0cc9ae3326..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py310.py +++ /dev/null @@ -1,149 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"id": 3, "name": "Wakaland", "headquarters": "Wakaland Capital City"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Preventers heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Spider-Boy without team:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], -] - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.read_relationships import ( - tutorial002_py310 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py39.py b/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py39.py deleted file mode 100644 index 891f4ca6a9..0000000000 --- a/tests/test_tutorial/test_relationship_attributes/test_read_relationships/test_tutorial002_py39.py +++ /dev/null @@ -1,149 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ....conftest import get_testing_print_function, needs_py39 - -expected_calls = [ - [ - "Created hero:", - { - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "team_id": 1, - "name": "Deadpond", - }, - ], - [ - "Created hero:", - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - ], - [ - "Created hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], - [ - "Updated hero:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - ], - [ - "Team Wakaland:", - {"id": 3, "name": "Wakaland", "headquarters": "Wakaland Capital City"}, - ], - [ - "Preventers new hero:", - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - ], - [ - "Preventers new hero:", - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - ], - [ - "Preventers new hero:", - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - [ - "Preventers heroes:", - [ - { - "age": 48, - "id": 2, - "secret_name": "Tommy Sharp", - "team_id": 2, - "name": "Rusty-Man", - }, - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": 2, - "name": "Spider-Boy", - }, - { - "age": 32, - "id": 6, - "secret_name": "Natalia Roman-on", - "team_id": 2, - "name": "Tarantula", - }, - { - "age": 36, - "id": 7, - "secret_name": "Steve Weird", - "team_id": 2, - "name": "Dr. Weird", - }, - { - "age": 93, - "id": 8, - "secret_name": "Esteban Rogelios", - "team_id": 2, - "name": "Captain North America", - }, - ], - ], - [ - "Spider-Boy without team:", - { - "age": None, - "id": 3, - "secret_name": "Pedro Parqueador", - "team_id": None, - "name": "Spider-Boy", - }, - ], -] - - -@needs_py39 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.relationship_attributes.read_relationships import ( - tutorial002_py39 as mod, - ) - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 4b7e9a540357ebfce3c4318cd216190d1ac88be9 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 20:58:49 +0100 Subject: [PATCH 61/79] Simplify tests for `docs_src.tutorial.select.tutorial001*` and `docs_src.tutorial.select.tutorial002*` --- ...est_tutorial001_py310_tutorial002_py310.py | 57 ----------------- .../test_tutorial001_tutorial002.py | 64 +++++++++++-------- 2 files changed, 36 insertions(+), 85 deletions(-) delete mode 100644 tests/test_tutorial/test_select/test_tutorial001_py310_tutorial002_py310.py diff --git a/tests/test_tutorial/test_select/test_tutorial001_py310_tutorial002_py310.py b/tests/test_tutorial/test_select/test_tutorial001_py310_tutorial002_py310.py deleted file mode 100644 index 7521b6b717..0000000000 --- a/tests/test_tutorial/test_select/test_tutorial001_py310_tutorial002_py310.py +++ /dev/null @@ -1,57 +0,0 @@ -from typing import Any, Dict, List, Union -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -def check_calls(calls: List[List[Union[str, Dict[str, Any]]]]): - assert calls[0][0] == { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "age": None, - "id": 1, - } - assert calls[1][0] == { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": 2, - } - assert calls[2][0] == { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - "id": 3, - } - - -@needs_py310 -def test_tutorial_001(clear_sqlmodel): - from docs_src.tutorial.select import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) - - -@needs_py310 -def test_tutorial_002(clear_sqlmodel): - from docs_src.tutorial.select import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) diff --git a/tests/test_tutorial/test_select/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_select/test_tutorial001_tutorial002.py index fc8d546a19..a3f5e90d46 100644 --- a/tests/test_tutorial/test_select/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_select/test_tutorial001_tutorial002.py @@ -1,9 +1,11 @@ +import importlib +from types import ModuleType from typing import Any, Dict, List, Union -from unittest.mock import patch +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 def check_calls(calls: List[List[Union[str, Dict[str, Any]]]]): @@ -27,29 +29,35 @@ def check_calls(calls: List[List[Union[str, Dict[str, Any]]]]): } -def test_tutorial_001(clear_sqlmodel): - from docs_src.tutorial.select import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) - - -def test_tutorial_002(clear_sqlmodel): - from docs_src.tutorial.select import tutorial002 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) +@pytest.fixture(name="module") +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module(f"docs_src.tutorial.select.{request.param}") + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module + + +@pytest.mark.parametrize( + "module", + [ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial_001(print_mock: PrintMock, module: ModuleType): + module.main() + check_calls(print_mock.calls) + + +@pytest.mark.parametrize( + "module", + [ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial_002(print_mock: PrintMock, module: ModuleType): + module.main() + check_calls(print_mock.calls) From d834ede2901009bcd67ce23ddf25effd0df96f9d Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:02:38 +0100 Subject: [PATCH 62/79] Simplify tests for `docs_src.tutorial.select.tutorial003*` and `docs_src.tutorial.select.tutorial004*` --- ...est_tutorial003_py310_tutorial004_py310.py | 59 ------------------- .../test_tutorial003_tutorial004.py | 56 ++++++++++-------- 2 files changed, 32 insertions(+), 83 deletions(-) delete mode 100644 tests/test_tutorial/test_select/test_tutorial003_py310_tutorial004_py310.py diff --git a/tests/test_tutorial/test_select/test_tutorial003_py310_tutorial004_py310.py b/tests/test_tutorial/test_select/test_tutorial003_py310_tutorial004_py310.py deleted file mode 100644 index 0fa69df4a1..0000000000 --- a/tests/test_tutorial/test_select/test_tutorial003_py310_tutorial004_py310.py +++ /dev/null @@ -1,59 +0,0 @@ -from typing import Any, Dict, List, Union -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -def check_calls(calls: List[List[Union[str, Dict[str, Any]]]]): - assert calls[0][0] == [ - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "age": None, - "id": 1, - }, - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": 2, - }, - { - "name": "Rusty-Man", - "secret_name": "Tommy Sharp", - "age": 48, - "id": 3, - }, - ] - - -@needs_py310 -def test_tutorial_003(clear_sqlmodel): - from docs_src.tutorial.select import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) - - -@needs_py310 -def test_tutorial_002(clear_sqlmodel): - from docs_src.tutorial.select import tutorial004_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) diff --git a/tests/test_tutorial/test_select/test_tutorial003_tutorial004.py b/tests/test_tutorial/test_select/test_tutorial003_tutorial004.py index bfda0cb189..967ecdbd50 100644 --- a/tests/test_tutorial/test_select/test_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_select/test_tutorial003_tutorial004.py @@ -1,9 +1,11 @@ +import importlib +from types import ModuleType from typing import Any, Dict, List, Union -from unittest.mock import patch +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 def check_calls(calls: List[List[Union[str, Dict[str, Any]]]]): @@ -29,29 +31,35 @@ def check_calls(calls: List[List[Union[str, Dict[str, Any]]]]): ] -def test_tutorial_003(clear_sqlmodel): - from docs_src.tutorial.select import tutorial003 as mod +@pytest.fixture(name="module") +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module(f"docs_src.tutorial.select.{request.param}") + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - new_print = get_testing_print_function(calls) +@pytest.mark.parametrize( + "module", + [ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial_003(print_mock: PrintMock, module: ModuleType): + module.main() + check_calls(print_mock.calls) - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) - -def test_tutorial_002(clear_sqlmodel): - from docs_src.tutorial.select import tutorial004 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - check_calls(calls) +@pytest.mark.parametrize( + "module", + [ + "tutorial004", + pytest.param("tutorial004_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial_004(print_mock: PrintMock, module: ModuleType): + module.main() + check_calls(print_mock.calls) From 21c37ee4afdd819eb81db5aad5afd0d97632b5e6 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:09:28 +0100 Subject: [PATCH 63/79] Simplify tests for `docs_src.tutorial.update.tutorial002*` and `docs_src.tutorial.update.tutorial002*` --- ...est_tutorial001_py310_tutorial002_py310.py | 56 ------------------- .../test_tutorial001_tutorial002.py | 56 +++++++++++-------- 2 files changed, 32 insertions(+), 80 deletions(-) delete mode 100644 tests/test_tutorial/test_update/test_tutorial001_py310_tutorial002_py310.py diff --git a/tests/test_tutorial/test_update/test_tutorial001_py310_tutorial002_py310.py b/tests/test_tutorial/test_update/test_tutorial001_py310_tutorial002_py310.py deleted file mode 100644 index cefb75f333..0000000000 --- a/tests/test_tutorial/test_update/test_tutorial001_py310_tutorial002_py310.py +++ /dev/null @@ -1,56 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Hero:", - { - "id": 2, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - }, - ], - [ - "Updated hero:", - { - "id": 2, - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": 16, - }, - ], -] - - -@needs_py310 -def test_tutorial001(clear_sqlmodel): - from docs_src.tutorial.update import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -@needs_py310 -def test_tutorial002(clear_sqlmodel): - from docs_src.tutorial.update import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_update/test_tutorial001_tutorial002.py b/tests/test_tutorial/test_update/test_tutorial001_tutorial002.py index be81f410bf..ef12a8d950 100644 --- a/tests/test_tutorial/test_update/test_tutorial001_tutorial002.py +++ b/tests/test_tutorial/test_update/test_tutorial001_tutorial002.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -26,29 +28,35 @@ ] -def test_tutorial001(clear_sqlmodel): - from docs_src.tutorial.update import tutorial001 as mod +@pytest.fixture(name="module") +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module(f"docs_src.tutorial.update.{request.param}") + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -def test_tutorial002(clear_sqlmodel): - from docs_src.tutorial.update import tutorial002 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.mark.parametrize( + "module", + [ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial001(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +@pytest.mark.parametrize( + "module", + [ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial002(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls From d23ad209bd23af4af4364763fd76691402400ca8 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:09:47 +0100 Subject: [PATCH 64/79] Simplify tests for `docs_src.tutorial.update.tutorial003*` and `docs_src.tutorial.update.tutorial004*` --- ...est_tutorial003_py310_tutorial004_py310.py | 69 ------------------- .../test_tutorial003_tutorial004.py | 56 ++++++++------- 2 files changed, 32 insertions(+), 93 deletions(-) delete mode 100644 tests/test_tutorial/test_update/test_tutorial003_py310_tutorial004_py310.py diff --git a/tests/test_tutorial/test_update/test_tutorial003_py310_tutorial004_py310.py b/tests/test_tutorial/test_update/test_tutorial003_py310_tutorial004_py310.py deleted file mode 100644 index 31dc601901..0000000000 --- a/tests/test_tutorial/test_update/test_tutorial003_py310_tutorial004_py310.py +++ /dev/null @@ -1,69 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Hero 1:", - {"id": 2, "name": "Spider-Boy", "secret_name": "Pedro Parqueador", "age": None}, - ], - [ - "Hero 2:", - { - "id": 7, - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - }, - ], - [ - "Updated hero 1:", - { - "id": 2, - "name": "Spider-Youngster", - "secret_name": "Pedro Parqueador", - "age": 16, - }, - ], - [ - "Updated hero 2:", - { - "id": 7, - "name": "Captain North America Except Canada", - "secret_name": "Esteban Rogelios", - "age": 110, - }, - ], -] - - -@needs_py310 -def test_tutorial003(clear_sqlmodel): - from docs_src.tutorial.update import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -@needs_py310 -def test_tutorial004(clear_sqlmodel): - from docs_src.tutorial.update import tutorial004_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls diff --git a/tests/test_tutorial/test_update/test_tutorial003_tutorial004.py b/tests/test_tutorial/test_update/test_tutorial003_tutorial004.py index 0f705aa699..76788c62cd 100644 --- a/tests/test_tutorial/test_update/test_tutorial003_tutorial004.py +++ b/tests/test_tutorial/test_update/test_tutorial003_tutorial004.py @@ -1,8 +1,10 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 expected_calls = [ [ @@ -39,29 +41,35 @@ ] -def test_tutorial003(clear_sqlmodel): - from docs_src.tutorial.update import tutorial003 as mod +@pytest.fixture(name="module") +def get_module(request: pytest.FixtureRequest) -> ModuleType: + module = importlib.import_module(f"docs_src.tutorial.update.{request.param}") + module.sqlite_url = "sqlite://" + module.engine = create_engine(module.sqlite_url) + return module - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls - - -def test_tutorial004(clear_sqlmodel): - from docs_src.tutorial.update import tutorial004 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] +@pytest.mark.parametrize( + "module", + [ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial003(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +@pytest.mark.parametrize( + "module", + [ + "tutorial004", + pytest.param("tutorial004_py310", marks=needs_py310), + ], + indirect=True, +) +def test_tutorial004(print_mock: PrintMock, module: ModuleType): + module.main() + assert print_mock.calls == expected_calls From 1cf9569b56f17081dfff5db664b4236bcdd89879 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:13:17 +0100 Subject: [PATCH 65/79] Simplify tests for `docs_src.tutorial.where.tutorial001*` --- .../test_where/test_tutorial001.py | 27 ++++++++++------- .../test_where/test_tutorial001_py310.py | 29 ------------------- 2 files changed, 17 insertions(+), 39 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial001_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial001.py b/tests/test_tutorial/test_where/test_tutorial001.py index bba13269a1..1a557deefc 100644 --- a/tests/test_tutorial/test_where/test_tutorial001.py +++ b/tests/test_tutorial/test_where/test_tutorial001.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial001 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ { "name": "Deadpond", diff --git a/tests/test_tutorial/test_where/test_tutorial001_py310.py b/tests/test_tutorial/test_where/test_tutorial001_py310.py deleted file mode 100644 index 44e734ad7d..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial001_py310.py +++ /dev/null @@ -1,29 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "age": None, - "id": 1, - } - ] - ] From 20ceffe7d77873ffaef51a90fcf36e357b7f2fcd Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:14:19 +0100 Subject: [PATCH 66/79] Simplify tests for `docs_src.tutorial.where.tutorial002*` --- .../test_where/test_tutorial002.py | 27 ++++++++++------- .../test_where/test_tutorial002_py310.py | 30 ------------------- 2 files changed, 17 insertions(+), 40 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial002_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial002.py b/tests/test_tutorial/test_where/test_tutorial002.py index 80d60ff555..1c96f76126 100644 --- a/tests/test_tutorial/test_where/test_tutorial002.py +++ b/tests/test_tutorial/test_where/test_tutorial002.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial002 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [ { "name": "Spider-Boy", diff --git a/tests/test_tutorial/test_where/test_tutorial002_py310.py b/tests/test_tutorial/test_where/test_tutorial002_py310.py deleted file mode 100644 index 00d88ecdde..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial002_py310.py +++ /dev/null @@ -1,30 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [ - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": 2, - } - ], - [{"name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48, "id": 3}], - ] From b28be3454393489ba13d4a5862de78a72ac31870 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:16:45 +0100 Subject: [PATCH 67/79] Simplify tests for `docs_src.tutorial.where.tutorial003*` --- .../test_where/test_tutorial003.py | 26 ++++++++----- .../test_where/test_tutorial003_py310.py | 37 ------------------- 2 files changed, 17 insertions(+), 46 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial003_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial003.py b/tests/test_tutorial/test_where/test_tutorial003.py index 4794d846ff..6e90d22fc4 100644 --- a/tests/test_tutorial/test_where/test_tutorial003.py +++ b/tests/test_tutorial/test_where/test_tutorial003.py @@ -1,21 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial003 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial003", + pytest.param("tutorial003_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() expected_calls = [ [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], @@ -29,6 +36,7 @@ def test_tutorial(clear_sqlmodel): } ], ] + calls = print_mock.calls for call in expected_calls: assert call in calls, "This expected item should be in the list" # Now that this item was checked, remove it from the list diff --git a/tests/test_tutorial/test_where/test_tutorial003_py310.py b/tests/test_tutorial/test_where/test_tutorial003_py310.py deleted file mode 100644 index 2d84c2ca82..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial003_py310.py +++ /dev/null @@ -1,37 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial003_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - - expected_calls = [ - [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], - [{"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}], - [ - { - "id": 7, - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - } - ], - ] - for call in expected_calls: - assert call in calls, "This expected item should be in the list" - # Now that this item was checked, remove it from the list - calls.pop(calls.index(call)) - assert len(calls) == 0, "The list should only have the expected items" From 633e8f7b3ad95eaa2754021052a13d44cae42bc9 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:18:22 +0100 Subject: [PATCH 68/79] Simplify tests for `docs_src.tutorial.where.tutorial004*` --- .../test_where/test_tutorial004.py | 26 ++++++++----- .../test_where/test_tutorial004_py310.py | 37 ------------------- 2 files changed, 17 insertions(+), 46 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial004_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial004.py b/tests/test_tutorial/test_where/test_tutorial004.py index 682babd43a..b7a1212b77 100644 --- a/tests/test_tutorial/test_where/test_tutorial004.py +++ b/tests/test_tutorial/test_where/test_tutorial004.py @@ -1,21 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial004 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial004", + pytest.param("tutorial004_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() expected_calls = [ [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], @@ -29,6 +36,7 @@ def test_tutorial(clear_sqlmodel): } ], ] + calls = print_mock.calls for call in expected_calls: assert call in calls, "This expected item should be in the list" # Now that this item was checked, remove it from the list diff --git a/tests/test_tutorial/test_where/test_tutorial004_py310.py b/tests/test_tutorial/test_where/test_tutorial004_py310.py deleted file mode 100644 index 04566cbbec..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial004_py310.py +++ /dev/null @@ -1,37 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial004_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - expected_calls = [ - [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], - [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], - [{"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}], - [ - { - "id": 7, - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - } - ], - ] - for call in expected_calls: - assert call in calls, "This expected item should be in the list" - # Now that this item was checked, remove it from the list - calls.pop(calls.index(call)) - assert len(calls) == 0, "The list should only have the expected items" From 2db3d6476838b0f37b8769ff64a279ffe8d65d3a Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:20:46 +0100 Subject: [PATCH 69/79] Simplify tests for `docs_src.tutorial.where.tutorial005*` --- .../test_where/test_tutorial005.py | 27 ++++++++++++------- .../test_where/test_tutorial005_py310.py | 22 --------------- 2 files changed, 17 insertions(+), 32 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial005_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial005.py b/tests/test_tutorial/test_where/test_tutorial005.py index b6bfd2ce88..9adbec74a2 100644 --- a/tests/test_tutorial/test_where/test_tutorial005.py +++ b/tests/test_tutorial/test_where/test_tutorial005.py @@ -1,21 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial005 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial005", + pytest.param("tutorial005_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}] ] diff --git a/tests/test_tutorial/test_where/test_tutorial005_py310.py b/tests/test_tutorial/test_where/test_tutorial005_py310.py deleted file mode 100644 index d238fff4f8..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial005_py310.py +++ /dev/null @@ -1,22 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial005_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}] - ] From 24dedb63480f7c0ababbd8564bf384717f7ce48c Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:21:11 +0100 Subject: [PATCH 70/79] Simplify tests for `docs_src.tutorial.where.tutorial006*` --- .../test_where/test_tutorial006.py | 27 ++++++++++++------- .../test_where/test_tutorial006_py310.py | 23 ---------------- 2 files changed, 17 insertions(+), 33 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial006_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial006.py b/tests/test_tutorial/test_where/test_tutorial006.py index e5406dfbb0..e5d586a39a 100644 --- a/tests/test_tutorial/test_where/test_tutorial006.py +++ b/tests/test_tutorial/test_where/test_tutorial006.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial006 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial006", + pytest.param("tutorial006_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], ] diff --git a/tests/test_tutorial/test_where/test_tutorial006_py310.py b/tests/test_tutorial/test_where/test_tutorial006_py310.py deleted file mode 100644 index 8a4924fc09..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial006_py310.py +++ /dev/null @@ -1,23 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial006_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], - [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], - ] From 7e3d378f58f8ead509438d99c28a251f22a60e0a Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:22:28 +0100 Subject: [PATCH 71/79] Simplify tests for `docs_src.tutorial.where.tutorial007*` --- .../test_where/test_tutorial007.py | 27 ++++++++++++------- .../test_where/test_tutorial007_py310.py | 23 ---------------- 2 files changed, 17 insertions(+), 33 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial007_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial007.py b/tests/test_tutorial/test_where/test_tutorial007.py index 878e81f932..9a36279d38 100644 --- a/tests/test_tutorial/test_where/test_tutorial007.py +++ b/tests/test_tutorial/test_where/test_tutorial007.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial007 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial007", + pytest.param("tutorial007_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], ] diff --git a/tests/test_tutorial/test_where/test_tutorial007_py310.py b/tests/test_tutorial/test_where/test_tutorial007_py310.py deleted file mode 100644 index a2110a19dc..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial007_py310.py +++ /dev/null @@ -1,23 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial007_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], - [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], - ] From b005a91ef214953bb901c95069986d30a79d059c Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:23:40 +0100 Subject: [PATCH 72/79] Simplify tests for `docs_src.tutorial.where.tutorial008*` --- .../test_where/test_tutorial008.py | 27 ++++++++++++------- .../test_where/test_tutorial008_py310.py | 23 ---------------- 2 files changed, 17 insertions(+), 33 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial008_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial008.py b/tests/test_tutorial/test_where/test_tutorial008.py index 08f4c49b9d..a21e2ecbe3 100644 --- a/tests/test_tutorial/test_where/test_tutorial008.py +++ b/tests/test_tutorial/test_where/test_tutorial008.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial008 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial008", + pytest.param("tutorial008_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], ] diff --git a/tests/test_tutorial/test_where/test_tutorial008_py310.py b/tests/test_tutorial/test_where/test_tutorial008_py310.py deleted file mode 100644 index 887ac70abd..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial008_py310.py +++ /dev/null @@ -1,23 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial008_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], - [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], - ] From 8dbee6e614f6a6b282a35465a1c46fb19a702666 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:25:08 +0100 Subject: [PATCH 73/79] Simplify tests for `docs_src.tutorial.where.tutorial009*` --- .../test_where/test_tutorial009.py | 27 ++++++++++------ .../test_where/test_tutorial009_py310.py | 31 ------------------- 2 files changed, 17 insertions(+), 41 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial009_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial009.py b/tests/test_tutorial/test_where/test_tutorial009.py index 2583f330cb..8088045b02 100644 --- a/tests/test_tutorial/test_where/test_tutorial009.py +++ b/tests/test_tutorial/test_where/test_tutorial009.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial009 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial009", + pytest.param("tutorial009_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], [ diff --git a/tests/test_tutorial/test_where/test_tutorial009_py310.py b/tests/test_tutorial/test_where/test_tutorial009_py310.py deleted file mode 100644 index 9bbef9b9f8..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial009_py310.py +++ /dev/null @@ -1,31 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial009_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], - [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], - [ - { - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - "id": 7, - } - ], - ] From 3c64e7ac67558bedfaae3fa83427419472c27d57 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:26:16 +0100 Subject: [PATCH 74/79] Simplify tests for `docs_src.tutorial.where.tutorial010*` --- .../test_where/test_tutorial010.py | 27 ++++++++++------ .../test_where/test_tutorial010_py310.py | 31 ------------------- 2 files changed, 17 insertions(+), 41 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial010_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial010.py b/tests/test_tutorial/test_where/test_tutorial010.py index 71ef75d3a4..ea235ef708 100644 --- a/tests/test_tutorial/test_where/test_tutorial010.py +++ b/tests/test_tutorial/test_where/test_tutorial010.py @@ -1,22 +1,29 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial010 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial010", + pytest.param("tutorial010_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == [ [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], [ diff --git a/tests/test_tutorial/test_where/test_tutorial010_py310.py b/tests/test_tutorial/test_where/test_tutorial010_py310.py deleted file mode 100644 index e990abed44..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial010_py310.py +++ /dev/null @@ -1,31 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial010_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == [ - [{"name": "Tarantula", "secret_name": "Natalia Roman-on", "age": 32, "id": 4}], - [{"name": "Black Lion", "secret_name": "Trevor Challa", "age": 35, "id": 5}], - [ - { - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - "id": 7, - } - ], - ] From fdedfb5c7ab5ed0a0eae5939c0da34547617c150 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:27:20 +0100 Subject: [PATCH 75/79] Simplify tests for `docs_src.tutorial.where.tutorial011*` --- .../test_where/test_tutorial011.py | 26 ++++++++----- .../test_where/test_tutorial011_py310.py | 37 ------------------- 2 files changed, 17 insertions(+), 46 deletions(-) delete mode 100644 tests/test_tutorial/test_where/test_tutorial011_py310.py diff --git a/tests/test_tutorial/test_where/test_tutorial011.py b/tests/test_tutorial/test_where/test_tutorial011.py index 8006cd0708..ba53550611 100644 --- a/tests/test_tutorial/test_where/test_tutorial011.py +++ b/tests/test_tutorial/test_where/test_tutorial011.py @@ -1,21 +1,28 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial011 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial011", + pytest.param("tutorial011_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.tutorial.where.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() expected_calls = [ [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], @@ -29,6 +36,7 @@ def test_tutorial(clear_sqlmodel): } ], ] + calls = print_mock.calls for call in expected_calls: assert call in calls, "This expected item should be in the list" # Now that this item was checked, remove it from the list diff --git a/tests/test_tutorial/test_where/test_tutorial011_py310.py b/tests/test_tutorial/test_where/test_tutorial011_py310.py deleted file mode 100644 index aee809b15b..0000000000 --- a/tests/test_tutorial/test_where/test_tutorial011_py310.py +++ /dev/null @@ -1,37 +0,0 @@ -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial(clear_sqlmodel): - from docs_src.tutorial.where import tutorial011_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - expected_calls = [ - [{"id": 5, "name": "Black Lion", "secret_name": "Trevor Challa", "age": 35}], - [{"id": 6, "name": "Dr. Weird", "secret_name": "Steve Weird", "age": 36}], - [{"id": 3, "name": "Rusty-Man", "secret_name": "Tommy Sharp", "age": 48}], - [ - { - "id": 7, - "name": "Captain North America", - "secret_name": "Esteban Rogelios", - "age": 93, - } - ], - ] - for call in expected_calls: - assert call in calls, "This expected item should be in the list" - # Now that this item was checked, remove it from the list - calls.pop(calls.index(call)) - assert len(calls) == 0, "The list should only have the expected items" From a49113367bff695431cba582bcce0234dbf6687f Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:34:10 +0100 Subject: [PATCH 76/79] Simplify tests for `docs_src.advanced.decimal.tutorial001*` --- .../test_decimal/test_tutorial001.py | 36 +++++++++------ .../test_decimal/test_tutorial001_py310.py | 45 ------------------- 2 files changed, 22 insertions(+), 59 deletions(-) delete mode 100644 tests/test_advanced/test_decimal/test_tutorial001_py310.py diff --git a/tests/test_advanced/test_decimal/test_tutorial001.py b/tests/test_advanced/test_decimal/test_tutorial001.py index 2dc562209f..dad8f24c4c 100644 --- a/tests/test_advanced/test_decimal/test_tutorial001.py +++ b/tests/test_advanced/test_decimal/test_tutorial001.py @@ -1,9 +1,26 @@ +import importlib from decimal import Decimal -from unittest.mock import patch +from types import ModuleType +import pytest from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 + + +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.advanced.decimal.{request.param}") + mod.sqlite_url = "sqlite://" + mod.engine = create_engine(mod.sqlite_url) + return mod + expected_calls = [ [ @@ -30,15 +47,6 @@ ] -def test_tutorial(): - from docs_src.advanced.decimal import tutorial001 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls +def test_tutorial(print_mock: PrintMock, mod: ModuleType): + mod.main() + assert print_mock.calls == expected_calls diff --git a/tests/test_advanced/test_decimal/test_tutorial001_py310.py b/tests/test_advanced/test_decimal/test_tutorial001_py310.py deleted file mode 100644 index 4cda8b4653..0000000000 --- a/tests/test_advanced/test_decimal/test_tutorial001_py310.py +++ /dev/null @@ -1,45 +0,0 @@ -from decimal import Decimal -from unittest.mock import patch - -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - -expected_calls = [ - [ - "Hero 1:", - { - "name": "Deadpond", - "age": None, - "id": 1, - "secret_name": "Dive Wilson", - "money": Decimal("1.100"), - }, - ], - [ - "Hero 2:", - { - "name": "Rusty-Man", - "age": 48, - "id": 3, - "secret_name": "Tommy Sharp", - "money": Decimal("2.200"), - }, - ], - ["Total money: 3.300"], -] - - -@needs_py310 -def test_tutorial(): - from docs_src.advanced.decimal import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - assert calls == expected_calls From 1962d72bdd1d792551130b350a883a1b007b71af Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:36:25 +0100 Subject: [PATCH 77/79] Simplify tests for `docs_src.advanced.uuid.tutorial001*` --- .../test_uuid/test_tutorial001.py | 31 ++++---- .../test_uuid/test_tutorial001_py310.py | 72 ------------------- 2 files changed, 19 insertions(+), 84 deletions(-) delete mode 100644 tests/test_advanced/test_uuid/test_tutorial001_py310.py diff --git a/tests/test_advanced/test_uuid/test_tutorial001.py b/tests/test_advanced/test_uuid/test_tutorial001.py index b9d5a36800..ab4f3387dc 100644 --- a/tests/test_advanced/test_uuid/test_tutorial001.py +++ b/tests/test_advanced/test_uuid/test_tutorial001.py @@ -1,31 +1,38 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from dirty_equals import IsUUID from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial() -> None: - from docs_src.advanced.uuid import tutorial001 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial001", + pytest.param("tutorial001_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.advanced.uuid.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - first_uuid = calls[1][0]["id"] +def test_tutorial(print_mock: PrintMock, mod: ModuleType) -> None: + mod.main() + first_uuid = print_mock.calls[1][0]["id"] assert first_uuid == IsUUID(4) - second_uuid = calls[7][0]["id"] + second_uuid = print_mock.calls[7][0]["id"] assert second_uuid == IsUUID(4) assert first_uuid != second_uuid - assert calls == [ + assert print_mock.calls == [ ["The hero before saving in the DB"], [ { diff --git a/tests/test_advanced/test_uuid/test_tutorial001_py310.py b/tests/test_advanced/test_uuid/test_tutorial001_py310.py deleted file mode 100644 index 1250c32872..0000000000 --- a/tests/test_advanced/test_uuid/test_tutorial001_py310.py +++ /dev/null @@ -1,72 +0,0 @@ -from unittest.mock import patch - -from dirty_equals import IsUUID -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial() -> None: - from docs_src.advanced.uuid import tutorial001_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - first_uuid = calls[1][0]["id"] - assert first_uuid == IsUUID(4) - - second_uuid = calls[7][0]["id"] - assert second_uuid == IsUUID(4) - - assert first_uuid != second_uuid - - assert calls == [ - ["The hero before saving in the DB"], - [ - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "id": first_uuid, - "age": None, - } - ], - ["The hero ID was already set"], - [first_uuid], - ["After saving in the DB"], - [ - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "age": None, - "id": first_uuid, - } - ], - ["Created hero:"], - [ - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": second_uuid, - } - ], - ["Created hero ID:"], - [second_uuid], - ["Selected hero:"], - [ - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": second_uuid, - } - ], - ["Selected hero ID:"], - [second_uuid], - ] From 28cb1cc75f28ee93647c70d25b8032c9f740c928 Mon Sep 17 00:00:00 2001 From: Yurii Motov Date: Tue, 2 Dec 2025 21:37:46 +0100 Subject: [PATCH 78/79] Simplify tests for `docs_src.advanced.uuid.tutorial002*` --- .../test_uuid/test_tutorial002.py | 31 ++++---- .../test_uuid/test_tutorial002_py310.py | 72 ------------------- 2 files changed, 19 insertions(+), 84 deletions(-) delete mode 100644 tests/test_advanced/test_uuid/test_tutorial002_py310.py diff --git a/tests/test_advanced/test_uuid/test_tutorial002.py b/tests/test_advanced/test_uuid/test_tutorial002.py index c9f4e5a35d..b1ff5ba3fd 100644 --- a/tests/test_advanced/test_uuid/test_tutorial002.py +++ b/tests/test_advanced/test_uuid/test_tutorial002.py @@ -1,31 +1,38 @@ -from unittest.mock import patch +import importlib +from types import ModuleType +import pytest from dirty_equals import IsUUID from sqlmodel import create_engine -from ...conftest import get_testing_print_function +from ...conftest import PrintMock, needs_py310 -def test_tutorial() -> None: - from docs_src.advanced.uuid import tutorial002 as mod - +@pytest.fixture( + name="mod", + params=[ + "tutorial002", + pytest.param("tutorial002_py310", marks=needs_py310), + ], +) +def get_module(request: pytest.FixtureRequest) -> ModuleType: + mod = importlib.import_module(f"docs_src.advanced.uuid.{request.param}") mod.sqlite_url = "sqlite://" mod.engine = create_engine(mod.sqlite_url) - calls = [] + return mod - new_print = get_testing_print_function(calls) - with patch("builtins.print", new=new_print): - mod.main() - first_uuid = calls[1][0]["id"] +def test_tutorial(print_mock: PrintMock, mod: ModuleType) -> None: + mod.main() + first_uuid = print_mock.calls[1][0]["id"] assert first_uuid == IsUUID(4) - second_uuid = calls[7][0]["id"] + second_uuid = print_mock.calls[7][0]["id"] assert second_uuid == IsUUID(4) assert first_uuid != second_uuid - assert calls == [ + assert print_mock.calls == [ ["The hero before saving in the DB"], [ { diff --git a/tests/test_advanced/test_uuid/test_tutorial002_py310.py b/tests/test_advanced/test_uuid/test_tutorial002_py310.py deleted file mode 100644 index ba472e30fd..0000000000 --- a/tests/test_advanced/test_uuid/test_tutorial002_py310.py +++ /dev/null @@ -1,72 +0,0 @@ -from unittest.mock import patch - -from dirty_equals import IsUUID -from sqlmodel import create_engine - -from ...conftest import get_testing_print_function, needs_py310 - - -@needs_py310 -def test_tutorial() -> None: - from docs_src.advanced.uuid import tutorial002_py310 as mod - - mod.sqlite_url = "sqlite://" - mod.engine = create_engine(mod.sqlite_url) - calls = [] - - new_print = get_testing_print_function(calls) - - with patch("builtins.print", new=new_print): - mod.main() - first_uuid = calls[1][0]["id"] - assert first_uuid == IsUUID(4) - - second_uuid = calls[7][0]["id"] - assert second_uuid == IsUUID(4) - - assert first_uuid != second_uuid - - assert calls == [ - ["The hero before saving in the DB"], - [ - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "id": first_uuid, - "age": None, - } - ], - ["The hero ID was already set"], - [first_uuid], - ["After saving in the DB"], - [ - { - "name": "Deadpond", - "secret_name": "Dive Wilson", - "age": None, - "id": first_uuid, - } - ], - ["Created hero:"], - [ - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": second_uuid, - } - ], - ["Created hero ID:"], - [second_uuid], - ["Selected hero:"], - [ - { - "name": "Spider-Boy", - "secret_name": "Pedro Parqueador", - "age": None, - "id": second_uuid, - } - ], - ["Selected hero ID:"], - [second_uuid], - ] From 931799568c876f489c11aee9f036ed1f4ab2992a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 2 Dec 2025 20:42:38 +0000 Subject: [PATCH 79/79] =?UTF-8?q?=F0=9F=8E=A8=20[pre-commit.ci]=20Auto=20f?= =?UTF-8?q?ormat=20from=20pre-commit.com=20hooks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../test_back_populates/test_tutorial001.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py index f49c516911..698a7af2cb 100644 --- a/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py +++ b/tests/test_tutorial/test_relationship_attributes/test_back_populates/test_tutorial001.py @@ -294,4 +294,4 @@ def get_module(request: pytest.FixtureRequest) -> ModuleType: def test_tutorial(print_mock: PrintMock, mod: ModuleType): with pytest.warns(SAWarning): mod.main() - assert print_mock.calls == expected_calls \ No newline at end of file + assert print_mock.calls == expected_calls