From 1cb92df0c0b10e47ecc2b923a95b73cd455b605a Mon Sep 17 00:00:00 2001 From: zshengan Date: Sat, 7 Mar 2026 23:29:41 -0800 Subject: [PATCH 1/6] refactor: move universal tests into dedicated universal tree Restructure cross-backend Python tests into new universal directories, and relocate auth/unit outliers to align with the test taxonomy in issue #6051 while updating docs and Makefile paths. Made-with: Cursor --- Makefile | 6 +++--- docs/how-to-guides/adding-or-reusing-tests.md | 2 +- sdk/python/tests/README.md | 2 +- .../{online_store => auth}/test_remote_online_store.py | 0 .../online_store => unit}/test_hybrid_online_store.py | 0 .../{integration => universal}/cli/test_universal_cli.py | 0 sdk/python/tests/universal/conftest.py | 8 ++++++++ .../materialization/test_universal_materialization.py | 0 .../offline_store/test_dqm_validation.py | 0 .../offline_store/test_feature_logging.py | 0 .../offline_store/test_offline_write.py | 0 .../offline_store/test_persist.py | 0 .../offline_store/test_push_features_to_offline_store.py | 0 .../offline_store/test_universal_historical_retrieval.py | 0 .../offline_store/test_universal_types.py | 0 .../{integration => universal}/online_store/__init__.py | 0 .../online_store/test_push_features_to_online_store.py | 0 .../online_store/test_universal_e2e.py | 0 .../online_store/test_universal_online.py | 0 .../online_store/test_universal_online_types.py | 0 .../registration/test_feature_store.py | 0 .../registration/test_inference.py | 0 .../registration/test_universal_odfv_feature_inference.py | 0 .../registration/test_universal_registry.py | 0 24 files changed, 13 insertions(+), 5 deletions(-) rename sdk/python/tests/integration/{online_store => auth}/test_remote_online_store.py (100%) rename sdk/python/tests/{integration/online_store => unit}/test_hybrid_online_store.py (100%) rename sdk/python/tests/{integration => universal}/cli/test_universal_cli.py (100%) create mode 100644 sdk/python/tests/universal/conftest.py rename sdk/python/tests/{integration => universal}/materialization/test_universal_materialization.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_dqm_validation.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_feature_logging.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_offline_write.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_persist.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_push_features_to_offline_store.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_universal_historical_retrieval.py (100%) rename sdk/python/tests/{integration => universal}/offline_store/test_universal_types.py (100%) rename sdk/python/tests/{integration => universal}/online_store/__init__.py (100%) rename sdk/python/tests/{integration => universal}/online_store/test_push_features_to_online_store.py (100%) rename sdk/python/tests/{integration => universal}/online_store/test_universal_e2e.py (100%) rename sdk/python/tests/{integration => universal}/online_store/test_universal_online.py (100%) rename sdk/python/tests/{integration => universal}/online_store/test_universal_online_types.py (100%) rename sdk/python/tests/{integration => universal}/registration/test_feature_store.py (100%) rename sdk/python/tests/{integration => universal}/registration/test_inference.py (100%) rename sdk/python/tests/{integration => universal}/registration/test_universal_odfv_feature_inference.py (100%) rename sdk/python/tests/{integration => universal}/registration/test_universal_registry.py (100%) diff --git a/Makefile b/Makefile index 58c99b8c984..b6bf2d89cd0 100644 --- a/Makefile +++ b/Makefile @@ -474,7 +474,7 @@ test-python-universal-cassandra: ## Run Python Cassandra integration tests FULL_REPO_CONFIGS_MODULE=sdk.python.feast.infra.online_stores.cassandra_online_store.cassandra_repo_configuration \ PYTEST_PLUGINS=sdk.python.tests.universal.feature_repos.universal.online_store.cassandra \ python -m pytest -x --integration \ - sdk/python/tests/integration/offline_store/test_feature_logging.py \ + sdk/python/tests/universal/offline_store/test_feature_logging.py \ --ignore=sdk/python/tests/integration/offline_store/test_validation.py \ -k "not test_snowflake and \ not test_spark_materialization_consistency and \ @@ -560,7 +560,7 @@ test-python-universal-milvus-online: ## Run Python Milvus online store integrati PYTEST_PLUGINS=sdk.python.tests.universal.feature_repos.universal.online_store.milvus \ python -m pytest -n 8 --integration \ -k "test_retrieve_online_milvus_documents" \ - sdk/python/tests --ignore=sdk/python/tests/integration/offline_store/test_dqm_validation.py + sdk/python/tests --ignore=sdk/python/tests/universal/offline_store/test_dqm_validation.py test-python-universal-singlestore-online: ## Run Python Singlestore online store integration tests PYTHONPATH='.' \ @@ -579,7 +579,7 @@ test-python-universal-qdrant-online: ## Run Python Qdrant online store integrati PYTEST_PLUGINS=sdk.python.tests.universal.feature_repos.universal.online_store.qdrant \ python -m pytest -n 8 --integration \ -k "test_retrieve_online_documents" \ - sdk/python/tests/integration/online_store/test_universal_online.py + sdk/python/tests/universal/online_store/test_universal_online.py # To use Couchbase as an offline store, you need to create an Couchbase Capella Columnar cluster on cloud.couchbase.com. # Modify environment variables COUCHBASE_COLUMNAR_CONNECTION_STRING, COUCHBASE_COLUMNAR_USER, and COUCHBASE_COLUMNAR_PASSWORD diff --git a/docs/how-to-guides/adding-or-reusing-tests.md b/docs/how-to-guides/adding-or-reusing-tests.md index b7c01a04b02..21b7a9705ab 100644 --- a/docs/how-to-guides/adding-or-reusing-tests.md +++ b/docs/how-to-guides/adding-or-reusing-tests.md @@ -158,7 +158,7 @@ Docstring tests are primarily smoke tests to make sure imports and setup functio Let's look at a sample test using the universal repo: {% tabs %} -{% tab code="sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py" %} +{% tab code="sdk/python/tests/universal/offline_store/test_universal_historical_retrieval.py" %} ```python @pytest.mark.integration @pytest.mark.universal_offline_stores diff --git a/sdk/python/tests/README.md b/sdk/python/tests/README.md index 418e2131928..c7723a3a9e5 100644 --- a/sdk/python/tests/README.md +++ b/sdk/python/tests/README.md @@ -158,7 +158,7 @@ Docstring tests are primarily smoke tests to make sure imports and setup functio Let's look at a sample test using the universal repo: {% tabs %} -{% tab code="sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py" %} +{% tab code="sdk/python/tests/universal/offline_store/test_universal_historical_retrieval.py" %} ```python @pytest.mark.integration @pytest.mark.universal_offline_stores diff --git a/sdk/python/tests/integration/online_store/test_remote_online_store.py b/sdk/python/tests/integration/auth/test_remote_online_store.py similarity index 100% rename from sdk/python/tests/integration/online_store/test_remote_online_store.py rename to sdk/python/tests/integration/auth/test_remote_online_store.py diff --git a/sdk/python/tests/integration/online_store/test_hybrid_online_store.py b/sdk/python/tests/unit/test_hybrid_online_store.py similarity index 100% rename from sdk/python/tests/integration/online_store/test_hybrid_online_store.py rename to sdk/python/tests/unit/test_hybrid_online_store.py diff --git a/sdk/python/tests/integration/cli/test_universal_cli.py b/sdk/python/tests/universal/cli/test_universal_cli.py similarity index 100% rename from sdk/python/tests/integration/cli/test_universal_cli.py rename to sdk/python/tests/universal/cli/test_universal_cli.py diff --git a/sdk/python/tests/universal/conftest.py b/sdk/python/tests/universal/conftest.py new file mode 100644 index 00000000000..99d6fa823b3 --- /dev/null +++ b/sdk/python/tests/universal/conftest.py @@ -0,0 +1,8 @@ +"""Universal test fixtures. + +Load shared integration fixtures for universal tests. +After moving tests from `integration/*` to `universal/*`, pytest no longer +discovers `tests/integration/conftest.py` through parent-directory traversal. +""" + +pytest_plugins = ["tests.integration.conftest"] diff --git a/sdk/python/tests/integration/materialization/test_universal_materialization.py b/sdk/python/tests/universal/materialization/test_universal_materialization.py similarity index 100% rename from sdk/python/tests/integration/materialization/test_universal_materialization.py rename to sdk/python/tests/universal/materialization/test_universal_materialization.py diff --git a/sdk/python/tests/integration/offline_store/test_dqm_validation.py b/sdk/python/tests/universal/offline_store/test_dqm_validation.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_dqm_validation.py rename to sdk/python/tests/universal/offline_store/test_dqm_validation.py diff --git a/sdk/python/tests/integration/offline_store/test_feature_logging.py b/sdk/python/tests/universal/offline_store/test_feature_logging.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_feature_logging.py rename to sdk/python/tests/universal/offline_store/test_feature_logging.py diff --git a/sdk/python/tests/integration/offline_store/test_offline_write.py b/sdk/python/tests/universal/offline_store/test_offline_write.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_offline_write.py rename to sdk/python/tests/universal/offline_store/test_offline_write.py diff --git a/sdk/python/tests/integration/offline_store/test_persist.py b/sdk/python/tests/universal/offline_store/test_persist.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_persist.py rename to sdk/python/tests/universal/offline_store/test_persist.py diff --git a/sdk/python/tests/integration/offline_store/test_push_features_to_offline_store.py b/sdk/python/tests/universal/offline_store/test_push_features_to_offline_store.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_push_features_to_offline_store.py rename to sdk/python/tests/universal/offline_store/test_push_features_to_offline_store.py diff --git a/sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py b/sdk/python/tests/universal/offline_store/test_universal_historical_retrieval.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_universal_historical_retrieval.py rename to sdk/python/tests/universal/offline_store/test_universal_historical_retrieval.py diff --git a/sdk/python/tests/integration/offline_store/test_universal_types.py b/sdk/python/tests/universal/offline_store/test_universal_types.py similarity index 100% rename from sdk/python/tests/integration/offline_store/test_universal_types.py rename to sdk/python/tests/universal/offline_store/test_universal_types.py diff --git a/sdk/python/tests/integration/online_store/__init__.py b/sdk/python/tests/universal/online_store/__init__.py similarity index 100% rename from sdk/python/tests/integration/online_store/__init__.py rename to sdk/python/tests/universal/online_store/__init__.py diff --git a/sdk/python/tests/integration/online_store/test_push_features_to_online_store.py b/sdk/python/tests/universal/online_store/test_push_features_to_online_store.py similarity index 100% rename from sdk/python/tests/integration/online_store/test_push_features_to_online_store.py rename to sdk/python/tests/universal/online_store/test_push_features_to_online_store.py diff --git a/sdk/python/tests/integration/online_store/test_universal_e2e.py b/sdk/python/tests/universal/online_store/test_universal_e2e.py similarity index 100% rename from sdk/python/tests/integration/online_store/test_universal_e2e.py rename to sdk/python/tests/universal/online_store/test_universal_e2e.py diff --git a/sdk/python/tests/integration/online_store/test_universal_online.py b/sdk/python/tests/universal/online_store/test_universal_online.py similarity index 100% rename from sdk/python/tests/integration/online_store/test_universal_online.py rename to sdk/python/tests/universal/online_store/test_universal_online.py diff --git a/sdk/python/tests/integration/online_store/test_universal_online_types.py b/sdk/python/tests/universal/online_store/test_universal_online_types.py similarity index 100% rename from sdk/python/tests/integration/online_store/test_universal_online_types.py rename to sdk/python/tests/universal/online_store/test_universal_online_types.py diff --git a/sdk/python/tests/integration/registration/test_feature_store.py b/sdk/python/tests/universal/registration/test_feature_store.py similarity index 100% rename from sdk/python/tests/integration/registration/test_feature_store.py rename to sdk/python/tests/universal/registration/test_feature_store.py diff --git a/sdk/python/tests/integration/registration/test_inference.py b/sdk/python/tests/universal/registration/test_inference.py similarity index 100% rename from sdk/python/tests/integration/registration/test_inference.py rename to sdk/python/tests/universal/registration/test_inference.py diff --git a/sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py b/sdk/python/tests/universal/registration/test_universal_odfv_feature_inference.py similarity index 100% rename from sdk/python/tests/integration/registration/test_universal_odfv_feature_inference.py rename to sdk/python/tests/universal/registration/test_universal_odfv_feature_inference.py diff --git a/sdk/python/tests/integration/registration/test_universal_registry.py b/sdk/python/tests/universal/registration/test_universal_registry.py similarity index 100% rename from sdk/python/tests/integration/registration/test_universal_registry.py rename to sdk/python/tests/universal/registration/test_universal_registry.py From fcad0271564a0c4402125b02252a10231e063814 Mon Sep 17 00:00:00 2001 From: zshengan Date: Sat, 14 Mar 2026 16:26:16 -0700 Subject: [PATCH 2/6] fix: update integration ignore path for moved registration tests Point integration test targets to ignore sdk/python/tests/universal/registration after the test restructure so registration suites remain excluded as intended. Signed-off-by: zshengan Made-with: Cursor --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b6bf2d89cd0..f4c3c67667e 100644 --- a/Makefile +++ b/Makefile @@ -188,7 +188,7 @@ test-python-integration: ## Run Python integration tests (CI) uv run python -m pytest --tb=short -v -n 8 --integration --color=yes --durations=10 --timeout=1200 --timeout_method=thread --dist loadgroup \ -k "(not snowflake or not test_historical_features_main)" \ -m "not rbac_remote_integration_test and not ray_offline_stores_only" \ - --ignore=sdk/python/tests/integration/registration \ + --ignore=sdk/python/tests/universal/registration \ --ignore=sdk/python/tests/component/ray \ --log-cli-level=INFO -s \ sdk/python/tests @@ -207,7 +207,7 @@ test-python-integration-local: ## Run Python integration tests (local dev mode) -k "not test_lambda_materialization and not test_snowflake_materialization" \ -m "not rbac_remote_integration_test and not ray_offline_stores_only" \ --ignore=sdk/python/tests/component/ray \ - --ignore=sdk/python/tests/integration/registration \ + --ignore=sdk/python/tests/universal/registration \ --log-cli-level=INFO -s \ sdk/python/tests From f9ac5146ac7d87f63332d129324eaaf1bd328f9c Mon Sep 17 00:00:00 2001 From: zshengan Date: Sat, 14 Mar 2026 16:39:22 -0700 Subject: [PATCH 3/6] fix: add integration auth package initializer Add missing __init__.py under sdk/python/tests/integration/auth after moving test_remote_online_store.py to keep package structure consistent. Signed-off-by: zshengan Made-with: Cursor --- sdk/python/tests/integration/auth/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 sdk/python/tests/integration/auth/__init__.py diff --git a/sdk/python/tests/integration/auth/__init__.py b/sdk/python/tests/integration/auth/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/tests/integration/auth/__init__.py @@ -0,0 +1 @@ + From 59f7a909ecd56e4215c55da7d66c0cb656160001 Mon Sep 17 00:00:00 2001 From: zshengan Date: Sat, 14 Mar 2026 16:47:01 -0700 Subject: [PATCH 4/6] fix: add missing package initializers in universal test directories Add __init__.py files to moved universal test subdirectories so pytest module imports and package discovery remain consistent. Signed-off-by: zshengan Made-with: Cursor --- sdk/python/tests/universal/cli/__init__.py | 1 + sdk/python/tests/universal/feature_repos/__init__.py | 1 + sdk/python/tests/universal/materialization/__init__.py | 1 + sdk/python/tests/universal/offline_store/__init__.py | 1 + sdk/python/tests/universal/registration/__init__.py | 1 + 5 files changed, 5 insertions(+) create mode 100644 sdk/python/tests/universal/cli/__init__.py create mode 100644 sdk/python/tests/universal/feature_repos/__init__.py create mode 100644 sdk/python/tests/universal/materialization/__init__.py create mode 100644 sdk/python/tests/universal/offline_store/__init__.py create mode 100644 sdk/python/tests/universal/registration/__init__.py diff --git a/sdk/python/tests/universal/cli/__init__.py b/sdk/python/tests/universal/cli/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/tests/universal/cli/__init__.py @@ -0,0 +1 @@ + diff --git a/sdk/python/tests/universal/feature_repos/__init__.py b/sdk/python/tests/universal/feature_repos/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/tests/universal/feature_repos/__init__.py @@ -0,0 +1 @@ + diff --git a/sdk/python/tests/universal/materialization/__init__.py b/sdk/python/tests/universal/materialization/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/tests/universal/materialization/__init__.py @@ -0,0 +1 @@ + diff --git a/sdk/python/tests/universal/offline_store/__init__.py b/sdk/python/tests/universal/offline_store/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/tests/universal/offline_store/__init__.py @@ -0,0 +1 @@ + diff --git a/sdk/python/tests/universal/registration/__init__.py b/sdk/python/tests/universal/registration/__init__.py new file mode 100644 index 00000000000..8b137891791 --- /dev/null +++ b/sdk/python/tests/universal/registration/__init__.py @@ -0,0 +1 @@ + From a6d8fac17fe393e2c2817cf5b8f3740e1d0f9888 Mon Sep 17 00:00:00 2001 From: Shengan Zhang Date: Sun, 5 Apr 2026 15:04:48 -0700 Subject: [PATCH 5/6] Update Makefile Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f4c3c67667e..1be68a4f49b 100644 --- a/Makefile +++ b/Makefile @@ -475,7 +475,7 @@ test-python-universal-cassandra: ## Run Python Cassandra integration tests PYTEST_PLUGINS=sdk.python.tests.universal.feature_repos.universal.online_store.cassandra \ python -m pytest -x --integration \ sdk/python/tests/universal/offline_store/test_feature_logging.py \ - --ignore=sdk/python/tests/integration/offline_store/test_validation.py \ + --ignore=sdk/python/tests/universal/offline_store/test_dqm_validation.py \ -k "not test_snowflake and \ not test_spark_materialization_consistency and \ not test_universal_materialization" From 9e4e1220fbf1084035b2be8ba7478c9277a6bf3f Mon Sep 17 00:00:00 2001 From: zshengan Date: Sun, 5 Apr 2026 15:30:51 -0700 Subject: [PATCH 6/6] fix: update stale universal test paths in build tasks Update Makefile and pixi task test paths to use the moved universal registration and offline store directories so excludes and targeted runs still execute the intended suites. Signed-off-by: zshengan Made-with: Cursor --- pyproject.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3ba14b4ee47..8c51c0e3f32 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -287,13 +287,13 @@ python = "~=3.10.0" feast = { path = ".", editable = true, extras = ["duckdb", "delta", "grpcio", "test"] } [tool.pixi.feature.duckdb-tests.tasks] -test = { cmd = "python -m pytest -n 8 --integration -m 'not ray_offline_stores_only' --ignore=sdk/python/tests/integration/offline_store/test_dqm_validation.py sdk/python/tests/integration/offline_store", env = { PYTHONPATH = ".", FULL_REPO_CONFIGS_MODULE = "sdk.python.tests.universal.feature_repos.duckdb_repo_configuration", FEAST_IS_LOCAL_TEST = "True" } } +test = { cmd = "python -m pytest -n 8 --integration -m 'not ray_offline_stores_only' --ignore=sdk/python/tests/universal/offline_store/test_dqm_validation.py sdk/python/tests/universal/offline_store", env = { PYTHONPATH = ".", FULL_REPO_CONFIGS_MODULE = "sdk.python.tests.universal.feature_repos.duckdb_repo_configuration", FEAST_IS_LOCAL_TEST = "True" } } [tool.pixi.feature.ray-tests.pypi-dependencies] feast = { path = ".", editable = true, extras = ["ray", "grpcio", "test"] } [tool.pixi.feature.ray-tests.tasks] -test-offline = { cmd = "python -m pytest -v --integration --ignore=sdk/python/tests/integration/offline_store/test_dqm_validation.py sdk/python/tests/integration/offline_store", env = { PYTHONPATH = ".", FULL_REPO_CONFIGS_MODULE = "sdk.python.tests.universal.feature_repos.ray_repo_configuration", FEAST_IS_LOCAL_TEST = "True" } } +test-offline = { cmd = "python -m pytest -v --integration --ignore=sdk/python/tests/universal/offline_store/test_dqm_validation.py sdk/python/tests/universal/offline_store", env = { PYTHONPATH = ".", FULL_REPO_CONFIGS_MODULE = "sdk.python.tests.universal.feature_repos.ray_repo_configuration", FEAST_IS_LOCAL_TEST = "True" } } test-compute = { cmd = "python -m pytest -v --integration sdk/python/tests/component/ray", env = { PYTHONPATH = ".", FEAST_IS_LOCAL_TEST = "True" } } test = { depends-on = ["test-offline", "test-compute"] } @@ -302,8 +302,8 @@ feast = { path = ".", editable = true, extras = ["aws", "gcp", "grpcio", "postgr grpcio-testing = ">=1.56.2,<=1.62.3" [tool.pixi.feature.registration-tests.tasks] -test = { cmd = "python -m pytest -n auto --dist loadgroup --integration sdk/python/tests/integration/registration", env = { PYTHONPATH = ".", FEAST_IS_LOCAL_TEST = "True" } } -test-ci = { cmd = "python -m pytest -n auto --dist loadgroup --integration sdk/python/tests/integration/registration", env = { PYTHONPATH = "." } } +test = { cmd = "python -m pytest -n auto --dist loadgroup --integration sdk/python/tests/universal/registration", env = { PYTHONPATH = ".", FEAST_IS_LOCAL_TEST = "True" } } +test-ci = { cmd = "python -m pytest -n auto --dist loadgroup --integration sdk/python/tests/universal/registration", env = { PYTHONPATH = "." } } [tool.pixi.environments] duckdb-tests = ["py310", "duckdb-tests"]