@@ -97,7 +97,7 @@ def materialize_test_profiles(tmp_dir: Path) -> Path:
9797 return profiles_dir
9898
9999
100- def preserve_tmp_dir_on_failure (tmp_dir ):
100+ def preserve_tmp_dir_on_failure (tmp_dir , * , force : bool = False ):
101101 """Copy tmp_dir to test-artifacts/ when this worker saw any failure.
102102
103103 Called by integration-test fixture teardowns BEFORE they rmtree the
@@ -132,7 +132,7 @@ def preserve_tmp_dir_on_failure(tmp_dir):
132132 # tmp_dir regardless of that worker's own failure state. Used during
133133 # concurrency investigations where a failure on worker B needs to be
134134 # correlated against what worker A was doing at the same time.
135- force = os .environ .get ("CAPSEM_TEST_PRESERVE_ALWAYS" )
135+ force = force or bool ( os .environ .get ("CAPSEM_TEST_PRESERVE_ALWAYS" ) )
136136 if not force and not FAILED_NODEIDS :
137137 return
138138 import stat as statmod
@@ -346,7 +346,14 @@ def stop(self, *, cleanup: bool = True):
346346 if not cleanup :
347347 return
348348
349- preserve_tmp_dir_on_failure (self .home_dir )
349+ # Tests commonly stop the service from a ``finally`` block. That
350+ # happens before pytest's makereport hook records FAILED_NODEIDS, so
351+ # use the actively-propagating exception as authoritative failure
352+ # evidence instead of deleting the only service/process logs.
353+ if sys .exc_info ()[0 ] is not None :
354+ preserve_tmp_dir_on_failure (self .home_dir , force = True )
355+ else :
356+ preserve_tmp_dir_on_failure (self .home_dir )
350357
351358 if self .home_dir .exists ():
352359 shutil .rmtree (self .home_dir , ignore_errors = True )
0 commit comments