createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result1 = $engine->execute($context1); $this->assertSuccess($result1); $batchNo = $result1->batchNo; $this->assertNotEmpty($batchNo); // 2. 漂洗 - 批次号应该一致 $context2 = $this->createContext([ 'readerType' => '漂洗', 'currentStep' => '清洗', 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); $this->setStepTime($context2, '清洗', 400); $result2 = $engine->execute($context2); $this->assertSuccess($result2); $this->assertEquals($batchNo, $result2->batchNo); // 3. 消毒 - 批次号应该一致 $context3 = $this->createContext([ 'readerType' => '消毒', 'currentStep' => '漂洗', 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); $this->setStepTime($context3, '漂洗', 200); $result3 = $engine->execute($context3); $this->assertSuccess($result3); $this->assertEquals($batchNo, $result3->batchNo); // 4. 终末漂洗 - 批次号应该一致 $context4 = $this->createContext([ 'readerType' => '终末漂洗', 'currentStep' => '消毒', 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); $this->setStepTime($context4, '消毒', 400); $result4 = $engine->execute($context4); $this->assertSuccess($result4); $this->assertEquals($batchNo, $result4->batchNo); // 5. 干燥 - 批次号应该一致 $context5 = $this->createContext([ 'readerType' => '干燥', 'currentStep' => '终末漂洗', 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); $this->setStepTime($context5, '终末漂洗', 200); $result5 = $engine->execute($context5); $this->assertSuccess($result5); $this->assertEquals($batchNo, $result5->batchNo); // 6. 结束 - 批次号应该一致 $context6 = $this->createContext([ 'readerType' => '结束', 'currentStep' => '干燥', 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); $this->setStepTime($context6, '干燥', 300); $result6 = $engine->execute($context6); $this->assertSuccess($result6); $this->assertEquals($batchNo, $result6->batchNo); } /** * 测试多内镜批次号唯一性 */ public function testMultiEndoscopeBatchUniqueness(): void { $engine = ProcessEngine::createStandard(); $batchNos = []; // 模拟5个不同内镜同时开始清洗 for ($i = 1; $i <= 5; $i++) { $context = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result = $engine->execute($context); $this->assertSuccess($result); $batchNos[] = $result->batchNo; } // 所有批次号应该唯一 $uniqueBatchNos = array_unique($batchNos); $this->assertCount(5, $uniqueBatchNos); } /** * 测试批次号格式正确性 */ public function testBatchNoFormat(): void { $context = $this->createContext([ 'endoscopeId' => '123', ]); $batchNo = $context->generateBatchNo(); // 验证格式:YYYYMMDDHHMMSS + 内镜ID(6位) + 随机数(4位) $this->assertEquals(24, strlen($batchNo)); $this->assertMatchesRegularExpression('/^\d{14}\d{6}\d{4}$/', $batchNo); // 验证日期部分 $datePart = substr($batchNo, 0, 8); $this->assertEquals(date('Ymd'), $datePart); // 验证内镜ID部分 $endoscopePart = substr($batchNo, 14, 6); $this->assertEquals('000123', $endoscopePart); } /** * 测试批次号不随时间变化(同一流程内) */ public function testBatchNoStability(): void { $engine = ProcessEngine::createStandard(); $context1 = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result1 = $engine->execute($context1); $batchNo1 = $result1->batchNo; // 模拟时间流逝(实际测试中无法真正等待,所以直接验证) $context2 = $this->createContext([ 'readerType' => '漂洗', 'currentStep' => '清洗', 'endoscopeId' => '', 'batchNo' => $batchNo1, 'morningWashed' => true, ]); $this->setStepTime($context2, '清洗', 400); $result2 = $engine->execute($context2); // 批次号应该保持不变 $this->assertEquals($batchNo1, $result2->batchNo); } /** * 测试新流程生成新批次号 */ public function testNewProcessGeneratesNewBatchNo(): void { $engine = ProcessEngine::createStandard(); // 第一个流程 $context1 = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result1 = $engine->execute($context1); $batchNo1 = $result1->batchNo; // 完成第一个流程 $contextEnd = $this->createContext([ 'readerType' => '结束', 'currentStep' => '清洗', 'endoscopeId' => '', 'batchNo' => $batchNo1, 'morningWashed' => true, ]); $engine->execute($contextEnd); // 第二个流程(新流程) $context2 = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '结束', // 上一步已结束 'endoscopeId' => '', 'morningWashed' => true, ]); $result2 = $engine->execute($context2); $batchNo2 = $result2->batchNo; // 新流程应该有新的批次号 $this->assertNotEquals($batchNo1, $batchNo2); } /** * 测试分布式场景下的批次号一致性(模拟) */ public function testDistributedBatchConsistency(): void { // 模拟机器A(清洗) $engineA = ProcessEngine::createStandard(); $contextA = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $resultA = $engineA->execute($contextA); $batchNo = $resultA->batchNo; // 模拟机器B(消毒)- 从数据库获取批次号 $engineB = ProcessEngine::createStandard(); $contextB = $this->createContext([ 'readerType' => '消毒', 'currentStep' => '漂洗', 'endoscopeId' => '', 'batchNo' => $batchNo, // 从数据库获取的批次号 'morningWashed' => true, ]); $resultB = $engineB->execute($contextB); // 批次号应该一致 $this->assertEquals($batchNo, $resultB->batchNo); } /** * 测试批次号在错误情况下的保持 */ public function testBatchNoPreservedOnError(): void { $engine = ProcessEngine::createStandard(); // 开始清洗 $context1 = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result1 = $engine->execute($context1); $batchNo = $result1->batchNo; // 完成漂洗 $contextRinse = $this->createContext([ 'readerType' => '漂洗', 'currentStep' => '清洗', 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); $this->setStepTime($contextRinse, '清洗', 400); // 清洗时间足够 $resultRinse = $engine->execute($contextRinse); $this->assertSuccess($resultRinse); // 尝试再次漂洗(重复刷漂洗读卡器,时间验证会失败) $context2 = $this->createContext([ 'readerType' => '漂洗', 'currentStep' => '漂洗', // 当前已经是漂洗 'endoscopeId' => '', 'batchNo' => $batchNo, 'morningWashed' => true, ]); // 设置漂洗步骤的上次时间为刚刚(时间不足) $context2->setStepLastTime('漂洗', date('Y-m-d H:i:s', time() - 30)); $result2 = $engine->execute($context2); // 执行失败(重复步骤或时间不足),但批次号应该保持不变 $this->assertEquals($batchNo, $result2->batchNo); } /** * 测试不同流程类型的批次号 */ public function testBatchNoWithDifferentProcessTypes(): void { $engine = ProcessEngine::createStandard(); // 手工洗流程 $context1 = $this->createContext([ 'readerType' => '清洗', 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result1 = $engine->execute($context1); $batchNo1 = $result1->batchNo; $this->assertEquals('手工洗', $result1->processType); // 机洗流程 $engineMachine = ProcessEngine::createMachineWash(); $context2 = $this->createContext([ 'readerType' => '机洗', // 使用机洗读卡器 'currentStep' => '', 'endoscopeId' => '', 'morningWashed' => true, ]); $result2 = $engineMachine->execute($context2); $batchNo2 = $result2->batchNo; $this->assertEquals('机洗', $result2->processType); // 不同流程的批次号应该不同 $this->assertNotEquals($batchNo1, $batchNo2); } }