test_transaction_comparison.py 4.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. import copy
  2. from datetime import datetime, timedelta
  3. import pytz
  4. from sentry.testutils import AcceptanceTestCase, SnubaTestCase
  5. from sentry.testutils.helpers.datetime import before_now, timestamp_format
  6. from sentry.utils.compat.mock import patch
  7. from tests.acceptance.test_organization_events_v2 import generate_transaction
  8. FEATURE_NAMES = ["organizations:performance-view"]
  9. class TransactionComparison(AcceptanceTestCase, SnubaTestCase):
  10. def setUp(self):
  11. super().setUp()
  12. self.user = self.create_user("foo@example.com", is_superuser=True)
  13. self.org = self.create_organization(name="Rowdy Tiger")
  14. self.team = self.create_team(organization=self.org, name="Mariachi Band")
  15. self.project = self.create_project(organization=self.org, teams=[self.team], name="Bengal")
  16. self.create_member(user=self.user, organization=self.org, role="owner", teams=[self.team])
  17. self.login_as(self.user)
  18. def wait_until_loaded(self):
  19. self.browser.wait_until_not(".loading-indicator")
  20. self.browser.wait_until_not('[data-test-id="loading-placeholder"]')
  21. @patch("django.utils.timezone.now")
  22. def test_transaction_comparison(self, mock_now):
  23. mock_now.return_value = before_now().replace(tzinfo=pytz.utc)
  24. baseline_event_data = generate_transaction(trace="a" * 32, span="ab" * 8)
  25. baseline_event = self.store_event(
  26. data=baseline_event_data, project_id=self.project.id, assert_no_errors=True
  27. )
  28. baseline_event_slug = f"{self.project.slug}:{baseline_event.event_id}"
  29. regression_event_data = generate_transaction(trace="b" * 32, span="bc" * 8)
  30. regression_event_data.update({"event_id": "b" * 32})
  31. regression_event_data["spans"] = regress_spans(regression_event_data["spans"])
  32. regression_event = self.store_event(
  33. data=regression_event_data, project_id=self.project.id, assert_no_errors=True
  34. )
  35. regression_event_slug = f"{self.project.slug}:{regression_event.event_id}"
  36. comparison_page_path = f"/organizations/{self.org.slug}/performance/compare/{baseline_event_slug}/{regression_event_slug}/"
  37. with self.feature(FEATURE_NAMES):
  38. self.browser.get(comparison_page_path)
  39. self.wait_until_loaded()
  40. # screenshot for un-expanded span details are visually different from
  41. # when a matched span is expanded
  42. self.browser.snapshot("transaction comparison page")
  43. self.browser.elements('[data-test-id="span-row"]')[0].click()
  44. self.browser.elements('[data-test-id="span-row"]')[1].click()
  45. self.browser.elements('[data-test-id="span-row"]')[2].click()
  46. self.browser.elements('[data-test-id="span-row"]')[10].click()
  47. self.browser.snapshot("transaction comparison page - expanded span details")
  48. def regress_spans(original_spans):
  49. spans = []
  50. last_index = len(original_spans) - 1
  51. for index, reference_span in enumerate(original_spans):
  52. end_datetime = datetime.utcfromtimestamp(reference_span["timestamp"]).replace(
  53. tzinfo=pytz.utc
  54. )
  55. span = copy.deepcopy(reference_span)
  56. if index % 2 == 0:
  57. # for every even indexed span, increase its duration.
  58. # this implies the span was slower.
  59. regression_time = timedelta(milliseconds=10 + index)
  60. span["timestamp"] = timestamp_format(end_datetime + regression_time)
  61. else:
  62. # for every odd indexed span, decrease its duration.
  63. # this implies the span was faster
  64. regression_time = timedelta(milliseconds=5 + index)
  65. span["timestamp"] = timestamp_format(end_datetime - regression_time)
  66. if index == last_index:
  67. # change the op name of the last span.
  68. # the last span would be removed from the baseline transaction;
  69. # and the last span of the baseline transaction would be missing from
  70. # the regression transaction
  71. span["op"] = "resource"
  72. spans.append(span)
  73. return spans