This is an automated email from the ASF dual-hosted git repository.

potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 9bd7d147b83 Add missing unit tests for common.compat lineage entities 
(#72506)
9bd7d147b83 is described below

commit 9bd7d147b83d50665d76ce85f11e2099f2ca86eb
Author: Keith <[email protected]>
AuthorDate: Thu Sep 10 17:40:06 2026 +0900

    Add missing unit tests for common.compat lineage entities (#72506)
    
    The module was listed in OVERLOOKED_TESTS in test_project_structure.py;
    covering it lets the guard list shrink toward zero (related: #35442).
---
 .../tests/unit/always/test_project_structure.py    |   1 -
 .../unit/common/compat/lineage/test_entities.py    | 125 ++++++++++++++++++++-
 2 files changed, 124 insertions(+), 2 deletions(-)

diff --git a/airflow-core/tests/unit/always/test_project_structure.py 
b/airflow-core/tests/unit/always/test_project_structure.py
index 509243e21e4..923790bd76a 100644
--- a/airflow-core/tests/unit/always/test_project_structure.py
+++ b/airflow-core/tests/unit/always/test_project_structure.py
@@ -95,7 +95,6 @@ class TestProjectStructure:
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/utils/test_delete_from.py",
             
"providers/cncf/kubernetes/tests/unit/cncf/kubernetes/utils/test_k8s_hashlib_wrapper.py",
             "providers/common/ai/tests/unit/common/ai/test_exceptions.py",
-            
"providers/common/compat/tests/unit/common/compat/lineage/test_entities.py",
             
"providers/common/compat/tests/unit/common/compat/standard/test_operators.py",
             
"providers/common/compat/tests/unit/common/compat/standard/test_triggers.py",
             
"providers/common/compat/tests/unit/common/compat/standard/test_utils.py",
diff --git 
a/providers/common/compat/tests/unit/common/compat/lineage/test_entities.py 
b/providers/common/compat/tests/unit/common/compat/lineage/test_entities.py
index 9ec0ea72675..db5d4ce7992 100644
--- a/providers/common/compat/tests/unit/common/compat/lineage/test_entities.py
+++ b/providers/common/compat/tests/unit/common/compat/lineage/test_entities.py
@@ -16,7 +16,130 @@
 # under the License.
 from __future__ import annotations
 
-from airflow.providers.common.compat.lineage.entities import Column, Table, 
Tag, User
+import attr
+import pytest
+
+from airflow.providers.common.compat.lineage.entities import (
+    Column,
+    File,
+    Table,
+    Tag,
+    User,
+    default_if_none,
+)
+
+
+class TestFile:
+    def test_accepts_positional_url_and_defaults(self):
+        file = File("s3://bucket/key")
+
+        assert file.url == "s3://bucket/key"
+        assert file.type_hint is None
+
+    def test_equality_is_value_based(self):
+        assert File(url="s3://bucket/key") == File(url="s3://bucket/key")
+        assert File(url="s3://bucket/key") != File(url="s3://bucket/other")
+
+
+class TestKeywordOnlyEntities:
+    @pytest.mark.parametrize(
+        ("entity_class", "positional_args"),
+        [
+            (User, ("[email protected]",)),
+            (Tag, ("pii",)),
+            (Column, ("name", None, "VARCHAR")),
+            (Table, ("db", "cluster", "name")),
+        ],
+    )
+    def test_rejects_positional_arguments(self, entity_class, positional_args):
+        with pytest.raises(TypeError):
+            entity_class(*positional_args)
+
+    @pytest.mark.parametrize(
+        ("entity_class", "kwargs"),
+        [
+            (User, {}),
+            (Column, {"name": "id"}),
+            (Table, {"database": "db", "cluster": "c"}),
+        ],
+    )
+    def test_rejects_missing_required_fields(self, entity_class, kwargs):
+        with pytest.raises(TypeError):
+            entity_class(**kwargs)
+
+
+class TestUser:
+    def test_optional_name_fields_default_to_none(self):
+        user = User(email="[email protected]")
+
+        assert user.email == "[email protected]"
+        assert user.first_name is None
+        assert user.last_name is None
+
+
+class TestColumn:
+    def test_defaults(self):
+        column = Column(name="id", data_type="INTEGER")
+
+        assert column.description is None
+        assert column.tags == []
+
+
+class TestTable:
+    def test_defaults(self):
+        table = Table(database="db", cluster="cluster", name="orders")
+
+        assert table.tags == []
+        assert table.description is None
+        assert table.columns == []
+        assert table.owners == []
+        assert table.extra == {}
+        assert table.type_hint is None
+
+    def test_asdict_serializes_nested_entities(self):
+        table = Table(
+            database="db",
+            cluster="cluster",
+            name="orders",
+            tags=[Tag(tag_name="pii")],
+            columns=[Column(name="id", data_type="INTEGER", 
tags=[Tag(tag_name="key")])],
+            owners=[User(email="[email protected]", first_name="Ada")],
+            extra={"source": "warehouse"},
+        )
+
+        serialized = attr.asdict(table)
+
+        assert serialized["tags"] == [{"tag_name": "pii"}]
+        assert serialized["columns"][0]["name"] == "id"
+        assert serialized["columns"][0]["tags"] == [{"tag_name": "key"}]
+        assert serialized["owners"][0]["email"] == "[email protected]"
+        assert serialized["extra"] == {"source": "warehouse"}
+
+
[email protected](
+    ("entity_class", "expected"),
+    [
+        (File, ("url",)),
+        (User, ("email", "first_name", "last_name")),
+        (Tag, ("tag_name",)),
+        (Column, ("name", "description", "data_type", "tags")),
+        (Table, ("database", "cluster", "name", "tags", "description", 
"columns", "owners", "extra")),
+    ],
+)
+def test_template_fields(entity_class, expected):
+    assert entity_class.template_fields == expected
+
+
[email protected](
+    ("arg", "expected"),
+    [
+        (None, False),
+        (False, False),
+        (True, True),
+    ],
+)
+def test_default_if_none(arg, expected):
+    assert default_if_none(arg) is expected
 
 
 class TestMutableDefaultsAreNotShared:

Reply via email to