如何对自定义变量监听器做集成测试以确保无分数损坏
自定义变量监听器隔离测试方案(针对分数损坏场景)
推荐方案说明
你参考的CustomVariableListenerTest、ListVariableListenerTest、ChangeMoveTest这类官方测试类,就是Timefold推荐的隔离测试方案。这类测试直接操作移动与变量监听器,能精准触发特定场景,非常适合定位分数损坏问题、辅助调试。
测试步骤实现
1. 搭建测试用解决方案
自行构建符合特定场景的测试解决方案,确保初始状态下:
- 实体的规划变量值合理
- Shadow变量初始值正确
- 初始分数计算无误
2. 创建并执行特定移动(核心实现)
通过ScoreDirector模拟移动执行,它会自动触发自定义变量监听器的生命周期方法,完全还原求解过程中的逻辑:
// 初始化ScoreDirectorFactory(可通过SolverFactory获取) ScoreDirectorFactory<MySolution> scoreDirectorFactory = solverFactory.getScoreDirectorFactory(); try (ScoreDirector<MySolution> scoreDirector = scoreDirectorFactory.createScoreDirector()) { // 加载测试解决方案 MySolution testSolution = buildTargetTestSolution(); scoreDirector.setWorkingSolution(testSolution); // 示例:创建并执行ChangeMove MyEntity targetEntity = testSolution.getEntityList().get(0); Object originalValue = targetEntity.getPlanningVariable(); Object targetValue = getSpecificTargetValue(); // 触发问题场景的目标值 ChangeMove<MyEntity> testMove = new ChangeMove<>(targetEntity, MyEntity_.planningVariable, targetValue); // 执行移动,自动触发变量监听器 scoreDirector.doMove(testMove); // 如需执行多个连续移动,重复调用doMove即可 // scoreDirector.doMove(anotherTestMove); }
3. 断言分数未损坏
使用ScoreDirector的内置方法验证分数一致性,直接检测是否存在分数损坏:
// 断言当前工作分数与从头计算的分数一致,即无损坏 scoreDirector.assertScoreFromScratch(scoreDirector.getWorkingScore()); // 或手动计算预期分数后对比 Score expectedScore = calculateExpectedScoreAfterMove(testSolution); assertEquals(expectedScore, scoreDirector.getWorkingScore());
4. 断言Shadow变量预期值
遍历实体,逐一验证Shadow变量是否符合预期:
for (MyEntity entity : testSolution.getEntityList()) { Object expectedShadowValue = computeExpectedShadowValue(entity); assertEquals(expectedShadowValue, entity.getShadowVariable()); }
额外提示
- 若涉及列表变量,参考ListVariableListenerTest的实现,使用
ListChangeMove等列表专属移动类型 - 可将测试封装为JUnit单元测试,便于重复执行与调试
- 测试前务必验证初始解决方案的正确性,避免初始状态问题干扰测试结果
内容的提问来源于stack exchange,提问作者greyhairredbear
相关产品推荐
相关产品推荐

