diff --git a/src/pytest_opentelemetry/instrumentation.py b/src/pytest_opentelemetry/instrumentation.py index 581349d..afe25d7 100644 --- a/src/pytest_opentelemetry/instrumentation.py +++ b/src/pytest_opentelemetry/instrumentation.py @@ -103,12 +103,15 @@ def pytest_exception_interact( ) -> None: excinfo = call.excinfo assert excinfo - assert isinstance(excinfo.value, Exception) + assert isinstance(excinfo.value, BaseException) test_span = trace.get_current_span() test_span.record_exception( - exception=excinfo.value, + # Interface says Exception, but BaseException seems to work fine + # This is needed because pytest's Failed exception inherits from + # BaseException, not Exception + exception=excinfo.value, # type: ignore[arg-type] attributes={ SpanAttributes.EXCEPTION_STACKTRACE: str(report.longrepr), }, diff --git a/tests/test_spans.py b/tests/test_spans.py index 4d729f3..c9dbe86 100644 --- a/tests/test_spans.py +++ b/tests/test_spans.py @@ -54,6 +54,8 @@ def test_two(): def test_failures_and_errors(pytester: Pytester, span_recorder: SpanRecorder) -> None: pytester.makepyfile( """ + import pytest + def test_one(): assert 1 + 2 == 3 @@ -62,13 +64,18 @@ def test_two(): def test_three(): raise ValueError('woops') + + def test_four(): + # Test did not raise case + with pytest.raises(ValueError): + pass """ ) result = pytester.runpytest() - result.assert_outcomes(passed=1, failed=2) + result.assert_outcomes(passed=1, failed=3) spans = span_recorder.spans_by_name() - assert len(spans) == 3 + 1 + assert len(spans) == 4 + 1 span = spans['test run'] assert not span.status.is_ok @@ -81,7 +88,7 @@ def test_three(): assert span.attributes assert span.attributes['code.function'] == 'test_two' assert span.attributes['code.filepath'] == 'test_failures_and_errors.py' - assert span.attributes['code.lineno'] == 3 + assert span.attributes['code.lineno'] == 5 assert 'exception.stacktrace' not in span.attributes assert len(span.events) == 1 event = span.events[0] @@ -93,7 +100,7 @@ def test_three(): assert span.attributes assert span.attributes['code.function'] == 'test_three' assert span.attributes['code.filepath'] == 'test_failures_and_errors.py' - assert span.attributes['code.lineno'] == 6 + assert span.attributes['code.lineno'] == 8 assert 'exception.stacktrace' not in span.attributes assert len(span.events) == 1 event = span.events[0] @@ -101,6 +108,19 @@ def test_three(): assert event.attributes['exception.type'] == 'ValueError' assert event.attributes['exception.message'] == 'woops' + span = spans['test_four'] + assert not span.status.is_ok + assert span.attributes + assert span.attributes['code.function'] == 'test_four' + assert span.attributes['code.filepath'] == 'test_failures_and_errors.py' + assert span.attributes['code.lineno'] == 11 + assert 'exception.stacktrace' not in span.attributes + assert len(span.events) == 1 + event = span.events[0] + assert event.attributes + assert event.attributes['exception.type'] == 'Failed' + assert event.attributes['exception.message'] == "DID NOT RAISE " + def test_failures_in_fixtures(pytester: Pytester, span_recorder: SpanRecorder) -> None: pytester.makepyfile(