mirror of
https://github.com/BerriAI/litellm.git
synced 2026-09-06 08:16:43 +00:00
tests/e2e/test_junit_properties.py fed a hand-rolled FakeItem to result_properties and attach_result_properties, both typed pytest.Item, so uv run basedpyright tests/e2e reported 3 reportArgumentType errors on litellm_internal_staging and every make check that scopes a litellm/ or tests/e2e/ Python file failed. Each test now looks up its own collected Item in request.session.items and applies the covers marker at run time through request.applymarker, so the coverage registry's collect-only pass never sees the test ids and the production functions keep their pytest.Item signatures. No casts, no ignores. Resolves LIT-6669
131 lines
5.9 KiB
Python
131 lines
5.9 KiB
Python
"""Harness coverage for the custom JUnit properties.
|
|
|
|
No proxy and no ``e2e`` marker. Pins the two normalizations that have to agree
|
|
about where a suite file lives -- ``package_from_nodeid`` (strip the suite root)
|
|
and ``source_from_location`` (re-root at it) -- across both ways the suite is
|
|
launched, plus the one-based line offset and the refusal to emit a path that
|
|
escapes the suite. The consumers of these properties are the Loki/Grafana
|
|
rollups and, for ``source``, the status page's per-test links to GitHub.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
from junit_properties import (
|
|
SUITE_ROOT,
|
|
attach_result_properties,
|
|
dedupe_covers,
|
|
package_from_nodeid,
|
|
result_properties,
|
|
source_from_location,
|
|
suite_parts,
|
|
)
|
|
|
|
|
|
def collected_item(request: pytest.FixtureRequest, name: str) -> pytest.Item:
|
|
"""The Item pytest collected for test ``name`` in this file: the real nodeid,
|
|
location and marker machinery the collection hook reads, as pytest built it."""
|
|
return next(item for item in request.session.items if item.path == request.path and item.name == name)
|
|
|
|
|
|
def repo_root() -> Path | None:
|
|
"""The litellm checkout above this file, or None when there isn't one."""
|
|
return next((p for p in Path(__file__).resolve().parents if (p / ".git").exists()), None)
|
|
|
|
|
|
class TestSuiteParts:
|
|
@pytest.mark.parametrize(
|
|
"path",
|
|
["logging/test_x.py", "tests/e2e/logging/test_x.py", "./logging/test_x.py", "tests\\e2e\\logging\\test_x.py"],
|
|
)
|
|
def test_both_invocation_shapes_collapse_to_the_same_components(self, path: str) -> None:
|
|
"""A repo-root run and a suite-cwd run report the same file differently;
|
|
every downstream signal has to see one spelling."""
|
|
assert suite_parts(path) == ("logging", "test_x.py")
|
|
|
|
def test_top_level_suite_file_keeps_its_single_component(self) -> None:
|
|
assert suite_parts("tests/e2e/test_fixture_mode.py") == ("test_fixture_mode.py",)
|
|
|
|
|
|
class TestPackageFromNodeid:
|
|
@pytest.mark.parametrize(
|
|
("nodeid", "expected"),
|
|
[
|
|
("logging/test_x.py::TestFoo::test_bar", "logging"),
|
|
("tests/e2e/logging/test_x.py::TestFoo::test_bar", "logging"),
|
|
("quota_management/spend_tracking/test_x.py::test_bar", "quota_management"),
|
|
("test_fixture_mode.py::TestParseFixtureMode::test_known_values_normalize", "root"),
|
|
("tests/e2e/test_fixture_mode.py::test_bar", "root"),
|
|
],
|
|
)
|
|
def test_package_is_the_first_dir_under_the_suite_root(self, nodeid: str, expected: str) -> None:
|
|
assert package_from_nodeid(nodeid) == expected
|
|
|
|
|
|
class TestSourceFromLocation:
|
|
@pytest.mark.parametrize("path", ["a2a/test_a2a_agent_e2e.py", "tests/e2e/a2a/test_a2a_agent_e2e.py"])
|
|
def test_path_is_repo_relative_however_pytest_was_started(self, path: str) -> None:
|
|
assert source_from_location(path, 40) == "tests/e2e/a2a/test_a2a_agent_e2e.py:41"
|
|
|
|
def test_line_is_emitted_one_based(self) -> None:
|
|
"""pytest.Item.location counts from 0; editors, tracebacks and GitHub's
|
|
#L anchor all count from 1, and an off-by-one lands on the decorator."""
|
|
assert source_from_location("a2a/test_x.py", 0) == "tests/e2e/a2a/test_x.py:1"
|
|
|
|
def test_top_level_suite_file_sits_directly_under_the_suite_root(self) -> None:
|
|
assert source_from_location("test_fixture_mode.py", 39) == "tests/e2e/test_fixture_mode.py:40"
|
|
|
|
@pytest.mark.parametrize(
|
|
("path", "lineno"),
|
|
[
|
|
("a2a/test_x.py", None),
|
|
("/app/e2e/a2a/test_x.py", 40),
|
|
("C:\\app\\e2e\\a2a\\test_x.py", 40),
|
|
("../conftest.py", 40),
|
|
("", 40),
|
|
],
|
|
)
|
|
def test_nothing_linkable_yields_empty_rather_than_a_guess(self, path: str, lineno: int | None) -> None:
|
|
"""A colon is rejected on two counts: it is how a Windows absolute path
|
|
arrives, and `path:line` cannot represent one in the path half."""
|
|
assert source_from_location(path, lineno) == ""
|
|
|
|
|
|
class TestResultProperties:
|
|
def test_every_test_carries_package_covers_and_source(self, request: pytest.FixtureRequest) -> None:
|
|
"""Read off this test's own collected Item, so the nodeid and location are
|
|
whatever pytest reports for the launch shape in use, and the marker is added
|
|
at run time so the coverage registry's collect-only pass never sees it."""
|
|
test = type(self).test_every_test_carries_package_covers_and_source
|
|
request.applymarker(pytest.mark.covers("LOG-1", "LOG-2"))
|
|
assert result_properties(collected_item(request, test.__name__)) == (
|
|
("package", "root"),
|
|
("covers", "LOG-1,LOG-2"),
|
|
("source", f"tests/e2e/test_junit_properties.py:{test.__code__.co_firstlineno}"),
|
|
)
|
|
|
|
def test_attach_is_idempotent(self, request: pytest.FixtureRequest) -> None:
|
|
"""Collection can run the hook more than once; a second pass must not
|
|
double the <property> entries in the report."""
|
|
item = collected_item(request, type(self).test_attach_is_idempotent.__name__)
|
|
attach_result_properties(item)
|
|
attach_result_properties(item)
|
|
assert [name for name, _ in item.user_properties] == ["package", "covers", "source"]
|
|
|
|
|
|
class TestSuiteRoot:
|
|
def test_suite_root_names_this_file_s_real_home(self) -> None:
|
|
"""SUITE_ROOT is hardcoded because the runner image has no repo to read it
|
|
from. Where there IS a checkout, prove the constant still points at us --
|
|
otherwise a moved tests/e2e/ ships links that 404."""
|
|
root = repo_root()
|
|
if root is None:
|
|
pytest.skip("no checkout above this file (the runner image copies tests/e2e/ to /app/e2e)")
|
|
assert (root / SUITE_ROOT / Path(__file__).name).resolve() == Path(__file__).resolve()
|
|
|
|
|
|
class TestDedupeCovers:
|
|
def test_ids_are_unique_order_preserving_and_non_empty_strings(self) -> None:
|
|
assert dedupe_covers([("A", "B"), ("B", ""), ("C", 7)]) == ("A", "B", "C")
|