Skip to content

Commit 0752112

Browse files
authored
refactor: remove fixture support (#76)
1 parent ef03494 commit 0752112

File tree

2 files changed

+0
-221
lines changed

2 files changed

+0
-221
lines changed

pytest_mergify/__init__.py

Lines changed: 0 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -114,112 +114,6 @@ def pytest_runtest_protocol(
114114
else:
115115
yield
116116

117-
@pytest.hookimpl(hookwrapper=True)
118-
def pytest_runtest_teardown(
119-
self, item: _pytest.nodes.Item
120-
) -> typing.Generator[None, None, None]:
121-
if self.tracer:
122-
# Since there is no pytest_fixture_teardown hook, we have to be a
123-
# little clever to capture the spans for each fixture's teardown.
124-
# The pytest_fixture_post_finalizer hook is called at the end of a
125-
# fixture's teardown, but we don't know when the fixture actually
126-
# began tearing down.
127-
#
128-
# Instead start a span here for the first fixture to be torn down,
129-
# but give it a temporary name, since we don't know which fixture it
130-
# will be. Then, in pytest_fixture_post_finalizer, when we do know
131-
# which fixture is being torn down, update the name and attributes
132-
# to the actual fixture, end the span, and create the span for the
133-
# next fixture in line to be torn down.
134-
self._fixture_teardown_span = self.tracer.start_span("fixture teardown")
135-
yield
136-
# The last call to pytest_fixture_post_finalizer will create
137-
# a span that is unneeded, so delete it.
138-
del self._fixture_teardown_span
139-
else:
140-
yield
141-
142-
def _attributes_from_fixturedef(
143-
self, fixturedef: _pytest.fixtures.FixtureDef[typing.Any]
144-
) -> dict[str, str | int]:
145-
return {
146-
SpanAttributes.CODE_FILEPATH: fixturedef.func.__code__.co_filename,
147-
SpanAttributes.CODE_FUNCTION: fixturedef.argname,
148-
SpanAttributes.CODE_LINENO: fixturedef.func.__code__.co_firstlineno,
149-
"test.fixture.scope": fixturedef.scope,
150-
"test.scope": "fixture",
151-
}
152-
153-
def _name_from_fixturedef(
154-
self,
155-
fixturedef: _pytest.fixtures.FixtureDef[typing.Any],
156-
request: _pytest.fixtures.FixtureRequest,
157-
) -> str:
158-
if fixturedef.params and "request" in fixturedef.argnames:
159-
try:
160-
parameter = str(request.param)
161-
except Exception:
162-
parameter = str(
163-
request.param_index
164-
if isinstance(request, _pytest.fixtures.SubRequest)
165-
else "?"
166-
)
167-
return f"{fixturedef.argname}[{parameter}]"
168-
return fixturedef.argname
169-
170-
@pytest.hookimpl(hookwrapper=True)
171-
def pytest_fixture_setup(
172-
self,
173-
fixturedef: _pytest.fixtures.FixtureDef[typing.Any],
174-
request: _pytest.fixtures.FixtureRequest,
175-
) -> typing.Generator[None, None, None]:
176-
if self.tracer:
177-
with self.tracer.start_as_current_span(
178-
name=f"{self._name_from_fixturedef(fixturedef, request)} setup",
179-
attributes=self._attributes_from_fixturedef(fixturedef),
180-
):
181-
yield
182-
else:
183-
yield
184-
185-
@pytest.hookimpl(hookwrapper=True)
186-
def pytest_fixture_post_finalizer(
187-
self,
188-
fixturedef: _pytest.fixtures.FixtureDef[typing.Any],
189-
request: _pytest.fixtures.SubRequest,
190-
) -> typing.Generator[None, None, None]:
191-
"""When the span for a fixture teardown is created by
192-
pytest_runtest_teardown or a previous pytest_fixture_post_finalizer, we
193-
need to update the name and attributes now that we know which fixture it
194-
was for."""
195-
196-
if self.tracer:
197-
# If the fixture has already been torn down, then it will have no cached
198-
# result, so we can skip this one.
199-
if fixturedef.cached_result is None:
200-
yield
201-
# Passing `-x` option to pytest can cause it to exit early so it may not
202-
# have this span attribute.
203-
elif not hasattr(self, "_fixture_teardown_span"): # pragma: no cover
204-
yield
205-
else:
206-
# If we've gotten here, we have a real fixture about to be torn down.
207-
name = f"{self._name_from_fixturedef(fixturedef, request)} teardown"
208-
self._fixture_teardown_span.update_name(name)
209-
attributes = self._attributes_from_fixturedef(fixturedef)
210-
self._fixture_teardown_span.set_attributes(
211-
attributes # type: ignore[arg-type]
212-
)
213-
yield
214-
self._fixture_teardown_span.end()
215-
216-
# Create the span for the next fixture to be torn down. When there are
217-
# no more fixtures remaining, this will be an empty, useless span, so it
218-
# needs to be deleted by pytest_runtest_teardown.
219-
self._fixture_teardown_span = self.tracer.start_span("fixture teardown")
220-
else:
221-
yield
222-
223117
def pytest_exception_interact(
224118
self,
225119
node: _pytest.nodes.Node,

tests/test_spans.py

Lines changed: 0 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import typing
2-
31
import opentelemetry.trace
42
from opentelemetry.semconv.trace import SpanAttributes
53

6-
import anys
74

85
from tests import conftest
96

@@ -110,118 +107,6 @@ def test_skipped():
110107
assert spans["test_skipped"].parent.span_id == session_span.context.span_id
111108

112109

113-
def test_fixture(
114-
pytester_with_spans: conftest.PytesterWithSpanT,
115-
) -> None:
116-
result, spans = pytester_with_spans("""
117-
import pytest
118-
@pytest.fixture
119-
def myfix(): pass
120-
def test_pass(myfix): pass
121-
""")
122-
123-
expected_spans = (
124-
"myfix setup",
125-
"myfix teardown",
126-
)
127-
for name in expected_spans:
128-
assert name in spans
129-
130-
assert spans["myfix setup"].attributes == {
131-
"test.scope": "fixture",
132-
"code.function": "myfix",
133-
"code.lineno": 2,
134-
"code.filepath": anys.ANY_STR,
135-
"test.fixture.scope": "function",
136-
}
137-
assert typing.cast(str, spans["myfix setup"].attributes["code.filepath"]).endswith(
138-
"test_fixture.py"
139-
)
140-
assert (
141-
spans["myfix setup"].status.status_code == opentelemetry.trace.StatusCode.UNSET
142-
)
143-
144-
assert spans["myfix teardown"].attributes == {
145-
"test.scope": "fixture",
146-
"code.function": "myfix",
147-
"code.lineno": 2,
148-
"code.filepath": anys.ANY_STR,
149-
"test.fixture.scope": "function",
150-
}
151-
assert typing.cast(
152-
str, spans["myfix teardown"].attributes["code.filepath"]
153-
).endswith("test_fixture.py")
154-
assert (
155-
spans["myfix teardown"].status.status_code
156-
== opentelemetry.trace.StatusCode.UNSET
157-
)
158-
159-
160-
def test_fixture_failure(
161-
pytester_with_spans: conftest.PytesterWithSpanT,
162-
) -> None:
163-
result, spans = pytester_with_spans("""
164-
import pytest
165-
@pytest.fixture
166-
def myfix(): raise Exception("HELLO")
167-
def test_pass(myfix): pass
168-
""")
169-
170-
expected_spans = (
171-
"myfix setup",
172-
"myfix teardown",
173-
)
174-
for name in expected_spans:
175-
assert name in spans
176-
177-
assert spans["myfix setup"].attributes == {
178-
"test.scope": "fixture",
179-
"code.function": "myfix",
180-
"code.lineno": 2,
181-
"code.filepath": anys.ANY_STR,
182-
"test.fixture.scope": "function",
183-
}
184-
assert typing.cast(str, spans["myfix setup"].attributes["code.filepath"]).endswith(
185-
"test_fixture_failure.py"
186-
)
187-
# NOTE: this should probably be error, but it seems there no way to catch fixture issue
188-
# Anyhow, the test is marked as fail and the problem is pointed to the fixture
189-
assert (
190-
spans["myfix setup"].status.status_code == opentelemetry.trace.StatusCode.UNSET
191-
)
192-
193-
assert spans["myfix teardown"].attributes == {
194-
"test.scope": "fixture",
195-
"code.function": "myfix",
196-
"code.lineno": 2,
197-
"code.filepath": anys.ANY_STR,
198-
"test.fixture.scope": "function",
199-
}
200-
assert typing.cast(
201-
str, spans["myfix teardown"].attributes["code.filepath"]
202-
).endswith("test_fixture_failure.py")
203-
assert (
204-
spans["myfix teardown"].status.status_code
205-
== opentelemetry.trace.StatusCode.UNSET
206-
)
207-
208-
assert spans["test_pass"].attributes == {
209-
"test.scope": "case",
210-
"code.function": "test_pass",
211-
"code.lineno": 3,
212-
"code.filepath": "test_fixture_failure.py",
213-
SpanAttributes.EXCEPTION_TYPE: "<class 'Exception'>",
214-
SpanAttributes.EXCEPTION_MESSAGE: "HELLO",
215-
SpanAttributes.EXCEPTION_STACKTRACE: """@pytest.fixture
216-
> def myfix(): raise Exception("HELLO")
217-
E Exception: HELLO
218-
219-
test_fixture_failure.py:3: Exception""",
220-
}
221-
assert spans["test_pass"].status.status_code == opentelemetry.trace.StatusCode.ERROR
222-
assert spans["test_pass"].status.description == "<class 'Exception'>: HELLO"
223-
224-
225110
def test_span_resources_test_run_id(
226111
pytester_with_spans: conftest.PytesterWithSpanT,
227112
) -> None:

0 commit comments

Comments
 (0)