Skip to content

Commit dbd7a4f

Browse files
test(admin): skip optional-extra tests when opik/comet_mpm absent (fix CI)
CI installs only requirements.txt (opik present, comet_mpm not), but the growth-report tests patched comet_mpm/opik unconditionally, erroring at setup with ModuleNotFoundError. Guard the SDK-patching tests with skipif(find_spec(...) is None), and make the two cross-platform assembly tests env-independent by forcing the resolved platform set instead of relying on which optional extras happen to be installed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent ae33492 commit dbd7a4f

1 file changed

Lines changed: 36 additions & 1 deletion

File tree

tests/unit/test_admin_growth_report.py

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
import datetime
22
import importlib
3+
import importlib.util
34
from unittest.mock import MagicMock, patch
45

6+
import pytest
7+
8+
# opik and comet_mpm are OPTIONAL extras (cometx[all]); CI installs neither by
9+
# default (opik happens to be in requirements.txt, comet_mpm is not). Tests that
10+
# patch those SDKs must be skipped when the extra isn't importable, otherwise
11+
# `@patch("comet_mpm.API")` errors at setup with ModuleNotFoundError.
12+
requires_opik = pytest.mark.skipif(
13+
importlib.util.find_spec("opik") is None,
14+
reason="opik extra not installed (cometx[all])",
15+
)
16+
requires_mpm = pytest.mark.skipif(
17+
importlib.util.find_spec("comet_mpm") is None,
18+
reason="comet_mpm extra not installed (cometx[all])",
19+
)
20+
521

622
def test_creation_event_and_window():
723
from cometx.cli.admin_growth_report import CreationEvent, Window
@@ -300,6 +316,7 @@ def _make_opik_metrics_response(datapoints):
300316
"cometx.cli.smoke_test.get_opik_config",
301317
return_value="https://example.com/opik/api/",
302318
)
319+
@requires_opik
303320
@patch("opik.Opik")
304321
def test_collect_opik_creation_events_and_span_count_usage(mock_opik_ctor, _mock_host):
305322
from cometx.cli.admin_growth_report import GrowthReporter
@@ -371,6 +388,7 @@ def get_project_metrics(project_id, **kwargs):
371388
"cometx.cli.smoke_test.get_opik_config",
372389
return_value="https://example.com/opik/api/",
373390
)
391+
@requires_opik
374392
@patch("opik.Opik")
375393
def test_collect_opik_respects_limit_on_workspaces(mock_opik_ctor, _mock_host):
376394
from cometx.cli.admin_growth_report import GrowthReporter
@@ -404,6 +422,7 @@ def test_collect_opik_respects_limit_on_workspaces(mock_opik_ctor, _mock_host):
404422
"cometx.cli.smoke_test.get_opik_config",
405423
return_value="https://example.com/opik/api/",
406424
)
425+
@requires_opik
407426
@patch("opik.Opik")
408427
def test_collect_opik_skips_bad_workspace_and_continues(
409428
mock_opik_ctor, _mock_host, capsys
@@ -516,6 +535,7 @@ def _mpm_workspaces_resp(models_by_ws):
516535
}
517536

518537

538+
@requires_mpm
519539
@patch("comet_mpm.API")
520540
def test_collect_mpm_creation_scenarios_a_b_c(mock_api_ctor):
521541
from cometx.cli.admin_growth_report import GrowthReporter
@@ -579,6 +599,7 @@ def test_collect_mpm_creation_scenarios_a_b_c(mock_api_ctor):
579599
assert modelC_metric.platform == "mpm" and modelC_metric.workspace == "ws1"
580600

581601

602+
@requires_mpm
582603
@patch("comet_mpm.API")
583604
def test_collect_mpm_prediction_volume_usage_per_model_and_per_workspace(
584605
mock_api_ctor,
@@ -626,6 +647,7 @@ def test_collect_mpm_prediction_volume_usage_per_model_and_per_workspace(
626647
assert client.get_nb_predictions.call_count == 2
627648

628649

650+
@requires_mpm
629651
@patch("comet_mpm.API")
630652
def test_collect_mpm_respects_limit_on_workspaces(mock_api_ctor):
631653
from cometx.cli.admin_growth_report import GrowthReporter
@@ -652,6 +674,7 @@ def test_collect_mpm_respects_limit_on_workspaces(mock_api_ctor):
652674
assert not any(e.use_case == "modelZ" for e in events)
653675

654676

677+
@requires_mpm
655678
@patch("comet_mpm.API")
656679
def test_collect_mpm_skips_bad_model_and_continues(mock_api_ctor, capsys):
657680
from cometx.cli.admin_growth_report import GrowthReporter
@@ -686,6 +709,7 @@ def fake_get_nb_predictions(model_id, *args, **kwargs):
686709
assert not any(m.project == "modelBad" for m in usage)
687710

688711

712+
@requires_mpm
689713
@patch("comet_mpm.API")
690714
def test_collect_mpm_workspaces_endpoint_error_returns_empty(mock_api_ctor):
691715
from cometx.cli.admin_growth_report import GrowthReporter
@@ -704,6 +728,7 @@ def test_collect_mpm_workspaces_endpoint_error_returns_empty(mock_api_ctor):
704728
assert usage == []
705729

706730

731+
@requires_mpm
707732
@patch("comet_mpm.API")
708733
def test_collect_mpm_skips_malformed_enumeration_elements(mock_api_ctor):
709734
# The MPM inventory shape is unverifiable live; malformed workspace/model
@@ -1308,7 +1333,7 @@ def _usage_metric(platform, ws, metric, value, project=None, series=None):
13081333
)
13091334

13101335

1311-
def _patch_collectors(monkeypatch, em=None, opik=None, mpm=None):
1336+
def _patch_collectors(monkeypatch, em=None, opik=None, mpm=None, force_platforms=None):
13121337
from cometx.cli.admin_growth_report import GrowthReporter
13131338

13141339
monkeypatch.setattr(
@@ -1320,6 +1345,14 @@ def _patch_collectors(monkeypatch, em=None, opik=None, mpm=None):
13201345
monkeypatch.setattr(
13211346
GrowthReporter, "_collect_mpm", lambda self, ws: (mpm or ([], []))
13221347
)
1348+
# Decouple platform resolution from the environment: `_resolve_platforms`
1349+
# imports opik/comet_mpm to decide availability, but these are optional
1350+
# extras not always installed in CI. Force the set so cross-platform
1351+
# assembly tests are deterministic regardless of what's pip-installed.
1352+
if force_platforms is not None:
1353+
monkeypatch.setattr(
1354+
GrowthReporter, "_resolve_platforms", lambda self: list(force_platforms)
1355+
)
13231356

13241357

13251358
def test_build_assembles_report_data_matching_c8_contract(monkeypatch):
@@ -1402,6 +1435,7 @@ def test_build_assembles_report_data_matching_c8_contract(monkeypatch):
14021435
em=(em_events, em_usage),
14031436
opik=(opik_events, opik_usage),
14041437
mpm=(mpm_events, mpm_usage),
1438+
force_platforms=["opik", "em", "mpm"],
14051439
)
14061440

14071441
reporter = GrowthReporter(
@@ -1589,6 +1623,7 @@ def test_generate_growth_report_full_chain_all_platforms(monkeypatch, tmp_path):
15891623
em=(em_events, []),
15901624
opik=(opik_events, []),
15911625
mpm=(mpm_events, []),
1626+
force_platforms=["opik", "em", "mpm"],
15921627
)
15931628

15941629
out = tmp_path / "growth-full-chain.html"

0 commit comments

Comments
 (0)