Skip to content

Commit

Permalink
create helper for asserting count
Browse files Browse the repository at this point in the history
  • Loading branch information
Christinarlong committed Mar 3, 2025
1 parent fe4de7f commit 3804a47
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 42 deletions.
11 changes: 11 additions & 0 deletions src/sentry/testutils/asserts.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from functools import reduce

from django.http import StreamingHttpResponse

from sentry.integrations.types import EventLifecycleOutcome
Expand Down Expand Up @@ -110,3 +112,12 @@ def assert_middleware_metrics(middleware_calls):
assert end1.args[0] == EventLifecycleOutcome.SUCCESS
assert start2.args[0] == EventLifecycleOutcome.STARTED
assert end2.args[0] == EventLifecycleOutcome.SUCCESS


def assert_count_of_metric(mock_record, outcome, outcome_count):
calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == outcome else acc),
mock_record.mock_calls,
0,
)
assert calls == outcome_count
81 changes: 39 additions & 42 deletions tests/sentry/sentry_apps/tasks/test_sentry_apps.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from collections import namedtuple
from datetime import datetime, timedelta
from functools import reduce
from unittest.mock import ANY, patch

import pytest
Expand Down Expand Up @@ -39,7 +38,11 @@
from sentry.sentry_apps.utils.errors import SentryAppSentryError
from sentry.shared_integrations.exceptions import ClientError
from sentry.tasks.post_process import post_process_group
from sentry.testutils.asserts import assert_failure_metric, assert_success_metric
from sentry.testutils.asserts import (
assert_count_of_metric,
assert_failure_metric,
assert_success_metric,
)
from sentry.testutils.cases import TestCase
from sentry.testutils.helpers import with_feature
from sentry.testutils.helpers.datetime import before_now, freeze_time
Expand Down Expand Up @@ -347,26 +350,29 @@ def test_group_created_sends_webhook(self, mock_record, safe_urlopen):
"Sentry-Hook-Signature",
}
assert_success_metric(mock_record)
started_calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == EventLifecycleOutcome.SUCCESS else acc),
mock_record.mock_calls,
0,

# PREPARE_WEBHOOK (success) -> SEND_WEBHOOK (success) -> SEND_WEBHOOK (success)
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.STARTED, outcome_count=3
)
success_calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == EventLifecycleOutcome.SUCCESS else acc),
mock_record.mock_calls,
0,
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.SUCCESS, outcome_count=3
)

assert started_calls == 3
assert success_calls == 3

@patch("sentry.integrations.utils.metrics.EventLifecycle.record_event")
def test_does_not_process_disallowed_event(self, mock_record, safe_urlopen):
process_resource_change_bound("delete", "Group", self.create_group().id)
assert len(safe_urlopen.mock_calls) == 0
assert_failure_metric(mock_record, "invalid_event")

# PREPARE_WEBHOOK (failure)
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.STARTED, outcome_count=1
)
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.FAILURE, outcome_count=1
)

@patch("sentry.integrations.utils.metrics.EventLifecycle.record_event")
def test_does_not_process_sentry_apps_without_issue_webhooks(self, mock_record, safe_urlopen):
with assume_test_silo_mode_of(SentryApp):
Expand All @@ -380,20 +386,15 @@ def test_does_not_process_sentry_apps_without_issue_webhooks(self, mock_record,

assert len(safe_urlopen.mock_calls) == 0
assert_success_metric(mock_record)
started_calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == EventLifecycleOutcome.SUCCESS else acc),
mock_record.mock_calls,
0,

# PREPARE_WEBHOOK (success)
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.STARTED, outcome_count=1
)
success_calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == EventLifecycleOutcome.SUCCESS else acc),
mock_record.mock_calls,
0,
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.SUCCESS, outcome_count=1
)

assert started_calls == 1
assert success_calls == 1

@patch("sentry.sentry_apps.tasks.sentry_apps._process_resource_change")
def test_process_resource_change_bound_passes_retry_object(self, process, safe_urlopen):
group = self.create_group(project=self.project)
Expand Down Expand Up @@ -453,20 +454,15 @@ def test_error_created_sends_webhook(self, mock_record, safe_urlopen):
}

assert_success_metric(mock_record)
started_calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == EventLifecycleOutcome.SUCCESS else acc),
mock_record.mock_calls,
0,

# PREPARE_WEBHOOK (success) -> SEND_WEBHOOK (success) -> SEND_WEBHOOK (success)
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.STARTED, outcome_count=3
)
success_calls = reduce(
lambda acc, calls: (acc + 1 if calls.args[0] == EventLifecycleOutcome.SUCCESS else acc),
mock_record.mock_calls,
0,
assert_count_of_metric(
mock_record=mock_record, outcome=EventLifecycleOutcome.SUCCESS, outcome_count=3
)

assert started_calls == 3
assert success_calls == 3

# TODO(nola): Enable this test whenever we prevent infinite loops w/ error.created integrations
@pytest.mark.skip(reason="enable this when/if we do prevent infinite error.created loops")
@with_feature("organizations:integrations-event-hooks")
Expand Down Expand Up @@ -525,8 +521,9 @@ def setUp(self):
)

@patch("sentry.utils.sentry_apps.webhooks.safe_urlopen", return_value=MockResponse404)
@patch("sentry.integrations.utils.metrics.EventLifecycle.record_event")
@with_feature("organizations:integrations-event-hooks")
def test_sends_webhooks_to_all_installs(self, safe_urlopen):
def test_sends_webhooks_to_all_installs(self, mock_record, safe_urlopen):
one_min_ago = before_now(minutes=1).isoformat()
event = self.store_event(
data={
Expand Down Expand Up @@ -927,12 +924,12 @@ def test_ignore_issue_alert(self, safe_urlopen):
with assume_test_silo_mode_of(SentryApp):
self.sentry_app.update(status=SentryAppStatus.INTERNAL)
data = {"issue": serialize(self.issue)}
# we don't raise errors for unpublished and internal apps
# with pytest.raises(SentryAppSentryError):
for i in range(3):
send_webhooks(
installation=self.install, event="event.alert", data=data, actor=self.user
)
# event.alert is not in the servicehook events
with pytest.raises(SentryAppSentryError):
for i in range(3):
send_webhooks(
installation=self.install, event="event.alert", data=data, actor=self.user
)
assert not safe_urlopen.called
assert [len(item) == 0 for item in self.integration_buffer._get_broken_range_from_buffer()]
assert len(self.integration_buffer._get_all_from_buffer()) == 0
Expand Down

0 comments on commit 3804a47

Please sign in to comment.