factory/apps/bi/test_services.py

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)