test_transaction_comparison.py 4.1 KB

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