Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions benchmarks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@
from benchmarks.snapshot import Metric

# Importing the models / patterns packages triggers each module's
# ``register(...)`` / ``register_pattern(...)`` call at import time.
from benchmarks import bench, models, patterns # noqa: F401, E402
# ``register(...)`` / ``register_pattern(...)`` call at import time. ``bench``
# (analytics) is intentionally NOT eagerly imported — that keeps ``import
# benchmarks`` / the CodSpeed CI baseline free of the local-only layer;
# ``from benchmarks import bench`` still works (submodule import on demand).
from benchmarks import models, patterns # noqa: F401, E402


def load_long_df(
Expand Down
72 changes: 0 additions & 72 deletions benchmarks/_tests/test_memory_id_alignment.py

This file was deleted.

3 changes: 2 additions & 1 deletion benchmarks/cli/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class Measure(StrEnum):
)

PhaseName = Literal[
"build", "matrices", "to_lp", "to_netcdf", "from_netcdf", "to_solver"
"build", "matrices", "to_lp", "to_netcdf", "from_netcdf", "to_solver", "pipeline"
]
SpecKind = Literal["all", "models", "patterns"]

Expand All @@ -56,6 +56,7 @@ class Measure(StrEnum):
"to_netcdf": "benchmarks/test_netcdf.py::test_to_netcdf",
"from_netcdf": "benchmarks/test_netcdf.py::test_from_netcdf",
"to_solver": "benchmarks/test_to_solver.py",
"pipeline": "benchmarks/test_pipeline.py",
}

# pytest args that constitute a "smoke" run — quick sizes, no timings.
Expand Down
2 changes: 2 additions & 0 deletions benchmarks/cli/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ def run(
def _timing() -> None:
args: list[str] = []
args.append(_PHASE_TEST_FILE[phase] if phase is not None else "benchmarks/")
if phase == "pipeline":
args.append("--pipeline")
if quick:
args.append("--quick")
elif long:
Expand Down
43 changes: 43 additions & 0 deletions benchmarks/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

from __future__ import annotations

from typing import TYPE_CHECKING

import pytest

from benchmarks.registry import BenchSpec, skip_reason

if TYPE_CHECKING:
from collections.abc import Callable

from benchmarks.phases import PhaseCase

# Test modules the CodSpeed instruments measure (edit to change coverage).
# build + the two export paths: to_lp (LP text) and to_solver (direct handoff,
# which also exercises matrix-gen). matrices is dropped — a subset of to_solver;
Expand Down Expand Up @@ -55,6 +62,16 @@ def pytest_addoption(parser: pytest.Parser) -> None:
"--quick/--long for patterns, leaving models on the prevailing tier."
),
)
parser.addoption(
"--pipeline",
action="store_true",
default=False,
help=(
"Include the opt-in end-to-end pipeline benchmark (build → matrices "
"→ lp in one measured region). Off by default — it re-runs the "
"per-phase work and includes the build."
),
)


def pytest_collection_modifyitems(
Expand All @@ -63,13 +80,20 @@ def pytest_collection_modifyitems(
"""
``--quick`` drops the PyPSA end-to-end test (~30s; minutes under cachegrind).
``--codspeed`` narrows the run to ``CODSPEED_MODULES`` (drops netcdf/matrices).
``test_pipeline`` (end-to-end) is opt-in — deselected unless ``--pipeline``.
"""
if config.getoption("--quick"):
skip = pytest.mark.skip(reason="--quick: pypsa end-to-end skipped")
for item in items:
if "test_pypsa_carbon_management" in item.nodeid:
item.add_marker(skip)

if not config.getoption("--pipeline"):
dropped = [i for i in items if i.path.stem == "test_pipeline"]
if dropped:
config.hook.pytest_deselected(items=dropped)
items[:] = [i for i in items if i.path.stem != "test_pipeline"]

if getattr(config.option, "codspeed", False):
deselected = [i for i in items if i.path.stem not in CODSPEED_MODULES]
if deselected:
Expand Down Expand Up @@ -105,3 +129,22 @@ def maybe_skip(request: pytest.FixtureRequest, spec: BenchSpec, size: int) -> No
)
if reason:
pytest.skip(reason)


def run_case(
benchmark: Callable[..., object],
case: PhaseCase,
request: pytest.FixtureRequest,
) -> None:
"""
Shared pytest-benchmark driver body for one :class:`PhaseCase`.

Honours the case's own ``skip`` (e.g. solver not installed) and the size
tiers (via :func:`maybe_skip`), then runs the case's measured action under
``benchmark`` inside the case's setup/teardown context.
"""
if case.skip:
pytest.skip(case.skip)
maybe_skip(request, case.spec, case.value)
with case.run() as action:
benchmark(action)
Loading
Loading