@@ -96,6 +96,11 @@ async def run(
9696 blueprint .total_steps ,
9797 "开启" if smart_repair_enabled else "关闭" )
9898
99+ # v10.2:如果蓝本有 start_command,先启动被测应用并等待就绪
100+ self ._app_started_by_runner = False
101+ if getattr (blueprint , "start_command" , "" ) and blueprint .start_command .strip ():
102+ await self ._auto_start_app (blueprint )
103+
99104 # v2.0:通知控制器测试开始
100105 if self ._controller :
101106 self ._controller .start (total_steps = blueprint .total_steps )
@@ -638,3 +643,54 @@ def _generate_markdown(
638643 ])
639644
640645 return "\n " .join (lines )
646+
647+ # ── v10.2:自动启动被测应用 ────────────────────────
648+
649+ async def _auto_start_app (self , blueprint : Blueprint ) -> None :
650+ """根据蓝本中的 start_command 自动启动被测应用并等待就绪。"""
651+ import urllib .request
652+ import urllib .error
653+ from pathlib import Path
654+
655+ cmd = blueprint .start_command .strip ()
656+ cwd = blueprint .start_cwd .strip () or "."
657+ base_url = blueprint .base_url .strip ()
658+
659+ logger .info ("自动启动被测应用 | cmd={} | cwd={} | base_url={}" , cmd , cwd , base_url )
660+
661+ # 先检查 base_url 是否已经可访问(应用可能已在运行)
662+ if base_url and await self ._check_url_ready (base_url ):
663+ logger .info ("被测应用已在运行: {}" , base_url )
664+ return
665+
666+ # 通过 process_runner 启动应用
667+ from src .testing .process_runner import process_runner
668+ success = await process_runner .start (cmd , cwd )
669+ if not success :
670+ logger .warning ("应用启动失败或已在运行: {}" , cmd )
671+ return
672+
673+ self ._app_started_by_runner = True
674+
675+ # 等待 base_url 可访问(最多30秒)
676+ if base_url :
677+ logger .info ("等待应用就绪: {}" , base_url )
678+ import asyncio
679+ for i in range (30 ):
680+ if await self ._check_url_ready (base_url ):
681+ logger .info ("应用已就绪(等待{}秒): {}" , i + 1 , base_url )
682+ return
683+ await asyncio .sleep (1 )
684+ logger .warning ("应用启动超时(30秒),继续测试: {}" , base_url )
685+
686+ @staticmethod
687+ async def _check_url_ready (url : str ) -> bool :
688+ """检查URL是否可访问。"""
689+ import urllib .request
690+ import urllib .error
691+ try :
692+ req = urllib .request .Request (url , method = "HEAD" )
693+ with urllib .request .urlopen (req , timeout = 2 ):
694+ return True
695+ except Exception :
696+ return False
0 commit comments