From f15e364c37a65b13ea27bc75b0ef846144e07b57 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 10 Mar 2026 18:59:11 +0000 Subject: [PATCH 1/6] Refactor generate tests to use assertion helper --- tests/main/conftest.py | 47 ++- tests/main/jsonschema/test_main_jsonschema.py | 301 +++++++----------- 2 files changed, 167 insertions(+), 181 deletions(-) diff --git a/tests/main/conftest.py b/tests/main/conftest.py index 31a268010..58aea2d64 100644 --- a/tests/main/conftest.py +++ b/tests/main/conftest.py @@ -10,12 +10,13 @@ from argparse import Namespace from collections.abc import Callable, Generator, Sequence from pathlib import Path -from typing import Literal +from typing import Any, Literal import black import pytest from packaging import version +from datamodel_code_generator import InputFileType, generate from datamodel_code_generator.__main__ import Exit, main from datamodel_code_generator.arguments import arg_parser from tests.conftest import ( @@ -240,6 +241,50 @@ def run_main_with_args( return return_code +def run_generate_file_and_assert( + *, + input_path: Path, + output_path: Path, + input_file_type: InputFileType | None = None, + assert_func: AssertFileContent, + expected_file: str | Path | None = None, + transform: Callable[[str], str] | None = None, + **generate_kwargs: Any, +) -> None: + """Execute generate() for a file input and assert the generated output.""" + __tracebackhide__ = True + + input_: Path = input_path + if input_path.is_absolute(): + try: + input_ = input_path.relative_to(Path.cwd()) + except ValueError: + input_ = input_path + else: + assert not input_.is_absolute() + + generate( + input_=input_, + input_file_type=input_file_type, + output=output_path, + **generate_kwargs, + ) + + if expected_file is None: + frame = inspect.currentframe() + assert frame is not None + assert frame.f_back is not None + func_name = frame.f_back.f_code.co_name + del frame + for prefix in ("test_main_", "test_"): # pragma: no branch + if func_name.startswith(prefix): + func_name = func_name[len(prefix) :] + break + expected_file = f"{func_name}.py" + + assert_func(output_path, expected_file, transform=transform) + + def run_main_and_assert( # noqa: PLR0912 *, input_path: Path | None = None, diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index c8a2fd614..8789f592b 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -36,6 +36,7 @@ LEGACY_BLACK_SKIP, MSGSPEC_LEGACY_BLACK_SKIP, TIMESTAMP, + run_generate_file_and_assert, run_main_and_assert, run_main_url_and_assert, run_main_with_args, @@ -1628,312 +1629,252 @@ def test_main_jsonschema_pattern(output_file: Path) -> None: ) -def test_main_generate(tmp_path: Path) -> None: +def test_main_generate(output_file: Path) -> None: """Test code generation function.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "person.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "person.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="general.py", ) - assert_file_content(output_file, "general.py") - -def test_main_generate_non_pydantic_output(tmp_path: Path) -> None: +def test_main_generate_non_pydantic_output(output_file: Path) -> None: """Test generation with non-Pydantic output models (see issue #1452).""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="generate_non_pydantic_output.py", output_model_type=DataModelType.DataclassesDataclass, ) - assert_file_content(output_file, "generate_non_pydantic_output.py") - -def test_main_generate_pydantic_v2_dataclass(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass(output_file: Path) -> None: """Test generation with pydantic_v2.dataclass output model.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="generate_pydantic_v2_dataclass.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "generate_pydantic_v2_dataclass.py") - -def test_main_generate_pydantic_v2_dataclass_with_config(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_with_config(output_file: Path) -> None: """Test pydantic_v2.dataclass with ConfigDict from additionalProperties.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_config.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_config.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_config.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "pydantic_v2_dataclass_config.py") - -def test_main_generate_pydantic_v2_dataclass_additional_props_true(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_additional_props_true(output_file: Path) -> None: """Test pydantic_v2.dataclass with additionalProperties: true.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_additional_props_true.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_additional_props_true.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_additional_props_true.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "pydantic_v2_dataclass_additional_props_true.py") - -def test_main_generate_pydantic_v2_dataclass_unevaluated_props_true(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_unevaluated_props_true(output_file: Path) -> None: """Test pydantic_v2.dataclass with unevaluatedProperties: true.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "unevaluated_properties_true.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "unevaluated_properties_true.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="unevaluated_properties_true_dataclass.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "unevaluated_properties_true_dataclass.py") - -def test_main_generate_pydantic_v2_base_model_unevaluated_props(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_base_model_unevaluated_props(output_file: Path) -> None: """Test pydantic_v2.BaseModel with unevaluatedProperties: false.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "unevaluated_properties.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "unevaluated_properties.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="unevaluated_properties_pydantic_v2.py", output_model_type=DataModelType.PydanticV2BaseModel, ) - assert_file_content(output_file, "unevaluated_properties_pydantic_v2.py") - -def test_main_generate_pydantic_v2_base_model_unevaluated_props_true(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_base_model_unevaluated_props_true(output_file: Path) -> None: """Test pydantic_v2.BaseModel with unevaluatedProperties: true.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "unevaluated_properties_true.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "unevaluated_properties_true.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="unevaluated_properties_true_pydantic_v2.py", output_model_type=DataModelType.PydanticV2BaseModel, ) - assert_file_content(output_file, "unevaluated_properties_true_pydantic_v2.py") - -def test_main_generate_pydantic_v2_dataclass_unevaluated_props_false(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_unevaluated_props_false(output_file: Path) -> None: """Test pydantic_v2.dataclass with unevaluatedProperties: false.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "unevaluated_properties.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "unevaluated_properties.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="unevaluated_properties_dataclass.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "unevaluated_properties_dataclass.py") - -def test_main_generate_pydantic_v2_dataclass_use_attribute_docstrings(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_use_attribute_docstrings(output_file: Path) -> None: """Test pydantic_v2.dataclass with use_attribute_docstrings.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_use_attribute_docstrings.py", output_model_type=DataModelType.PydanticV2Dataclass, use_attribute_docstrings=True, ) - assert_file_content(output_file, "pydantic_v2_dataclass_use_attribute_docstrings.py") - -def test_main_generate_pydantic_v2_dataclass_allow_population_by_field_name(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_allow_population_by_field_name(output_file: Path) -> None: """Test pydantic_v2.dataclass with allow_population_by_field_name.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_populate_by_name.py", output_model_type=DataModelType.PydanticV2Dataclass, allow_population_by_field_name=True, ) - assert_file_content(output_file, "pydantic_v2_dataclass_populate_by_name.py") - -def test_main_generate_pydantic_v2_dataclass_allow_population_by_field_name_v2_11(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_allow_population_by_field_name_v2_11(output_file: Path) -> None: """Test pydantic_v2.dataclass with allow_population_by_field_name and target v2.11.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_validate_by_name.py", output_model_type=DataModelType.PydanticV2Dataclass, allow_population_by_field_name=True, target_pydantic_version=TargetPydanticVersion.V2_11, ) - assert_file_content(output_file, "pydantic_v2_dataclass_validate_by_name.py") - -def test_main_generate_pydantic_v2_dataclass_extra_allow(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_extra_allow(output_file: Path) -> None: """Test pydantic_v2.dataclass with extra='allow'.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_extra_allow.py", output_model_type=DataModelType.PydanticV2Dataclass, extra_fields="allow", ) - assert_file_content(output_file, "pydantic_v2_dataclass_extra_allow.py") - -def test_main_generate_pydantic_v2_dataclass_extra_forbid(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_extra_forbid(output_file: Path) -> None: """Test pydantic_v2.dataclass with extra='forbid'.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_extra_forbid.py", output_model_type=DataModelType.PydanticV2Dataclass, extra_fields="forbid", ) - assert_file_content(output_file, "pydantic_v2_dataclass_extra_forbid.py") - -def test_main_generate_pydantic_v2_dataclass_extra_ignore(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_extra_ignore(output_file: Path) -> None: """Test pydantic_v2.dataclass with extra='ignore'.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "simple_string.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "simple_string.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_extra_ignore.py", output_model_type=DataModelType.PydanticV2Dataclass, extra_fields="ignore", ) - assert_file_content(output_file, "pydantic_v2_dataclass_extra_ignore.py") - -def test_main_generate_pydantic_v2_dataclass_nested(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_nested(output_file: Path) -> None: """Test pydantic_v2.dataclass with nested models.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_nested.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_nested.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_nested.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "pydantic_v2_dataclass_nested.py") - -def test_main_generate_pydantic_v2_dataclass_constraints(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_constraints(output_file: Path) -> None: """Test pydantic_v2.dataclass with field constraints.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_constraints.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_constraints.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_constraints.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "pydantic_v2_dataclass_constraints.py") - -def test_main_generate_pydantic_v2_dataclass_nested_frozen(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_nested_frozen(output_file: Path) -> None: """Test pydantic_v2.dataclass with nested models and frozen=True.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_nested.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_nested.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_nested_frozen.py", output_model_type=DataModelType.PydanticV2Dataclass, frozen_dataclasses=True, ) - assert_file_content(output_file, "pydantic_v2_dataclass_nested_frozen.py") - -def test_main_generate_pydantic_v2_dataclass_field(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_field(output_file: Path) -> None: """Test pydantic_v2.dataclass with Field constraints and defaults.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_field.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_field.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_field.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "pydantic_v2_dataclass_field.py") - -def test_main_generate_pydantic_v2_dataclass_enum(tmp_path: Path) -> None: +def test_main_generate_pydantic_v2_dataclass_enum(output_file: Path) -> None: """Test pydantic_v2.dataclass with enum types.""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_enum.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "pydantic_v2_dataclass_enum.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="pydantic_v2_dataclass_enum.py", output_model_type=DataModelType.PydanticV2Dataclass, ) - assert_file_content(output_file, "pydantic_v2_dataclass_enum.py") - def test_main_generate_from_directory(tmp_path: Path) -> None: """Test generation from directory input.""" From 3a85eee18b0acd70c3135543a662dbc27eb4de3e Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 10 Mar 2026 19:08:36 +0000 Subject: [PATCH 2/6] Refactor more generate tests to use assertion helper --- tests/main/jsonschema/test_main_jsonschema.py | 63 +++++++++---------- tests/main/test_main_general.py | 25 ++++---- 2 files changed, 41 insertions(+), 47 deletions(-) diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index 8789f592b..663eb69fa 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -1898,19 +1898,14 @@ def custom_class_name_generator(title: str) -> str: return f"Custom{title}" output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "person.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "person.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, - custom_class_name_generator=custom_class_name_generator, - ) - - assert_file_content( - output_file, - "general.py", + assert_func=assert_file_content, + expected_file="general.py", transform=lambda s: s.replace("CustomPerson", "Person"), + custom_class_name_generator=custom_class_name_generator, ) @@ -1921,36 +1916,31 @@ def test_main_generate_custom_class_name_generator_additional_properties(tmp_pat def custom_class_name_generator(name: str) -> str: return f"Custom{name[0].upper() + name[1:]}" - input_ = (JSON_SCHEMA_DATA_PATH / "root_model_with_additional_properties.json").relative_to(Path.cwd()) - assert not input_.is_absolute() - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "root_model_with_additional_properties.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="root_model_with_additional_properties_custom_class_name.py", custom_class_name_generator=custom_class_name_generator, ) - assert_file_content(output_file, "root_model_with_additional_properties_custom_class_name.py") - -def test_main_generate_custom_class_name_generator_keep_underscores(tmp_path: Path) -> None: +def test_main_generate_custom_class_name_generator_keep_underscores(output_file: Path) -> None: """Test custom_class_name_generator preserves underscores in class names (Issue #1315).""" - output_file: Path = tmp_path / "output.py" - input_ = (JSON_SCHEMA_DATA_PATH / "underscore_title.json").relative_to(Path.cwd()) - assert not input_.is_absolute() def keep_underscores(name: str) -> str: return name - generate( - input_=input_, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "underscore_title.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="underscore_title.py", custom_class_name_generator=keep_underscores, ) - assert_file_content(output_file, "underscore_title.py") - def test_main_http_jsonschema(mocker: MockerFixture, output_file: Path) -> None: """Test HTTP JSON Schema fetching.""" @@ -4862,10 +4852,12 @@ def test_main_jsonschema_openapi_keyword_only_msgspec_with_extra_data(tmp_path: """Test OpenAPI msgspec keyword-only with extra data.""" extra_data = json.loads((JSON_SCHEMA_DATA_PATH / "extra_data_msgspec.json").read_text()) output_file: Path = tmp_path / "output.py" - generate( - input_=JSON_SCHEMA_DATA_PATH / "discriminator_literals.json", - output=output_file, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "discriminator_literals.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, + assert_func=assert_file_content, + expected_file="discriminator_literals_msgspec_keyword_only_omit_defaults.py", output_model_type=DataModelType.MsgspecStruct, keyword_only=True, target_python_version=PythonVersionMin, @@ -4874,7 +4866,6 @@ def test_main_jsonschema_openapi_keyword_only_msgspec_with_extra_data(tmp_path: use_annotated=True, field_constraints=True, ) - assert_file_content(output_file, "discriminator_literals_msgspec_keyword_only_omit_defaults.py") @MSGSPEC_LEGACY_BLACK_SKIP @@ -4916,14 +4907,16 @@ def test_main_msgspec_discriminator_with_meta(output_file: Path) -> None: @MSGSPEC_LEGACY_BLACK_SKIP def test_main_msgspec_discriminator_without_annotated(output_file: Path) -> None: """Test msgspec Struct discriminator generates ClassVar even without use_annotated.""" - generate( - JSON_SCHEMA_DATA_PATH / "discriminator_with_type_string.json", - output=output_file, + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "discriminator_with_type_string.json", + output_path=output_file, + input_file_type=InputFileType.JsonSchema, + assert_func=assert_file_content, + expected_file="discriminator_with_type_string_msgspec_no_annotated.py", output_model_type=DataModelType.MsgspecStruct, target_python_version=PythonVersion.PY_310, use_annotated=False, ) - assert_file_content(output_file, "discriminator_with_type_string_msgspec_no_annotated.py") @MSGSPEC_LEGACY_BLACK_SKIP diff --git a/tests/main/test_main_general.py b/tests/main/test_main_general.py index 5a69dc8ef..0feecaea2 100644 --- a/tests/main/test_main_general.py +++ b/tests/main/test_main_general.py @@ -37,6 +37,7 @@ OPEN_API_DATA_PATH, PYTHON_DATA_PATH, TIMESTAMP, + run_generate_file_and_assert, run_main_and_assert, run_main_with_args, ) @@ -137,23 +138,23 @@ def test_direct_input_dict(tmp_path: Path) -> None: ], ) def test_frozen_dataclasses( - tmp_path: Path, + output_file: Path, keyword_only: bool, target_python_version: PythonVersion, expected_file: str, ) -> None: """Test --frozen-dataclasses flag functionality.""" - output_file = tmp_path / "output.py" - generate( - DATA_PATH / "jsonschema" / "simple_frozen_test.json", + run_generate_file_and_assert( + input_path=DATA_PATH / "jsonschema" / "simple_frozen_test.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file=expected_file, output_model_type=DataModelType.DataclassesDataclass, frozen_dataclasses=True, keyword_only=keyword_only, target_python_version=target_python_version, ) - assert_file_content(output_file, expected_file) @pytest.mark.cli_doc( @@ -204,18 +205,18 @@ def test_frozen_dataclasses_command_line(output_file: Path, extra_args: list[str @freeze_time(TIMESTAMP) -def test_class_decorators(tmp_path: Path) -> None: +def test_class_decorators(output_file: Path) -> None: """Test --class-decorators flag functionality.""" - output_file = tmp_path / "output.py" - generate( - DATA_PATH / "jsonschema" / "simple_frozen_test.json", + run_generate_file_and_assert( + input_path=DATA_PATH / "jsonschema" / "simple_frozen_test.json", + output_path=output_file, input_file_type=InputFileType.JsonSchema, - output=output_file, + assert_func=assert_file_content, + expected_file="class_decorators_dataclass.py", output_model_type=DataModelType.DataclassesDataclass, class_decorators=["@dataclass_json"], additional_imports=["dataclasses_json.dataclass_json"], ) - assert_file_content(output_file, "class_decorators_dataclass.py") @pytest.mark.cli_doc( From 5c95785c7ce6f177a2e8c4f8b8b26793916088fb Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 10 Mar 2026 19:34:46 +0000 Subject: [PATCH 3/6] Add coverage for generate test helper --- tests/main/jsonschema/test_main_jsonschema.py | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index 325629733..8dfafb836 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -1647,11 +1647,35 @@ def test_main_generate_non_pydantic_output(output_file: Path) -> None: output_path=output_file, input_file_type=InputFileType.JsonSchema, assert_func=assert_file_content, - expected_file="generate_non_pydantic_output.py", output_model_type=DataModelType.DataclassesDataclass, ) +def test_main_generate_relative_input_path(output_file: Path) -> None: + """Test helper with a relative input path.""" + run_generate_file_and_assert( + input_path=(JSON_SCHEMA_DATA_PATH / "person.json").relative_to(Path.cwd()), + output_path=output_file, + input_file_type=InputFileType.JsonSchema, + assert_func=assert_file_content, + expected_file="general.py", + ) + + +def test_main_generate_external_absolute_input_path(tmp_path: Path) -> None: + """Test helper keeps absolute input paths that are outside the repository root.""" + input_path = tmp_path / "person.json" + input_path.write_text((JSON_SCHEMA_DATA_PATH / "person.json").read_text(encoding="utf-8"), encoding="utf-8") + + run_generate_file_and_assert( + input_path=input_path, + output_path=tmp_path / "output.py", + input_file_type=InputFileType.JsonSchema, + assert_func=assert_file_content, + expected_file="general.py", + ) + + def test_main_generate_pydantic_v2_dataclass(output_file: Path) -> None: """Test generation with pydantic_v2.dataclass output model.""" run_generate_file_and_assert( From 1c6a5d5ffeeb7b9f8a2b0130737555aee6e5e9fd Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 10 Mar 2026 19:53:20 +0000 Subject: [PATCH 4/6] Fix generate helper coverage and relative path test --- tests/main/conftest.py | 6 ++---- tests/main/jsonschema/test_main_jsonschema.py | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tests/main/conftest.py b/tests/main/conftest.py index 58aea2d64..e586e2779 100644 --- a/tests/main/conftest.py +++ b/tests/main/conftest.py @@ -276,10 +276,8 @@ def run_generate_file_and_assert( assert frame.f_back is not None func_name = frame.f_back.f_code.co_name del frame - for prefix in ("test_main_", "test_"): # pragma: no branch - if func_name.startswith(prefix): - func_name = func_name[len(prefix) :] - break + for prefix in ("test_main_", "test_"): + func_name = func_name.removeprefix(prefix) expected_file = f"{func_name}.py" assert_func(output_path, expected_file, transform=transform) diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index 8dfafb836..fe00a571e 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -3,6 +3,7 @@ from __future__ import annotations import json +import os from collections import defaultdict from pathlib import Path from typing import TYPE_CHECKING @@ -1654,7 +1655,7 @@ def test_main_generate_non_pydantic_output(output_file: Path) -> None: def test_main_generate_relative_input_path(output_file: Path) -> None: """Test helper with a relative input path.""" run_generate_file_and_assert( - input_path=(JSON_SCHEMA_DATA_PATH / "person.json").relative_to(Path.cwd()), + input_path=Path(os.path.relpath(JSON_SCHEMA_DATA_PATH / "person.json", Path.cwd())), output_path=output_file, input_file_type=InputFileType.JsonSchema, assert_func=assert_file_content, From 8d47735a3e3755a328ad995684987dc573753892 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 10 Mar 2026 20:11:53 +0000 Subject: [PATCH 5/6] Fix generate helper edge cases --- tests/main/conftest.py | 11 ++++++--- tests/main/jsonschema/test_main_jsonschema.py | 23 +++++++++++-------- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/tests/main/conftest.py b/tests/main/conftest.py index e586e2779..e562f4d78 100644 --- a/tests/main/conftest.py +++ b/tests/main/conftest.py @@ -263,11 +263,16 @@ def run_generate_file_and_assert( else: assert not input_.is_absolute() + generate_options: dict[str, Any] = { + "output": output_path, + **generate_kwargs, + } + if input_file_type is not None: + generate_options["input_file_type"] = input_file_type + generate( input_=input_, - input_file_type=input_file_type, - output=output_path, - **generate_kwargs, + **generate_options, ) if expected_file is None: diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index fe00a571e..0fa2f97a8 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -4,6 +4,7 @@ import json import os +import tempfile from collections import defaultdict from pathlib import Path from typing import TYPE_CHECKING @@ -1665,16 +1666,18 @@ def test_main_generate_relative_input_path(output_file: Path) -> None: def test_main_generate_external_absolute_input_path(tmp_path: Path) -> None: """Test helper keeps absolute input paths that are outside the repository root.""" - input_path = tmp_path / "person.json" - input_path.write_text((JSON_SCHEMA_DATA_PATH / "person.json").read_text(encoding="utf-8"), encoding="utf-8") - - run_generate_file_and_assert( - input_path=input_path, - output_path=tmp_path / "output.py", - input_file_type=InputFileType.JsonSchema, - assert_func=assert_file_content, - expected_file="general.py", - ) + with tempfile.TemporaryDirectory() as temp_dir: + input_path = Path(temp_dir) / "person.json" + assert Path.cwd() not in input_path.resolve().parents + input_path.write_text((JSON_SCHEMA_DATA_PATH / "person.json").read_text(encoding="utf-8"), encoding="utf-8") + + run_generate_file_and_assert( + input_path=input_path, + output_path=tmp_path / "output.py", + input_file_type=InputFileType.JsonSchema, + assert_func=assert_file_content, + expected_file="general.py", + ) def test_main_generate_pydantic_v2_dataclass(output_file: Path) -> None: From af16f88fed7c7833e12dcd3100e81b4f48393c36 Mon Sep 17 00:00:00 2001 From: Koudai Aono Date: Tue, 10 Mar 2026 20:20:25 +0000 Subject: [PATCH 6/6] Add coverage for omitted input file type --- tests/main/jsonschema/test_main_jsonschema.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/main/jsonschema/test_main_jsonschema.py b/tests/main/jsonschema/test_main_jsonschema.py index 0fa2f97a8..40a397eb2 100644 --- a/tests/main/jsonschema/test_main_jsonschema.py +++ b/tests/main/jsonschema/test_main_jsonschema.py @@ -1653,6 +1653,16 @@ def test_main_generate_non_pydantic_output(output_file: Path) -> None: ) +def test_main_generate_without_input_file_type(output_file: Path) -> None: + """Test helper preserves generate() input_file_type default behavior.""" + run_generate_file_and_assert( + input_path=JSON_SCHEMA_DATA_PATH / "person.json", + output_path=output_file, + assert_func=assert_file_content, + expected_file="general.py", + ) + + def test_main_generate_relative_input_path(output_file: Path) -> None: """Test helper with a relative input path.""" run_generate_file_and_assert(