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: