[dashboard] New, add statsd metrics to the API (#9519)

This commit is contained in:
Daniel Vaz Gaspar
2020-04-16 10:54:45 +01:00
committed by GitHub
parent d9ebd32485
commit 7b11b44abe
5 changed files with 240 additions and 48 deletions

View File

@@ -18,10 +18,11 @@
"""Unit tests for Superset"""
import imp
import json
from typing import Union
from unittest.mock import Mock
from typing import Union, Dict
from unittest.mock import Mock, patch
import pandas as pd
from flask import Response
from flask_appbuilder.security.sqla import models as ab_models
from flask_testing import TestCase
@@ -35,6 +36,7 @@ from superset.models.core import Database
from superset.models.dashboard import Dashboard
from superset.models.datasource_access_request import DatasourceAccessRequest
from superset.utils.core import get_example_database
from superset.views.base_api import BaseSupersetModelRestApi
FAKE_DB_NAME = "fake_db_100"
@@ -328,3 +330,81 @@ class SupersetTestCase(TestCase):
def get_dash_by_slug(self, dash_slug):
sesh = db.session()
return sesh.query(Dashboard).filter_by(slug=dash_slug).first()
def get_assert_metric(self, uri: str, func_name: str) -> Response:
"""
Simple client get with an extra assertion for statsd metrics
:param uri: The URI to use for the HTTP GET
:param func_name: The function name that the HTTP GET triggers
for the statsd metric assertion
:return: HTTP Response
"""
with patch.object(
BaseSupersetModelRestApi, "incr_stats", return_value=None
) as mock_method:
rv = self.client.get(uri)
if 200 <= rv.status_code < 400:
mock_method.assert_called_once_with("success", func_name)
else:
mock_method.assert_called_once_with("error", func_name)
return rv
def delete_assert_metric(self, uri: str, func_name: str) -> Response:
"""
Simple client delete with an extra assertion for statsd metrics
:param uri: The URI to use for the HTTP DELETE
:param func_name: The function name that the HTTP DELETE triggers
for the statsd metric assertion
:return: HTTP Response
"""
with patch.object(
BaseSupersetModelRestApi, "incr_stats", return_value=None
) as mock_method:
rv = self.client.delete(uri)
if 200 <= rv.status_code < 400:
mock_method.assert_called_once_with("success", func_name)
else:
mock_method.assert_called_once_with("error", func_name)
return rv
def post_assert_metric(self, uri: str, data: Dict, func_name: str) -> Response:
"""
Simple client post with an extra assertion for statsd metrics
:param uri: The URI to use for the HTTP POST
:param data: The JSON data payload to be posted
:param func_name: The function name that the HTTP POST triggers
for the statsd metric assertion
:return: HTTP Response
"""
with patch.object(
BaseSupersetModelRestApi, "incr_stats", return_value=None
) as mock_method:
rv = self.client.post(uri, json=data)
if 200 <= rv.status_code < 400:
mock_method.assert_called_once_with("success", func_name)
else:
mock_method.assert_called_once_with("error", func_name)
return rv
def put_assert_metric(self, uri: str, data: Dict, func_name: str) -> Response:
"""
Simple client put with an extra assertion for statsd metrics
:param uri: The URI to use for the HTTP PUT
:param data: The JSON data payload to be posted
:param func_name: The function name that the HTTP PUT triggers
for the statsd metric assertion
:return: HTTP Response
"""
with patch.object(
BaseSupersetModelRestApi, "incr_stats", return_value=None
) as mock_method:
rv = self.client.put(uri, json=data)
if 200 <= rv.status_code < 400:
mock_method.assert_called_once_with("success", func_name)
else:
mock_method.assert_called_once_with("error", func_name)
return rv

View File

@@ -79,13 +79,13 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_get_dashboard(self):
"""
Dashboard API: Test get dashboard
Dashboard API: Test get dashboard
"""
admin = self.get_user("admin")
dashboard = self.insert_dashboard("title", "slug1", [admin.id])
self.login(username="admin")
uri = f"api/v1/dashboard/{dashboard.id}"
rv = self.client.get(uri)
rv = self.get_assert_metric(uri, "get")
self.assertEqual(rv.status_code, 200)
expected_result = {
"changed_by": None,
@@ -121,19 +121,28 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
db.session.delete(dashboard)
db.session.commit()
def test_info_dashboard(self):
"""
Dashboard API: Test info
"""
self.login(username="admin")
uri = f"api/v1/dashboard/_info"
rv = self.get_assert_metric(uri, "info")
self.assertEqual(rv.status_code, 200)
def test_get_dashboard_not_found(self):
"""
Dashboard API: Test get dashboard not found
Dashboard API: Test get dashboard not found
"""
max_id = db.session.query(func.max(Dashboard.id)).scalar()
self.login(username="admin")
uri = f"api/v1/dashboard/{max_id + 1}"
rv = self.client.get(uri)
rv = self.get_assert_metric(uri, "get")
self.assertEqual(rv.status_code, 404)
def test_get_dashboard_no_data_access(self):
"""
Dashboard API: Test get dashboard without data access
Dashboard API: Test get dashboard without data access
"""
admin = self.get_user("admin")
dashboard = self.insert_dashboard("title", "slug1", [admin.id])
@@ -148,7 +157,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_get_dashboards_filter(self):
"""
Dashboard API: Test get dashboards filter
Dashboard API: Test get dashboards filter
"""
admin = self.get_user("admin")
gamma = self.get_user("gamma")
@@ -160,7 +169,8 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
"filters": [{"col": "dashboard_title", "opr": "sw", "value": "ti"}]
}
uri = f"api/v1/dashboard/?q={prison.dumps(arguments)}"
rv = self.client.get(uri)
rv = self.get_assert_metric(uri, "get_list")
self.assertEqual(rv.status_code, 200)
data = json.loads(rv.data.decode("utf-8"))
self.assertEqual(data["count"], 1)
@@ -182,7 +192,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_get_dashboards_custom_filter(self):
"""
Dashboard API: Test get dashboards custom filter
Dashboard API: Test get dashboards custom filter
"""
admin = self.get_user("admin")
dashboard1 = self.insert_dashboard("foo", "ZY_bar", [admin.id])
@@ -232,7 +242,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_get_dashboards_no_data_access(self):
"""
Dashboard API: Test get dashboards no data access
Dashboard API: Test get dashboards no data access
"""
admin = self.get_user("admin")
dashboard = self.insert_dashboard("title", "slug1", [admin.id])
@@ -253,20 +263,20 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_dashboard(self):
"""
Dashboard API: Test delete
Dashboard API: Test delete
"""
admin_id = self.get_user("admin").id
dashboard_id = self.insert_dashboard("title", "slug1", [admin_id]).id
self.login(username="admin")
uri = f"api/v1/dashboard/{dashboard_id}"
rv = self.client.delete(uri)
rv = self.delete_assert_metric(uri, "delete")
self.assertEqual(rv.status_code, 200)
model = db.session.query(Dashboard).get(dashboard_id)
self.assertEqual(model, None)
def test_delete_bulk_dashboards(self):
"""
Dashboard API: Test delete bulk
Dashboard API: Test delete bulk
"""
admin_id = self.get_user("admin").id
dashboard_count = 4
@@ -282,7 +292,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
self.login(username="admin")
argument = dashboard_ids
uri = f"api/v1/dashboard/?q={prison.dumps(argument)}"
rv = self.client.delete(uri)
rv = self.delete_assert_metric(uri, "bulk_delete")
self.assertEqual(rv.status_code, 200)
response = json.loads(rv.data.decode("utf-8"))
expected_response = {"message": f"Deleted {dashboard_count} dashboards"}
@@ -293,7 +303,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_bulk_dashboards_bad_request(self):
"""
Dashboard API: Test delete bulk bad request
Dashboard API: Test delete bulk bad request
"""
dashboard_ids = [1, "a"]
self.login(username="admin")
@@ -304,7 +314,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_not_found_dashboard(self):
"""
Dashboard API: Test not found delete
Dashboard API: Test not found delete
"""
self.login(username="admin")
dashboard_id = 1000
@@ -314,7 +324,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_bulk_dashboards_not_found(self):
"""
Dashboard API: Test delete bulk not found
Dashboard API: Test delete bulk not found
"""
dashboard_ids = [1001, 1002]
self.login(username="admin")
@@ -325,7 +335,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_dashboard_admin_not_owned(self):
"""
Dashboard API: Test admin delete not owned
Dashboard API: Test admin delete not owned
"""
gamma_id = self.get_user("gamma").id
dashboard_id = self.insert_dashboard("title", "slug1", [gamma_id]).id
@@ -339,7 +349,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_bulk_dashboard_admin_not_owned(self):
"""
Dashboard API: Test admin delete bulk not owned
Dashboard API: Test admin delete bulk not owned
"""
gamma_id = self.get_user("gamma").id
dashboard_count = 4
@@ -368,7 +378,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_dashboard_not_owned(self):
"""
Dashboard API: Test delete try not owned
Dashboard API: Test delete try not owned
"""
user_alpha1 = self.create_user(
"alpha1", "password", "Alpha", email="alpha1@superset.org"
@@ -393,7 +403,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_delete_bulk_dashboard_not_owned(self):
"""
Dashboard API: Test delete bulk try not owned
Dashboard API: Test delete bulk try not owned
"""
user_alpha1 = self.create_user(
"alpha1", "password", "Alpha", email="alpha1@superset.org"
@@ -455,7 +465,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_dashboard(self):
"""
Dashboard API: Test create dashboard
Dashboard API: Test create dashboard
"""
admin_id = self.get_user("admin").id
dashboard_data = {
@@ -469,7 +479,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
}
self.login(username="admin")
uri = "api/v1/dashboard/"
rv = self.client.post(uri, json=dashboard_data)
rv = self.post_assert_metric(uri, dashboard_data, "post")
self.assertEqual(rv.status_code, 201)
data = json.loads(rv.data.decode("utf-8"))
model = db.session.query(Dashboard).get(data.get("id"))
@@ -478,7 +488,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_simple_dashboard(self):
"""
Dashboard API: Test create simple dashboard
Dashboard API: Test create simple dashboard
"""
dashboard_data = {"dashboard_title": "title1"}
self.login(username="admin")
@@ -492,7 +502,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_dashboard_empty(self):
"""
Dashboard API: Test create empty
Dashboard API: Test create empty
"""
dashboard_data = {}
self.login(username="admin")
@@ -516,12 +526,12 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_dashboard_validate_title(self):
"""
Dashboard API: Test create dashboard validate title
Dashboard API: Test create dashboard validate title
"""
dashboard_data = {"dashboard_title": "a" * 600}
self.login(username="admin")
uri = "api/v1/dashboard/"
rv = self.client.post(uri, json=dashboard_data)
rv = self.post_assert_metric(uri, dashboard_data, "post")
self.assertEqual(rv.status_code, 400)
response = json.loads(rv.data.decode("utf-8"))
expected_response = {
@@ -531,7 +541,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_dashboard_validate_slug(self):
"""
Dashboard API: Test create validate slug
Dashboard API: Test create validate slug
"""
admin_id = self.get_user("admin").id
dashboard = self.insert_dashboard("title1", "slug1", [admin_id])
@@ -560,7 +570,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_dashboard_validate_owners(self):
"""
Dashboard API: Test create validate owners
Dashboard API: Test create validate owners
"""
dashboard_data = {"dashboard_title": "title1", "owners": [1000]}
self.login(username="admin")
@@ -573,7 +583,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_create_dashboard_validate_json(self):
"""
Dashboard API: Test create validate json
Dashboard API: Test create validate json
"""
dashboard_data = {"dashboard_title": "title1", "position_json": '{"A:"a"}'}
self.login(username="admin")
@@ -598,13 +608,13 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_dashboard(self):
"""
Dashboard API: Test update
Dashboard API: Test update
"""
admin = self.get_user("admin")
dashboard_id = self.insert_dashboard("title1", "slug1", [admin.id]).id
self.login(username="admin")
uri = f"api/v1/dashboard/{dashboard_id}"
rv = self.client.put(uri, json=self.dashboard_data)
rv = self.put_assert_metric(uri, self.dashboard_data, "put")
self.assertEqual(rv.status_code, 200)
model = db.session.query(Dashboard).get(dashboard_id)
self.assertEqual(model.dashboard_title, self.dashboard_data["dashboard_title"])
@@ -620,7 +630,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_dashboard_chart_owners(self):
"""
Dashboard API: Test update chart owners
Dashboard API: Test update chart owners
"""
user_alpha1 = self.create_user(
"alpha1", "password", "Alpha", email="alpha1@superset.org"
@@ -663,7 +673,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_partial_dashboard(self):
"""
Dashboard API: Test update partial
Dashboard API: Test update partial
"""
admin_id = self.get_user("admin").id
dashboard_id = self.insert_dashboard("title1", "slug1", [admin_id]).id
@@ -692,7 +702,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_dashboard_new_owner(self):
"""
Dashboard API: Test update set new owner to current user
Dashboard API: Test update set new owner to current user
"""
gamma_id = self.get_user("gamma").id
admin = self.get_user("admin")
@@ -711,7 +721,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_dashboard_slug_formatting(self):
"""
Dashboard API: Test update slug formatting
Dashboard API: Test update slug formatting
"""
admin_id = self.get_user("admin").id
dashboard_id = self.insert_dashboard("title1", "slug1", [admin_id]).id
@@ -728,7 +738,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_dashboard_validate_slug(self):
"""
Dashboard API: Test update validate slug
Dashboard API: Test update validate slug
"""
admin_id = self.get_user("admin").id
dashboard1 = self.insert_dashboard("title1", "slug-1", [admin_id])
@@ -763,7 +773,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_published(self):
"""
Dashboard API: Test update published patch
Dashboard API: Test update published patch
"""
admin = self.get_user("admin")
gamma = self.get_user("gamma")
@@ -785,7 +795,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_update_dashboard_not_owned(self):
"""
Dashboard API: Test update dashboard not owned
Dashboard API: Test update dashboard not owned
"""
user_alpha1 = self.create_user(
"alpha1", "password", "Alpha", email="alpha1@superset.org"
@@ -802,7 +812,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
self.login(username="alpha2", password="password")
dashboard_data = {"dashboard_title": "title1_changed", "slug": "slug1 changed"}
uri = f"api/v1/dashboard/{dashboard.id}"
rv = self.client.put(uri, json=dashboard_data)
rv = self.put_assert_metric(uri, dashboard_data, "put")
self.assertEqual(rv.status_code, 403)
db.session.delete(dashboard)
db.session.delete(user_alpha1)
@@ -811,13 +821,12 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_export(self):
"""
Dashboard API: Test dashboard export
Dashboard API: Test dashboard export
"""
self.login(username="admin")
argument = [1, 2]
uri = f"api/v1/dashboard/export/?q={prison.dumps(argument)}"
rv = self.client.get(uri)
rv = self.get_assert_metric(uri, "export")
self.assertEqual(rv.status_code, 200)
self.assertEqual(
rv.headers["Content-Disposition"],
@@ -826,7 +835,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_export_not_found(self):
"""
Dashboard API: Test dashboard export not found
Dashboard API: Test dashboard export not found
"""
self.login(username="admin")
argument = [1000]
@@ -836,7 +845,7 @@ class DashboardApiTests(SupersetTestCase, ApiOwnersTestCaseMixin):
def test_export_not_allowed(self):
"""
Dashboard API: Test dashboard export not allowed
Dashboard API: Test dashboard export not allowed
"""
admin_id = self.get_user("admin").id
dashboard = self.insert_dashboard("title", "slug1", [admin_id], published=False)