106 lines
3.3 KiB
Python
106 lines
3.3 KiB
Python
from types import SimpleNamespace
|
|
from unittest.mock import patch
|
|
|
|
from django.test import SimpleTestCase
|
|
from rest_framework.exceptions import ParseError
|
|
|
|
from apps.bi.services import (
|
|
exec_dataset,
|
|
execute_rendered_dataset,
|
|
render_dataset_sql,
|
|
)
|
|
from apps.bi.views import DatasetViewSet
|
|
|
|
|
|
def dataset(**overrides):
|
|
values = {
|
|
"code": "output_daily",
|
|
"sql_query": "select * from output where day = '{day}'",
|
|
"default_param": {"day": "2026-08-01"},
|
|
"test_param": {"day": "2026-08-02"},
|
|
"echart_options": "",
|
|
}
|
|
values.update(overrides)
|
|
return SimpleNamespace(**values)
|
|
|
|
|
|
class DatasetExecutionServiceTests(SimpleTestCase):
|
|
def test_render_does_not_mutate_default_parameters(self):
|
|
item = dataset()
|
|
|
|
sql = render_dataset_sql(item, {"day": "2026-08-10"})
|
|
|
|
self.assertIn("2026-08-10", sql)
|
|
self.assertEqual(item.default_param, {"day": "2026-08-01"})
|
|
|
|
def test_render_reports_missing_parameters(self):
|
|
item = dataset(default_param={}, sql_query="select '{required}'")
|
|
|
|
with self.assertRaises(ParseError):
|
|
render_dataset_sql(item)
|
|
|
|
def test_execute_formats_each_statement(self):
|
|
item = dataset(echart_options='{"series": {ds0}}')
|
|
with (
|
|
patch("apps.bi.services.execute_raw_sql", return_value=([], [])),
|
|
patch(
|
|
"apps.bi.services.format_sqldata",
|
|
return_value=([{"count": 1}], {"count": [1]}),
|
|
),
|
|
):
|
|
response, can_cache = execute_rendered_dataset(
|
|
item, "select 1;select 2"
|
|
)
|
|
|
|
self.assertTrue(can_cache)
|
|
self.assertEqual(set(response["data"]), {"ds0", "ds1"})
|
|
self.assertIn('"count": 1', response["echart_options"])
|
|
|
|
def test_empty_dataset_has_stable_empty_result(self):
|
|
full_sql, response = exec_dataset(dataset(sql_query=""))
|
|
|
|
self.assertEqual(full_sql, "")
|
|
self.assertEqual(response, {"data": {}, "data2": {}})
|
|
|
|
|
|
class DatasetViewExecutionTests(SimpleTestCase):
|
|
@patch("apps.bi.views.cache")
|
|
@patch("apps.bi.views.execute_rendered_dataset")
|
|
@patch("apps.bi.views.render_dataset_sql")
|
|
@patch("apps.bi.views.DatasetSerializer")
|
|
def test_api_reuses_shared_execution_service(
|
|
self,
|
|
serializer_mock,
|
|
render_mock,
|
|
execute_mock,
|
|
cache_mock,
|
|
):
|
|
item = dataset(
|
|
enabled=True,
|
|
name="日产量",
|
|
cache_seconds=10,
|
|
)
|
|
serializer_mock.return_value.data = {
|
|
"code": item.code,
|
|
"echart_options": "",
|
|
}
|
|
render_mock.return_value = "select 1"
|
|
execute_mock.return_value = (
|
|
{"data": {"ds0": [{"count": 1}]}, "data2": {}},
|
|
True,
|
|
)
|
|
cache_mock.get.return_value = None
|
|
view = DatasetViewSet(basename="dataset")
|
|
view.get_object = lambda: item
|
|
request = SimpleNamespace(
|
|
data={"query": {"day": "2026-08-10"}},
|
|
user=SimpleNamespace(id=42, belong_dept=SimpleNamespace(id=7)),
|
|
)
|
|
|
|
response = view.exec(request)
|
|
|
|
render_query = render_mock.call_args.args[1]
|
|
self.assertEqual(render_query["r_user"], 42)
|
|
self.assertEqual(render_query["r_dept"], 7)
|
|
self.assertEqual(response.data["data"]["ds0"][0]["count"], 1)
|