""" 测试参数管理功能 包括必填参数验证、参数记录创建、回退后参数可见性等 """ from django.test import TestCase from django.contrib.auth import get_user_model from stateflow import models, services User = get_user_model() class ParameterManagementTestCase(TestCase): """测试参数管理功能""" def setUp(self): """设置测试数据""" # 创建测试用户 self.user = User.objects.create_user(username='testuser', password='testpass') # 创建状态 self.state1 = models.State.objects.create(name='状态1', description='第一个状态') self.state2 = models.State.objects.create(name='状态2', description='第二个状态') self.state3 = models.State.objects.create(name='状态3', description='第三个状态') # 为状态1添加必填参数 self.required_param = models.StateParameter.objects.create( key='temperature', value='', is_required=True, description='温度(必填)' ) self.optional_param = models.StateParameter.objects.create( key='humidity', value='', is_required=False, description='湿度(可选)' ) self.state1.parameters.add(self.required_param, self.optional_param) # 为状态2添加必填参数 self.required_param2 = models.StateParameter.objects.create( key='pressure', value='', is_required=True, description='压力(必填)' ) self.state2.parameters.add(self.required_param2) # 创建流程 self.process = models.Process.objects.create(name='测试流程') models.ProcessNode.objects.create(process=self.process, state=self.state1, order=0) models.ProcessNode.objects.create(process=self.process, state=self.state2, order=1) models.ProcessNode.objects.create(process=self.process, state=self.state3, order=2) # 创建业务对象 self.business_object = models.BusinessObject.objects.create( name='测试业务对象', process=self.process ) def test_advance_without_required_parameter_fails(self): """测试不提供必填参数时推进失败""" # 尝试推进但不提供必填参数 success, message, state_log = services.advance_to_next_state( self.business_object, self.user ) # 应该失败 self.assertFalse(success) self.assertIn('缺失必填参数', message) self.assertIn('temperature', message) self.assertIsNone(state_log) # 验证状态未改变 current_state = services.get_business_object_current_state(self.business_object) self.assertIsNone(current_state) # 验证没有创建状态流转记录 self.assertEqual(self.business_object.state_logs.count(), 0) def test_advance_with_only_required_parameter_succeeds(self): """测试只提供必填参数时推进成功""" # 只提供必填参数 success, message, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5' # 只提供必填的 ) # 应该成功 self.assertTrue(success) self.assertIsNotNone(state_log) # 验证状态已推进 current_state = services.get_business_object_current_state(self.business_object) self.assertEqual(current_state.name, self.state1.name) # 验证参数记录已创建 self.assertEqual(state_log.parameter_records.count(), 1) param_record = state_log.parameter_records.first() self.assertEqual(param_record.parameters['temperature'], '25.5') self.assertNotIn('humidity', param_record.parameters) def test_advance_with_all_parameters(self): """测试提供所有参数时推进成功""" success, message, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5', humidity='60%' ) # 应该成功 self.assertTrue(success) self.assertIsNotNone(state_log) # 验证参数记录包含所有提供的参数 param_record = state_log.parameter_records.first() self.assertEqual(param_record.parameters['temperature'], '25.5') self.assertEqual(param_record.parameters['humidity'], '60%') def test_advance_with_extra_parameters(self): """测试提供额外参数时也能成功(不做验证)""" success, message, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5', humidity='60%', operator='张三', # 额外参数 notes='测试备注' # 额外参数 ) # 应该成功(不验证参数是否在定义中) self.assertTrue(success) # 验证所有参数都被保存 param_record = state_log.parameter_records.first() self.assertEqual(len(param_record.parameters), 4) self.assertEqual(param_record.parameters['operator'], '张三') self.assertEqual(param_record.parameters['notes'], '测试备注') def test_add_parameters_after_advance(self): """测试推进后补充参数""" # 先推进 success, message, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5' ) self.assertTrue(success) # 补充参数 new_record = services.add_parameters_to_state_log( state_log, remark='补充测量', humidity='65%', inspector='李四' ) # 验证创建了新的参数记录 self.assertEqual(state_log.parameter_records.count(), 2) self.assertEqual(new_record.parameters['humidity'], '65%') self.assertEqual(new_record.parameters['inspector'], '李四') self.assertEqual(new_record.remark, '补充测量') def test_parameter_summary_with_updates(self): """测试参数汇总(包含更新的值)""" # 推进并提供初始参数 success, message, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5', humidity='60%' ) # 补充参数(更新 temperature) services.add_parameters_to_state_log( state_log, temperature='26.0', # 重新测量 remark='温度重新测量' ) # 获取参数汇总 summary = state_log.get_all_parameters_summary() # 验证最新值 self.assertEqual(summary['temperature'], '26.0') # 应该是更新后的值 self.assertEqual(summary['humidity'], '60%') # 保持原值 def test_parameter_history(self): """测试参数历史记录""" # 推进 success, message, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5' ) # 多次更新同一个参数 services.add_parameters_to_state_log( state_log, temperature='26.0', remark='第一次重测' ) services.add_parameters_to_state_log( state_log, temperature='26.5', remark='第二次重测' ) # 获取历史 history = state_log.get_parameter_history('temperature') # 验证历史记录 self.assertEqual(len(history), 3) self.assertEqual(history[0]['value'], '25.5') self.assertEqual(history[1]['value'], '26.0') self.assertEqual(history[1]['remark'], '第一次重测') self.assertEqual(history[2]['value'], '26.5') self.assertEqual(history[2]['remark'], '第二次重测') def test_step_back_excludes_cancelled_state_parameters(self): """测试回退后,默认情况下查询参数时应排除已撤销状态的参数""" # 推进两次,每次都提供参数 success, msg, state_log1 = services.advance_to_next_state( self.business_object, self.user, temperature='25.5', humidity='60%' ) self.assertTrue(success) success, msg, state_log2 = services.advance_to_next_state( self.business_object, self.user, pressure='1013' ) self.assertTrue(success) # 验证两个状态都有参数记录 self.assertEqual(state_log1.parameter_records.count(), 1) self.assertEqual(state_log2.parameter_records.count(), 1) # 回退一步(撤销 state2) success, message = services.step_back_one_state(self.business_object, self.user) self.assertTrue(success) # 刷新 state_log2 state_log2.refresh_from_db() self.assertTrue(state_log2.is_cancelled) # 默认情况下,已撤销状态的参数不可见 summary = state_log2.get_all_parameters_summary() self.assertEqual(len(summary), 0) # 应该返回空字典 # 使用 include_cancelled=True 可以查看已撤销状态的参数 summary_with_cancelled = state_log2.get_all_parameters_summary(include_cancelled=True) self.assertEqual(len(summary_with_cancelled), 1) self.assertEqual(summary_with_cancelled['pressure'], '1013') # 验证 state_log1 的参数仍然可见(未撤销) summary1 = state_log1.get_all_parameters_summary() self.assertEqual(len(summary1), 2) self.assertEqual(summary1['temperature'], '25.5') self.assertEqual(summary1['humidity'], '60%') def test_cancelled_state_parameter_history(self): """测试已撤销状态的参数历史记录不可见""" # 推进并提供参数 success, msg, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5' ) self.assertTrue(success) # 补充参数 services.add_parameters_to_state_log( state_log, temperature='26.0', remark='重新测量' ) # 验证参数历史存在 history = state_log.get_parameter_history('temperature') self.assertEqual(len(history), 2) # 回退(撤销状态) services.step_back_one_state(self.business_object, self.user) state_log.refresh_from_db() # 默认情况下,已撤销状态的参数历史不可见 history = state_log.get_parameter_history('temperature') self.assertEqual(len(history), 0) # 使用 include_cancelled=True 可以查看 history_with_cancelled = state_log.get_parameter_history('temperature', include_cancelled=True) self.assertEqual(len(history_with_cancelled), 2) def test_cancelled_state_get_latest_parameter(self): """测试已撤销状态无法获取最新参数值""" # 推进并提供参数 success, msg, state_log = services.advance_to_next_state( self.business_object, self.user, temperature='25.5' ) self.assertTrue(success) # 验证可以获取参数 temp = state_log.get_latest_parameter('temperature') self.assertEqual(temp, '25.5') # 回退(撤销状态) services.step_back_one_state(self.business_object, self.user) state_log.refresh_from_db() # 默认情况下返回默认值 temp = state_log.get_latest_parameter('temperature', default='N/A') self.assertEqual(temp, 'N/A') # 使用 include_cancelled=True 可以获取 temp_with_cancelled = state_log.get_latest_parameter('temperature', include_cancelled=True) self.assertEqual(temp_with_cancelled, '25.5') def test_multiple_states_with_different_required_parameters(self): """测试多个状态各自的必填参数验证""" # 推进到 state1(需要 temperature) success, msg, _ = services.advance_to_next_state( self.business_object, self.user, temperature='25.5' ) self.assertTrue(success) # 尝试推进到 state2 但不提供 pressure success, msg, _ = services.advance_to_next_state( self.business_object, self.user, temperature='26.0' # 提供了 state1 的参数,但这是 state2 ) # 应该失败(缺少 state2 的必填参数 pressure) self.assertFalse(success) self.assertIn('缺失必填参数', msg) self.assertIn('pressure', msg) # 提供正确的必填参数 success, msg, _ = services.advance_to_next_state( self.business_object, self.user, pressure='1013' ) self.assertTrue(success) def test_state_without_required_parameters_allows_advance_without_params(self): """测试没有必填参数的状态允许不提供参数推进""" # 先推进两次到达 state3(没有任何参数要求) services.advance_to_next_state(self.business_object, self.user, temperature='25') services.advance_to_next_state(self.business_object, self.user, pressure='1013') # 推进到 state3,不提供任何参数 success, msg, state_log = services.advance_to_next_state( self.business_object, self.user ) # 应该成功 self.assertTrue(success) self.assertIsNotNone(state_log) # 验证没有创建参数记录 self.assertEqual(state_log.parameter_records.count(), 0)