test_plan_presentation.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import copy
  2. import unittest
  3. from unittest.mock import patch
  4. from step3_qa_agent.agent.plan_presentation import describe_plan
  5. from step3_qa_agent.agent import production
  6. SCHEMA = {'nodes':[{'id':'人员信息','attributes':['姓名','年龄','岗位']}, {'id':'项目信息','attributes':['名称']}],
  7. 'relations':[{'id':'r1','source':'人员信息','target':'项目信息','type':'服务于'}]}
  8. class PlanPresentationTests(unittest.TestCase):
  9. def plan(self):
  10. return {'steps':[{'step_id':'s1','tool':'图谱查询','depends':[], 'params':{
  11. 'nodes':[{'alias':'n','type':'人员信息'}],
  12. 'filters':[{'alias':'n','field':'年龄','op':'lte','value':40}],
  13. 'select':[{'alias':'n','field':'姓名','as':'姓名'}], 'limit':20}}]}
  14. def test_conditions_and_confirmation_do_not_change_query(self):
  15. plan=self.plan(); before=copy.deepcopy(plan)
  16. state={'plan':plan,'qa_context':{'schema':SCHEMA,'build_id':'test'}}
  17. production.validate_plan(plan,state['qa_context'])
  18. with patch.object(production,'interrupt',return_value='确认') as interrupt:
  19. self.assertTrue(production.confirm(state)['plan_confirm'])
  20. text=interrupt.call_args.args[0]['message']
  21. self.assertIn('年龄不大于“40”',text)
  22. self.assertIn('最多展示20条明细',text)
  23. self.assertNotIn('"nodes"',text)
  24. self.assertEqual(plan,before)
  25. with patch.object(production,'interrupt',return_value='改成30岁'):
  26. self.assertEqual(production.confirm(state)['plan_feedback'],'改成30岁')
  27. def test_relation_grouping_count_order(self):
  28. plan=self.plan(); p=plan['steps'][0]['params']
  29. p['nodes'].append({'alias':'p','type':'项目信息'})
  30. p['relations']=[{'source':'n','target':'p','id':'r1'}]
  31. p['select']=[{'alias':'p','field':'名称','as':'项目'}]
  32. p['aggregates']=[{'alias':'n','op':'count','as':'人数'}]
  33. p['order_by']=[{'field':'人数','direction':'desc'}]
  34. production.validate_plan(plan,{'schema':SCHEMA,'build_id':'test'})
  35. text=describe_plan(plan,SCHEMA)
  36. for expected in ['服务于','按以下信息分组','同一对象只计一次','人数从高到低','20组统计结果']:
  37. self.assertIn(expected,text)
  38. def test_all_filter_operators_and_aggregate_forms(self):
  39. for op,value,expected in [('eq','甲','是“甲”'),('ne','甲','不是“甲”'),('contains','甲','包含“甲”'),
  40. ('in',['甲','乙'],'“甲”、“乙”'),('gt',0,'大于“0”'),('gte',0,'不小于“0”'),
  41. ('lt',40,'小于“40”'),('is_null',None,'未填写'),('not_null',None,'已填写')]:
  42. plan=self.plan(); plan['steps'][0]['params']['filters']=[{'alias':'n','field':'姓名','op':op,'value':value}]
  43. self.assertIn(expected,describe_plan(plan,SCHEMA))
  44. for op,expected in [('sum','合计'),('avg','平均值'),('min','最小值'),('max','最大值'),('count_distinct','不同取值')]:
  45. plan=self.plan(); p=plan['steps'][0]['params']; p['select']=[]; p['filters']=[]
  46. p['aggregates']=[{'alias':'n','field':'年龄','op':op,'as':'统计'}]
  47. self.assertIn(expected,describe_plan(plan,SCHEMA))
  48. self.assertIn('不额外限定',describe_plan(plan,SCHEMA))
  49. def test_unsupported_does_not_interrupt(self):
  50. with patch.object(production,'interrupt') as interrupt:
  51. self.assertTrue(production.confirm({'plan':{'steps':[]}})['plan_confirm'])
  52. interrupt.assert_not_called()
  53. if __name__ == '__main__': unittest.main()