Skip to content

Commit 14cfbcc

Browse files
umaannamalaia-feld
authored andcommitted
Add tests for ASGI exception capture.
1 parent 38e2f09 commit 14cfbcc

File tree

2 files changed

+52
-14
lines changed

2 files changed

+52
-14
lines changed

tests/agent_features/test_asgi_transaction.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,32 @@
1515
import asyncio
1616
import logging
1717
import pytest
18-
from testing_support.sample_asgi_applications import simple_app_v2_raw, simple_app_v3_raw, simple_app_v2, simple_app_v3, AppWithDescriptor
19-
from testing_support.fixtures import validate_transaction_metrics, override_application_settings, function_not_called
18+
from testing_support.sample_asgi_applications import (
19+
simple_app_v2_raw,
20+
simple_app_v3_raw,
21+
simple_app_v2,
22+
simple_app_v3,
23+
AppWithDescriptor,
24+
simple_app_v2_init_exc,
25+
)
26+
from testing_support.fixtures import (
27+
validate_transaction_metrics,
28+
override_application_settings,
29+
function_not_called,
30+
validate_transaction_errors,
31+
)
2032
from newrelic.api.asgi_application import asgi_application, ASGIApplicationWrapper
2133
from testing_support.asgi_testing import AsgiTest
2234

23-
#Setup test apps from sample_asgi_applications.py
35+
# Setup test apps from sample_asgi_applications.py
2436
simple_app_v2_original = AsgiTest(simple_app_v2_raw)
2537
simple_app_v3_original = AsgiTest(simple_app_v3_raw)
2638

2739
simple_app_v3_wrapped = AsgiTest(simple_app_v3)
2840
simple_app_v2_wrapped = AsgiTest(simple_app_v2)
41+
simple_app_v2_init_exc = AsgiTest(simple_app_v2_init_exc)
2942

30-
#Test naming scheme logic and ASGIApplicationWrapper for a single callable
43+
# Test naming scheme logic and ASGIApplicationWrapper for a single callable
3144
@pytest.mark.parametrize("naming_scheme", (None, "component", "framework"))
3245
def test_single_callable_naming_scheme(naming_scheme):
3346

@@ -49,7 +62,7 @@ def _test():
4962
_test()
5063

5164

52-
#Test the default naming scheme logic and ASGIApplicationWrapper for a double callable
65+
# Test the default naming scheme logic and ASGIApplicationWrapper for a double callable
5366
@validate_transaction_metrics(name="", group="Uri")
5467
def test_double_callable_default_naming_scheme():
5568
response = simple_app_v2_wrapped.make_request("GET", "/")
@@ -58,24 +71,26 @@ def test_double_callable_default_naming_scheme():
5871
assert response.body == b""
5972

6073

61-
#No harm test on single callable asgi app with agent disabled to ensure proper response
74+
# No harm test on single callable asgi app with agent disabled to ensure proper response
6275
def test_single_callable_raw():
6376
response = simple_app_v3_original.make_request("GET", "/")
6477
assert response.status == 200
6578
assert response.headers == {}
6679
assert response.body == b""
6780

6881

69-
#No harm test on double callable asgi app with agent disabled to ensure proper response
82+
# No harm test on double callable asgi app with agent disabled to ensure proper response
7083
def test_double_callable_raw():
7184
response = simple_app_v2_original.make_request("GET", "/")
7285
assert response.status == 200
7386
assert response.headers == {}
7487
assert response.body == b""
7588

7689

77-
#Test asgi_application decorator with parameters passed in on a single callable
78-
@pytest.mark.parametrize("name, group", ((None, "group"), ("name", "group"), ("", "group")))
90+
# Test asgi_application decorator with parameters passed in on a single callable
91+
@pytest.mark.parametrize(
92+
"name, group", ((None, "group"), ("name", "group"), ("", "group"))
93+
)
7994
def test_asgi_application_decorator_single_callable(name, group):
8095
if name:
8196
expected_name = name
@@ -97,7 +112,7 @@ def _test():
97112
_test()
98113

99114

100-
#Test asgi_application decorator using default values on a double callable
115+
# Test asgi_application decorator using default values on a double callable
101116
@validate_transaction_metrics(name="", group="Uri")
102117
def test_asgi_application_decorator_no_params_double_callable():
103118
asgi_decorator = asgi_application()
@@ -109,8 +124,10 @@ def test_asgi_application_decorator_no_params_double_callable():
109124
assert response.body == b""
110125

111126

112-
#Test for presence of framework info based on whether framework is specified
113-
@validate_transaction_metrics(name="test", custom_metrics=[("Python/Framework/framework/v1", 1)])
127+
# Test for presence of framework info based on whether framework is specified
128+
@validate_transaction_metrics(
129+
name="test", custom_metrics=[("Python/Framework/framework/v1", 1)]
130+
)
114131
def test_framework_metrics():
115132
asgi_decorator = asgi_application(name="test", framework=("framework", "v1"))
116133
decorated_application = asgi_decorator(simple_app_v2_raw)
@@ -157,3 +174,12 @@ async def _test():
157174
loop = asyncio.get_event_loop()
158175
with pytest.raises(ValueError):
159176
loop.run_until_complete(_test())
177+
178+
179+
@pytest.mark.parametrize(
180+
"app", (simple_app_v3_wrapped, simple_app_v2_wrapped, simple_app_v2_init_exc)
181+
)
182+
@validate_transaction_errors(errors=["builtins:ValueError"])
183+
def test_exception_capture(app):
184+
with pytest.raises(ValueError):
185+
app.make_request("GET", "/exc")

tests/testing_support/sample_asgi_applications.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,25 @@ def __init__(self, scope):
2424
async def __call__(self, receive, send):
2525
if self.scope["type"] != "http":
2626
raise ValueError("unsupported")
27+
28+
if self.scope["path"] == "/exc":
29+
raise ValueError("whoopsies")
2730
await send({"type": "http.response.start", "status": 200})
2831
await send({"type": "http.response.body"})
2932

3033

34+
class simple_app_v2_init_exc(simple_app_v2_raw):
35+
def __init__(self, scope):
36+
raise ValueError("oh no!")
37+
38+
3139
async def simple_app_v3_raw(scope, receive, send):
3240
if scope["type"] != "http":
3341
raise ValueError("unsupported")
3442

43+
if scope["path"] == "/exc":
44+
raise ValueError("whoopsies")
45+
3546
await send({"type": "http.response.start", "status": 200})
3647
await send({"type": "http.response.body"})
3748

@@ -53,6 +64,7 @@ async def static(scope, receive, send):
5364

5465

5566
simple_app_v2 = ASGIApplicationWrapper(simple_app_v2_raw)
67+
simple_app_v2_init_exc = ASGIApplicationWrapper(simple_app_v2_init_exc)
5668
simple_app_v3 = ASGIApplicationWrapper(simple_app_v3_raw)
5769

5870

@@ -68,9 +80,9 @@ async def normal_asgi_application(scope, receive, send):
6880
]
6981

7082
try:
71-
raise ValueError('Transaction had bad value')
83+
raise ValueError("Transaction had bad value")
7284
except ValueError:
73-
record_exception(params={'ohnoes': 'param-value'})
85+
record_exception(params={"ohnoes": "param-value"})
7486

7587
await send(
7688
{"type": "http.response.start", "status": 200, "headers": response_headers}

0 commit comments

Comments
 (0)