Skip to content

Commit 258a3ce

Browse files
authored
Switch to path filtering instead of conformance markers to run conformance tests (#45)
* Switch to path filtering instead of conformance markers to run conformance tests
1 parent 7cafd93 commit 258a3ce

8 files changed

Lines changed: 30 additions & 35 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,10 @@ via Weaver live-check. Each scenario module defines a subclass of
119119
`expected_spans`, `expected_metrics`, and implements
120120
`run(*, tracer_provider, meter_provider, logger_provider, vcr)`.
121121

122-
`tests/test_conformance.py` must set `pytestmark = pytest.mark.conformance` at
123-
module level.
124-
125-
Run via `tox -e py312-test-instrumentation-<pkg>-conformance`.
122+
Run via `tox -e py312-test-instrumentation-<pkg>-conformance`. The
123+
`*-conformance` tox envs target `tests/test_conformance.py` directly; the
124+
regular `*-{oldest,latest}` envs `--ignore` it so they don't need the
125+
OTLP/gRPC exporter or `weaver_live_check`.
126126

127127
The parallel PR-review rules live in
128128
[`.github/instructions/instrumentation.instructions.md`](.github/instructions/instrumentation.instructions.md)

instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@
2121
from .conformance.inference import InferenceScenario
2222
from .conformance.tool_calling import ToolCallingScenario
2323

24-
pytestmark = pytest.mark.conformance
25-
2624
_LEGACY_SYSTEM_SKIP = pytest.mark.skip(
2725
reason="anthropic emits legacy gen_ai.system in experimental mode"
2826
)

instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020

2121
from .conformance.inference import InferenceScenario
2222

23-
pytestmark = pytest.mark.conformance
24-
2523

2624
@pytest.mark.parametrize(
2725
"scenario",

instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@
2727
from .conformance.inference import InferenceScenario
2828
from .conformance.tool_calling import ToolCallingScenario
2929

30-
pytestmark = pytest.mark.conformance
31-
3230

3331
@pytest.mark.parametrize(
3432
"scenario",

pytest.ini

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,3 @@
22
addopts = -rs -v
33
log_cli = true
44
log_cli_level = warning
5-
markers =
6-
conformance: GenAI semconv conformance scenario (run via the *-conformance tox envs)

tox.ini

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -146,23 +146,23 @@ commands_pre =
146146
coverage: python {toxinidir}/scripts/eachdist.py install --editable
147147

148148
commands =
149-
test-instrumentation-openai-v2-{oldest,latest}: pytest -m "not conformance" {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests {posargs}
150-
test-instrumentation-openai-v2-conformance: pytest -m conformance {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests --vcr-record=none {posargs}
149+
test-instrumentation-openai-v2-{oldest,latest}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests {posargs}
150+
test-instrumentation-openai-v2-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-v2/tests/test_conformance.py --vcr-record=none {posargs}
151151
lint-instrumentation-openai-v2: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-openai-v2"
152152
test-instrumentation-openai_agents-v2: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-openai-agents-v2/tests {posargs}
153153
lint-instrumentation-openai_agents-v2: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-openai-agents-v2"
154154

155155
test-instrumentation-google-genai: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-google-genai/tests --vcr-record=none {posargs}
156156
lint-instrumentation-google-genai: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-google-genai"
157157

158-
test-instrumentation-anthropic-{oldest,latest}: pytest -m "not conformance" {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests --vcr-record=none {posargs}
159-
test-instrumentation-anthropic-conformance: pytest -m conformance {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests --vcr-record=none {posargs}
158+
test-instrumentation-anthropic-{oldest,latest}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests --vcr-record=none {posargs}
159+
test-instrumentation-anthropic-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-anthropic/tests/test_conformance.py --vcr-record=none {posargs}
160160
lint-instrumentation-anthropic: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-anthropic"
161161

162162
test-instrumentation-claude-agent-sdk: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-claude-agent-sdk/tests --vcr-record=none {posargs}
163163
lint-instrumentation-claude-agent-sdk: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-claude-agent-sdk"
164164

165-
test-instrumentation-langchain-conformance: pytest -m conformance {toxinidir}/instrumentation/opentelemetry-instrumentation-langchain/tests --vcr-record=none {posargs}
165+
test-instrumentation-langchain-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-langchain/tests/test_conformance.py --vcr-record=none {posargs}
166166
lint-instrumentation-langchain: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-langchain"
167167

168168
lint-instrumentation-weaviate: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-weaviate"

util/opentelemetry-test-util-genai/src/opentelemetry/test_util_genai/conformance.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,17 @@
55
66
Intended call shape from a per-package ``tests/test_conformance.py``::
77
8-
pytestmark = pytest.mark.conformance
9-
108
@pytest.mark.parametrize(
119
"scenario", [InferenceScenario(), ToolCallingScenario()]
1210
)
1311
def test_conformance(scenario, vcr, weaver_live_check):
1412
report = run_conformance(scenario, vcr=vcr, weaver=weaver_live_check)
1513
# Optionally layer lib-specific assertions on `report` here.
1614
17-
The module-level ``pytestmark = pytest.mark.conformance`` is required: the
18-
``*-conformance`` tox envs select these tests via ``-m conformance``, and the
19-
regular ``*-{oldest,latest}`` envs deselect them via ``-m "not conformance"``.
15+
The ``*-conformance`` tox envs point pytest directly at
16+
``tests/test_conformance.py``; the regular ``*-{oldest,latest}`` envs
17+
``--ignore`` it. The OTLP/gRPC exporter and ``weaver_live_check`` only need
18+
to be installed in the conformance envs.
2019
2120
Each ``tests/conformance/<op>.py`` defines a :class:`Scenario` subclass with:
2221
@@ -40,15 +39,6 @@ def test_conformance(scenario, vcr, weaver_live_check):
4039
from pathlib import Path
4140
from typing import Any, ClassVar
4241

43-
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
44-
OTLPLogExporter,
45-
)
46-
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import (
47-
OTLPMetricExporter,
48-
)
49-
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
50-
OTLPSpanExporter,
51-
)
5242
from opentelemetry.sdk._logs import LoggerProvider
5343
from opentelemetry.sdk._logs.export import SimpleLogRecordProcessor
5444
from opentelemetry.sdk.metrics import MeterProvider
@@ -105,6 +95,19 @@ def validate(self, report: LiveCheckReport) -> None:
10595
def _build_providers(
10696
endpoint: str,
10797
) -> tuple[TracerProvider, MeterProvider, LoggerProvider]:
98+
# OTLP/gRPC exporters are only installed in the *-conformance tox envs
99+
# (see dev-requirements-conformance.txt). Import lazily so this module
100+
# stays importable in regular test envs that exclude conformance tests.
101+
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import ( # noqa: PLC0415
102+
OTLPLogExporter,
103+
)
104+
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import ( # noqa: PLC0415
105+
OTLPMetricExporter,
106+
)
107+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( # noqa: PLC0415
108+
OTLPSpanExporter,
109+
)
110+
108111
tracer_provider = TracerProvider()
109112
tracer_provider.add_span_processor(
110113
SimpleSpanProcessor(OTLPSpanExporter(endpoint=endpoint, insecure=True))

util/opentelemetry-util-genai/src/opentelemetry/util/genai/completion_hook.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import logging
1616
from os import environ
17-
from typing import Any, Protocol, cast, runtime_checkable
17+
from typing import Any, Protocol, runtime_checkable
1818

1919
from opentelemetry._logs import LogRecord
2020
from opentelemetry.trace import Span
@@ -120,15 +120,15 @@ def load_completion_hook() -> CompletionHook:
120120
if not hook_name:
121121
return _NoOpCompletionHook()
122122

123-
for entry_point in entry_points( # pyright: ignore[reportUnknownVariableType]
123+
for entry_point in entry_points(
124124
group="opentelemetry_genai_completion_hook"
125125
):
126-
name = cast(str, entry_point.name) # pyright: ignore[reportUnknownMemberType]
126+
name = entry_point.name
127127
try:
128128
if hook_name != name:
129129
continue
130130

131-
hook = entry_point.load()() # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType]
131+
hook = entry_point.load()()
132132
if not isinstance(hook, CompletionHook):
133133
_logger.debug(
134134
"%s is not a valid CompletionHook. Using noop", name

0 commit comments

Comments
 (0)