Skip to content
48 changes: 47 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@
from utilities.infra import update_configmap_data
from utilities.logger import RedactedString
from utilities.minio import create_minio_data_connection_secret
from utilities.operator_utils import get_csv_related_images
from utilities.operator_utils import get_csv_related_images, get_cluster_service_version
from utilities.version_utils import compare_versions

LOGGER = get_logger(name=__name__)

Expand All @@ -72,6 +73,51 @@ def current_client_token(admin_client: DynamicClient) -> str:
return RedactedString(value=get_openshift_token())


@pytest.fixture(scope="session", autouse=True)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this PR. We branch based on version. Why not remove not needed tests directly from the branches?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but sometimes we submit a PR for an RHOAI N+2 branch feature that is expected to fail and create noise, since the dependent code from other components hasn't been merged yet. In such cases, this approach would be more efficient than manually adding or removing skip flags, IMO.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not a good idea. Your test branch should reflect associated product branch behavior. Adding programmatic skips is not a good idea. Please use jira marker or xfail.

def get_rhoai_csv_version(admin_client: DynamicClient, dsci_resource: DSCInitialization) -> str:
"""
Get RHOAI CSV version. This fixture depends on dsci_resource to ensure
global config is properly initialized first.
"""
namespace = py_config["applications_namespace"]
distribution = py_config["distribution"]

# Determine the correct CSV prefix based on distribution
prefix = "rhods" if distribution == "downstream" else "opendatahub"

csv = get_cluster_service_version(client=admin_client, prefix=prefix, namespace=namespace)
version = csv.instance.spec.version
py_config["current_rhods_version"] = version
return version


@pytest.fixture(scope="function")
def skip_if_downstream_version_greater_than(request: FixtureRequest, get_rhoai_csv_version: str) -> None:
if not hasattr(request, "param"):
raise ValueError("This fixture requires a parameter.Use @pytest.mark.parametrize with indirect=True")

threshold_version = request.param
current_version = get_rhoai_csv_version
distribution = py_config.get("distribution", "")

if distribution == "downstream" and compare_versions(current_version, threshold_version) > 0:
pytest.skip(f"Skipping test: downstream RHODS version {current_version} > {threshold_version}")


@pytest.fixture(scope="function")
def skip_if_downstream_version_less_than(request: FixtureRequest, get_rhoai_csv_version: str) -> None:
if not hasattr(request, "param"):
raise ValueError("This fixture requires a parameter. Use @pytest.mark.parametrize with indirect=True")

threshold_version = request.param
current_version = get_rhoai_csv_version
distribution = py_config.get("distribution", "")

if distribution == "downstream":
if compare_versions(current_version, threshold_version) < 0:
pytest.skip(f"Skipping test: downstream RHODS version {current_version} < {threshold_version}")


@pytest.fixture(scope="session")
def teardown_resources(pytestconfig: pytest.Config) -> bool:
delete_resources = True
Expand Down
92 changes: 92 additions & 0 deletions utilities/version_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
import pytest
from typing import Any
from simple_logger.logger import get_logger

LOGGER = get_logger(name=__name__)


def compare_versions(version1: str, version2: str) -> int:
"""
Compare two version strings.
Returns: -1 if version1 < version2, 0 if equal, 1 if version1 > version2
"""
from packaging import version

try:
return (version.parse(version1) > version.parse(version2)) - (version.parse(version1) < version.parse(version2))
except Exception as e:
LOGGER.error(f"[VERSION COMPARE] Error comparing versions: {e}")
return 0


def skip_if_version_less_than(min_version: str) -> tuple[Any, ...]:
"""
Skip tests if version is less than specified minimum.

Works for both UPSTREAM and DOWNSTREAM distributions:
- DOWNSTREAM: Uses RHODS version checking
- UPSTREAM: Uses environment variable control

Usage:
pytestmark = [
pytest.mark.serverless,
*skip_if_version_less_than("2.23.0"),
]
Args:
min_version: Minimum required version (e.g., "2.23.0")

Returns:
Tuple of pytest marks for downstream OR skipif mark for upstream
"""
try:
from pytest_testconfig import config as py_config

distribution = py_config.get("distribution", "")

if distribution == "downstream":
# Use existing RHODS version checking fixtures
return (
pytest.mark.parametrize("skip_if_downstream_version_less_than", [min_version], indirect=True),
pytest.mark.usefixtures("skip_if_downstream_version_less_than"),
)
else:
# For non-downstream distributions, return empty tuple
return ()
except Exception as e:
print(f"⚠️ Version check setup failed: {e}, proceeding with test")
return ()


def skip_if_version_greater_than(max_version: str) -> tuple[Any, ...]:
"""
Skip tests if version is greater than specified maximum.

Usage:
pytestmark = [
pytest.mark.serverless,
*skip_if_version_greater_than("2.25.0"),
]

Args:
max_version: Maximum allowed version (e.g., "2.25.0")

Returns:
Tuple of pytest marks for downstream
"""
try:
from pytest_testconfig import config as py_config

distribution = py_config.get("distribution", "")

if distribution == "downstream":
# Use existing RHODS version checking fixtures
return (
pytest.mark.parametrize("skip_if_downstream_version_greater_than", [max_version], indirect=True),
pytest.mark.usefixtures("skip_if_downstream_version_greater_than"),
)
else:
# For non-downstream distributions, return empty tuple
return ()
except Exception as e:
print(f"⚠️ Version check setup failed: {e}, proceeding with test")
return ()