Skip to content

Commit 1ca68e9

Browse files
committed
failure tests
1 parent bfbb3a4 commit 1ca68e9

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

src/sentry/workflow_engine/models/data_condition.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ def evaluate_value(self, value: T) -> DataConditionResult:
190190
return None
191191

192192
result = handler.evaluate_value(value, self.comparison)
193+
# TODO: refactor this to return the evaluation result for anomaly detection
193194
return self.get_condition_result() if result else None
194195

195196

tests/sentry/incidents/handlers/condition/test_anomaly_detection_handler.py

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@
22
from unittest import mock
33

44
import orjson
5+
import pytest
56
from urllib3.response import HTTPResponse
67

8+
from sentry.incidents.handlers.condition.anomaly_detection_handler import DetectorError
79
from sentry.incidents.utils.types import MetricDetectorUpdate
810
from sentry.seer.anomaly_detection.types import (
911
AnomalyDetectionSeasonality,
1012
AnomalyDetectionSensitivity,
1113
AnomalyDetectionThresholdType,
1214
AnomalyType,
15+
DataSourceType,
1316
DetectAnomaliesResponse,
1417
)
1518
from sentry.snuba.subscriptions import create_snuba_subscription
@@ -82,7 +85,7 @@ def test_passes(self, mock_seer_request):
8285
@mock.patch(
8386
"sentry.seer.anomaly_detection.get_anomaly_data.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen"
8487
)
85-
def test_does_not_pass(self, mock_seer_request):
88+
def test_passes_medium(self, mock_seer_request):
8689
seer_return_value: DetectAnomaliesResponse = {
8790
"success": True,
8891
"timeseries": [
@@ -97,4 +100,73 @@ def test_does_not_pass(self, mock_seer_request):
97100
],
98101
}
99102
mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200)
100-
self.assert_does_not_pass(self.dc, self.data_packet)
103+
assert self.dc.evaluate_value(self.data_packet) == DetectorPriorityLevel.MEDIUM
104+
105+
@mock.patch(
106+
"sentry.seer.anomaly_detection.get_anomaly_data.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen"
107+
)
108+
@mock.patch("sentry.seer.anomaly_detection.get_anomaly_data.logger")
109+
def test_seer_call_timeout_error(self, mock_logger, mock_seer_request):
110+
from urllib3.exceptions import TimeoutError
111+
112+
mock_seer_request.side_effect = TimeoutError
113+
timeout_extra = {
114+
"subscription_id": self.subscription.id,
115+
"organization_id": self.organization.id,
116+
"project_id": self.project.id,
117+
"source_id": self.subscription.id,
118+
"source_type": DataSourceType.SNUBA_QUERY_SUBSCRIPTION,
119+
"dataset": self.subscription.snuba_query.dataset,
120+
}
121+
with pytest.raises(DetectorError):
122+
self.dc.evaluate_value(self.data_packet)
123+
mock_logger.warning.assert_called_with(
124+
"Timeout error when hitting anomaly detection endpoint", extra=timeout_extra
125+
)
126+
127+
@mock.patch(
128+
"sentry.seer.anomaly_detection.get_anomaly_data.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen"
129+
)
130+
@mock.patch("sentry.seer.anomaly_detection.get_anomaly_data.logger")
131+
def test_seer_call_empty_list(self, mock_logger, mock_seer_request):
132+
seer_return_value: DetectAnomaliesResponse = {"success": True, "timeseries": []}
133+
mock_seer_request.return_value = HTTPResponse(orjson.dumps(seer_return_value), status=200)
134+
with pytest.raises(DetectorError):
135+
self.dc.evaluate_value(self.data_packet)
136+
assert mock_logger.warning.call_args[0] == (
137+
"Seer anomaly detection response returned no potential anomalies",
138+
)
139+
140+
@mock.patch(
141+
"sentry.seer.anomaly_detection.get_anomaly_data.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen"
142+
)
143+
@mock.patch("sentry.seer.anomaly_detection.get_anomaly_data.logger")
144+
def test_seer_call_bad_status(self, mock_logger, mock_seer_request):
145+
mock_seer_request.return_value = HTTPResponse(status=403)
146+
extra = {
147+
"subscription_id": self.subscription.id,
148+
"organization_id": self.organization.id,
149+
"project_id": self.project.id,
150+
"source_id": self.subscription.id,
151+
"source_type": DataSourceType.SNUBA_QUERY_SUBSCRIPTION,
152+
"dataset": self.subscription.snuba_query.dataset,
153+
"response_data": None,
154+
}
155+
with pytest.raises(DetectorError):
156+
self.dc.evaluate_value(self.data_packet)
157+
mock_logger.error.assert_called_with(
158+
"Error when hitting Seer detect anomalies endpoint", extra=extra
159+
)
160+
161+
@mock.patch(
162+
"sentry.seer.anomaly_detection.get_anomaly_data.SEER_ANOMALY_DETECTION_CONNECTION_POOL.urlopen"
163+
)
164+
@mock.patch("sentry.seer.anomaly_detection.get_anomaly_data.logger")
165+
def test_seer_call_failed_parse(self, mock_logger, mock_seer_request):
166+
# XXX: coercing a response into something that will fail to parse
167+
mock_seer_request.return_value = HTTPResponse(None, status=200) # type: ignore[arg-type]
168+
with pytest.raises(DetectorError):
169+
self.dc.evaluate_value(self.data_packet)
170+
mock_logger.exception.assert_called_with(
171+
"Failed to parse Seer anomaly detection response", extra=mock.ANY
172+
)

0 commit comments

Comments
 (0)