From 588b35330cef8ef2447462382ff04d9b184d00a5 Mon Sep 17 00:00:00 2001 From: "Keto D. Zhang" Date: Sun, 25 Aug 2024 20:01:48 -0700 Subject: [PATCH] test: add tests for example rectangle --- tests/examples/test_node.py | 8 +- tests/examples/test_rectangle.py | 124 +++++++++++++++++++------------ 2 files changed, 83 insertions(+), 49 deletions(-) diff --git a/tests/examples/test_node.py b/tests/examples/test_node.py index d863f80..828f8d0 100644 --- a/tests/examples/test_node.py +++ b/tests/examples/test_node.py @@ -3,6 +3,7 @@ from __future__ import annotations import textwrap +from unittest.mock import MagicMock, patch import asdf import asdf.exceptions @@ -86,8 +87,9 @@ def test_can_write_valid_asdf_file(tmp_path): @pytest.mark.usefixtures("asdf_extension") +@patch.object(AsdfNode, "model_validate", MagicMock()) # Ignore pydantic validation def test_errors_reading_invalid_asdf_file(tmp_path): - """Tests validation fails when ASDF file does not match the schema.""" + """Tests ASDF validation fails when ASDF file does not match the schema.""" content = """\ #ASDF 1.0.0 #ASDF_STANDARD 1.5.0 @@ -109,8 +111,8 @@ def test_errors_reading_invalid_asdf_file(tmp_path): child: None ... """ - with open(tmp_path / "test.asdf", "wb") as f: - f.write(textwrap.dedent(content).encode("utf-8")) + with open(tmp_path / "test.asdf", "w") as f: + f.write(textwrap.dedent(content)) with pytest.raises(asdf.exceptions.ValidationError): with asdf.open(tmp_path / "test.asdf") as af: diff --git a/tests/examples/test_rectangle.py b/tests/examples/test_rectangle.py index bd24368..77adefc 100644 --- a/tests/examples/test_rectangle.py +++ b/tests/examples/test_rectangle.py @@ -1,58 +1,90 @@ +import textwrap +from unittest.mock import MagicMock, patch + import asdf import pytest +import yaml from asdf.extension import Extension -from asdf.schema import check_schema, load_schema -from yaml.scanner import ScannerError -from asdf_pydantic import AsdfPydanticConverter -from asdf_pydantic.examples.shapes import AsdfRectangle +from asdf_pydantic import AsdfPydanticConverter, AsdfPydanticModel + + +class AsdfRectangle(AsdfPydanticModel): + _tag = "asdf://asdf-pydantic/examples/tags/rectangle-1.0.0" + width: float + height: float -def setup_module(): +@pytest.fixture() +def asdf_extension(): + """Registers an ASDF extension containing models for this test.""" AsdfPydanticConverter.add_models(AsdfRectangle) class TestExtension(Extension): - extension_uri = "asdf://asdf-pydantic/examples/extensions/test-1.0.0" # type: ignore + extension_uri = "asdf://asdf-pydantic/examples/extensions/test-1.0.0" - tags = [*AsdfPydanticConverter().tags] # type: ignore converters = [AsdfPydanticConverter()] # type: ignore + tags = [AsdfRectangle.get_tag_definition()] # type: ignore + + with asdf.config_context() as asdf_config: + asdf_config.add_resource_mapping( + { + yaml.safe_load(AsdfRectangle.model_asdf_schema())[ + "id" + ]: AsdfRectangle.model_asdf_schema() + } + ) + asdf_config.add_extension(TestExtension()) + yield asdf_config + + +@pytest.mark.usefixtures("asdf_extension") +def test_can_write_valid_asdf_file(tmp_path): + """Tests using the model to write an ASDF file validates its own schema.""" + af = asdf.AsdfFile() + af["root"] = AsdfRectangle(width=42, height=10) + af.validate() + af.write_to(tmp_path / "test.asdf") + + with asdf.open(tmp_path / "test.asdf") as af: + assert af.tree + + +@pytest.mark.usefixtures("asdf_extension") +@patch.object( + AsdfRectangle, "model_validate", MagicMock() +) # Ignore pydantic validation +def test_errors_reading_invalid_asdf_file(tmp_path): + """Tests validation fails when ASDF file does not match the schema.""" + content = """\ + #ASDF 1.0.0 + #ASDF_STANDARD 1.5.0 + %YAML 1.1 + %TAG ! tag:stsci.edu:asdf/ + --- !core/asdf-1.1.0 + asdf_library: !core/software-1.0.0 { + author: The ASDF Developers, + homepage: 'http://github.com/asdf-format/asdf', + name: asdf, + version: 2.14.3} + history: + extensions: + - !core/extension_metadata-1.0.0 + extension_class: asdf.extension.BuiltinExtension + software: !core/software-1.0.0 { + name: asdf, + version: 2.14.3} + - !core/extension_metadata-1.0.0 { + extension_class: mypackage.shapes.ShapesExtension, + extension_uri: 'asdf://asdf-pydantic/shapes/extensions/shapes-1.0.0'} + rect: ! + height: "10" + width: "42" + ... + """ + with open(tmp_path / "test.asdf", "w") as f: + f.write(textwrap.dedent(content)) - # HACK: The schema URI should be referenced from `AsdfRectangle._schema`. - # Then there should be a way to automatically add the schema to ASDF - # resources perhaps during AsdfPydanticConverter.add_models(). Further - # abstracting can be done later, perhaps defining a - # AsdfPydanticExtension. - asdf.get_config().add_resource_mapping( - { - "asdf://asdf-pydantic/shapes/schemas/rectangle-1.0.0": ( - AsdfRectangle.model_asdf_schema().encode("utf-8") - ) - } - ) - asdf.get_config().add_extension(TestExtension()) - - -def test_schema(): - try: - schema = load_schema("asdf://asdf-pydantic/shapes/schemas/rectangle-1.0.0") - check_schema(schema) - except ScannerError as e: - pytest.fail(f"{e}\n{AsdfRectangle.model_asdf_schema()}") - - assert schema["$schema"] == "http://stsci.edu/schemas/asdf/asdf-schema-1.0.0" - assert schema["title"] == "AsdfRectangle" - assert schema["id"] == "asdf://asdf-pydantic/examples/tags/rectangle-1.0.0" - assert schema["tag"] == "tag:asdf-pydantic/examples/tags/rectangle-1.0.0" - assert schema["type"] == "object" - assert schema["properties"] == { - "width": { - "type": "number", - "title": "Width", - }, - "height": { - "type": "number", - "title": "Height", - }, - } - - assert schema["required"] == ["width", "height"] + with pytest.raises(asdf.exceptions.ValidationError): + with asdf.open(tmp_path / "test.asdf") as af: + assert af.tree