Files
kefu/wechat_rpa/test_review_policy_integration.py
T
2026-09-21 10:34:06 +08:00

107 lines
5.5 KiB
Python

"""Use actual production classes, including when imported from the frozen EXE."""
import unittest
from unittest import mock
import test_visual_review_visibility as visual
class VisualPolicyIntegration(unittest.TestCase):
setUp = visual.VisualReviewVisibilityTest.setUp
restart = visual.VisualReviewVisibilityTest.restart
def test_shadow_mode_survives_restart_and_releases_obsolete_review(self):
self.state.update(judge_mode='shadow', review_reason='模型裁判评估为高风险')
restored = self.restart()
with mock.patch('ai_config.AI_REVIEW_RULES', []):
self.bot._drop_stale_review_flags()
self.assertEqual(restored['judge_mode'], 'shadow')
self.assertFalse(restored.get('awaiting_review'))
self.assertEqual(restored['stage'], 'queued')
def test_disabling_keyword_rule_releases_existing_draft(self):
self.state.update(judge_risk='', staged_user_text='合成关键词')
restored = self.restart()
with mock.patch('ai_config.AI_REVIEW_RULES', [{'label':'测试规则','keywords':['合成关键词'],'enabled':False}]):
self.bot._drop_stale_review_flags()
self.assertFalse(restored.get('awaiting_review'))
self.assertFalse(restored.get('review_reason'))
def test_shadow_never_clears_unknown_receipt(self):
self.state.update(judge_mode='shadow', stage='receipt_check', send_state='uncertain')
with mock.patch('ai_config.AI_REVIEW_RULES', []):
self.bot._drop_stale_review_flags()
self.assertTrue(self.state['awaiting_review'])
self.assertEqual(self.state['send_state'], 'uncertain')
def test_new_strict_verdict_overrides_old_shadow_config(self):
self.state.update(judge_mode='score_only', judge_risk='high')
with mock.patch('review_policy.current_judge_mode',return_value='shadow'), \
mock.patch('ai_config.AI_REVIEW_RULES',[]):
self.assertTrue(self.bot._reply_needs_review(self.state,'合成问题','合成草稿')[0])
def test_old_judge_callback_cannot_modify_new_turn(self):
self.state.update(model_task_id='new-task', judge_risk='low', judge_mode='score_only')
outcome={'judge':{'risk':'high','participated':False},'judge_mode':'shadow','reply':'旧回答'}
self.bot._record_model_call(self.fp,outcome,task_id='old-task',
expected_task_id='old-task',expected_state=self.state)
self.assertEqual(self.state['model_task_id'],'new-task')
self.assertEqual(self.state['judge_risk'],'low')
try:
import test_protocol_review_visibility as protocol
except ImportError:
protocol = None
@unittest.skipIf(protocol is None, 'No protocol transport in this checkout')
class ProtocolPolicyIntegration(unittest.TestCase):
if protocol:
setUp = protocol.ProtocolReviewVisibilityTests.setUp
make_bot = protocol.ProtocolReviewVisibilityTests.make_bot
enqueue = protocol.ProtocolReviewVisibilityTests.enqueue
def test_gateway_shadow_verdict_is_recorded_and_sent_without_approval(self):
self.bot.generate=self.bot._generate
self.bot.send_delay_seconds=600
trace={'judge':{'risk':'high'},'judge_mode':'shadow','task_id':'gateway-task'}
with mock.patch('ai_config.AI_ENABLED',True), \
mock.patch('ai_chat.gateway_provider',return_value=object()), \
mock.patch('ai_chat.get_ai_reply',return_value='合成自动回复'), \
mock.patch('ai_chat.take_last_gateway_trace',side_effect=[{},trace]):
state=self.enqueue()
self.assertEqual(state['judge_mode'],'shadow')
self.assertEqual(state['judge_risk'],'high')
self.assertFalse(state['awaiting_review'])
state['send_ready_at']=0
self.bot.poll_once(); self.bot.poll_once()
self.assertEqual(len(self.sender.calls),1)
def test_current_shadow_plan_releases_legacy_high_risk_once(self):
self.bot.send_mode='review'; state=self.enqueue()
state.update(judge_risk='high',review_reason='模型裁判评估为高风险')
state.pop('judge_mode',None)
self.bot.send_mode='auto'
with mock.patch('review_policy.current_judge_mode',return_value='shadow'):
self.bot.poll_once(); self.bot.poll_once()
self.assertEqual(len(self.sender.calls),1)
def test_score_only_high_risk_still_requires_approval(self):
self.bot.generate=lambda _: (self.bot._pending[self.key].update(judge_risk='high',judge_mode='score_only') or '合成草稿')
with mock.patch('review_policy.current_judge_mode',return_value='score_only'):
state=self.enqueue()
self.assertTrue(state['awaiting_review'])
self.assertFalse(self.sender.calls)
def test_gateway_strict_verdict_overrides_stale_shadow_cache(self):
self.bot.generate=self.bot._generate
trace={'judge':{'risk':'high'},'judge_mode':'score_only','task_id':'new-gateway-task'}
with mock.patch('ai_config.AI_ENABLED',True), \
mock.patch('review_policy.current_judge_mode',return_value='shadow'), \
mock.patch('ai_chat.gateway_provider',return_value=object()), \
mock.patch('ai_chat.get_ai_reply',return_value='合成严格审核草稿'), \
mock.patch('ai_chat.take_last_gateway_trace',side_effect=[{},trace]):
state=self.enqueue()
self.assertEqual(state['judge_mode'],'score_only')
self.assertTrue(state['awaiting_review'])
self.assertFalse(self.sender.calls)