44from .TestConfigProp import TestConfigPropNames
55from .TestStartupData import TestStartupData
66from .TestGlobalCache import TestGlobalCache
7+ from .TestServices import TestServices
78
89import pluggy
910import pytest
1819import _pytest .unittest
1920import _pytest .logging
2021
22+ # /////////////////////////////////////////////////////////////////////////////
23+
24+ T_TUPLE__str_int = typing .Tuple [str ,int ]
25+
2126# /////////////////////////////////////////////////////////////////////////////
2227# TEST_PROCESS_STATS
2328
@@ -35,11 +40,11 @@ class TEST_PROCESS_STATS:
3540cUnexpectedTests :int = 0
3641cAchtungTests :int = 0
3742
38- FailedTests = list [ str , int ] ()
39- XFailedTests = list [ str , int ] ()
40- NotXFailedTests = list [str ]()
41- WarningTests = list [ str , int ] ()
42- AchtungTests = list [str ]()
43+ FailedTests : typing . List [ T_TUPLE__str_int ] = list ()
44+ XFailedTests : typing . List [ T_TUPLE__str_int ] = list ()
45+ NotXFailedTests : typing . List [str ]= list ()
46+ WarningTests : typing . List [ T_TUPLE__str_int ] = list ()
47+ AchtungTests : typing . List [str ]= list ()
4348
4449cTotalDuration :datetime .timedelta = datetime .timedelta ()
4550
@@ -303,6 +308,15 @@ def helper__makereport__setup(
303308return
304309
305310
311+ # ------------------------------------------------------------------------
312+ class ExitStatusNames :
313+ FAILED = "FAILED"
314+ PASSED = "PASSED"
315+ XFAILED = "XFAILED"
316+ SKIPPED = "SKIPPED"
317+ UNEXPECTED = "UNEXPECTED"
318+
319+
306320# ------------------------------------------------------------------------
307321def helper__makereport__call (
308322item :pytest .Function ,call :pytest .CallInfo ,outcome :pluggy .Result
@@ -345,28 +359,29 @@ def helper__makereport__call(
345359
346360# --------
347361exitStatus = None
362+ exitStatusInfo = None
348363if rep .outcome == "skipped" :
349364assert call .excinfo is not None # research
350365assert call .excinfo .value is not None # research
351366
352367if type (call .excinfo .value )== _pytest .outcomes .Skipped :# noqa: E721
353368assert not hasattr (rep ,"wasxfail" )
354369
355- exitStatus = " SKIPPED"
370+ exitStatus = ExitStatusNames . SKIPPED
356371reasonText = str (call .excinfo .value )
357372reasonMsgTempl = "SKIP REASON: {0}"
358373
359374TEST_PROCESS_STATS .incrementSkippedTestCount ()
360375
361376elif type (call .excinfo .value )== _pytest .outcomes .XFailed :# noqa: E721
362- exitStatus = " XFAILED"
377+ exitStatus = ExitStatusNames . XFAILED
363378reasonText = str (call .excinfo .value )
364379reasonMsgTempl = "XFAIL REASON: {0}"
365380
366381TEST_PROCESS_STATS .incrementXFailedTestCount (testID ,item_error_msg_count )
367382
368383else :
369- exitStatus = " XFAILED"
384+ exitStatus = ExitStatusNames . XFAILED
370385assert hasattr (rep ,"wasxfail" )
371386assert rep .wasxfail is not None
372387assert type (rep .wasxfail )== str # noqa: E721
@@ -403,7 +418,7 @@ def helper__makereport__call(
403418assert item_error_msg_count > 0
404419TEST_PROCESS_STATS .incrementFailedTestCount (testID ,item_error_msg_count )
405420
406- exitStatus = " FAILED"
421+ exitStatus = ExitStatusNames . FAILED
407422elif rep .outcome == "passed" :
408423assert call .excinfo is None
409424
@@ -423,17 +438,25 @@ def helper__makereport__call(
423438assert not hasattr (rep ,"wasxfail" )
424439
425440TEST_PROCESS_STATS .incrementPassedTestCount ()
426- exitStatus = " PASSED"
441+ exitStatus = ExitStatusNames . PASSED
427442else :
428443TEST_PROCESS_STATS .incrementUnexpectedTests ()
429- exitStatus = "UNEXPECTED [{0}]" .format (rep .outcome )
444+ exitStatus = ExitStatusNames .UNEXPECTED
445+ exitStatusInfo = rep .outcome
430446# [2025-03-28] It may create a useless problem in new environment.
431447# assert False
432448
433449# --------
434450if item_warning_msg_count > 0 :
435451TEST_PROCESS_STATS .incrementWarningTestCount (testID ,item_warning_msg_count )
436452
453+ # --------
454+ if exitStatus == ExitStatusNames .FAILED :
455+ assert item_error_msg_count > 0
456+ pass
457+ else :
458+ TestServices .CleanTestTmpDirBeforeExit (item )
459+
437460# --------
438461assert type (TEST_PROCESS_STATS .cTotalDuration )== datetime .timedelta # noqa: E721
439462assert type (testDurration )== datetime .timedelta # noqa: E721
@@ -442,11 +465,17 @@ def helper__makereport__call(
442465
443466assert testDurration <= TEST_PROCESS_STATS .cTotalDuration
444467
468+ # --------
469+ exitStatusLineData = exitStatus
470+
471+ if exitStatusInfo is not None :
472+ exitStatusLineData += " [{}]" .format (exitStatusInfo )
473+
445474# --------
446475logging .info ("*" )
447476logging .info ("* DURATION : {0}" .format (timedelta_to_human_text (testDurration )))
448477logging .info ("*" )
449- logging .info ("* EXIT STATUS : {0}" .format (exitStatus ))
478+ logging .info ("* EXIT STATUS : {0}" .format (exitStatusLineData ))
450479logging .info ("* ERROR COUNT : {0}" .format (item_error_msg_count ))
451480logging .info ("* WARNING COUNT: {0}" .format (item_warning_msg_count ))
452481logging .info ("*" )
@@ -694,7 +723,7 @@ def helper__calc_W(n: int) -> int:
694723
695724
696725# ------------------------------------------------------------------------
697- def helper__print_test_list (tests :list [str ])-> None :
726+ def helper__print_test_list (tests :typing . List [str ])-> None :
698727assert type (tests )== list # noqa: E721
699728
700729assert helper__calc_W (9 )== 1
@@ -721,7 +750,7 @@ def helper__print_test_list(tests: list[str]) -> None:
721750
722751
723752# ------------------------------------------------------------------------
724- def helper__print_test_list2 (tests :list [ str , int ])-> None :
753+ def helper__print_test_list2 (tests :typing . List [ T_TUPLE__str_int ])-> None :
725754assert type (tests )== list # noqa: E721
726755
727756assert helper__calc_W (9 )== 1
@@ -773,7 +802,9 @@ def LOCAL__print_line1_with_header(header: str):
773802assert header != ""
774803logging .info (C_LINE1 + " [" + header + "]" )
775804
776- def LOCAL__print_test_list (header :str ,test_count :int ,test_list :list [str ]):
805+ def LOCAL__print_test_list (
806+ header :str ,test_count :int ,test_list :typing .List [str ]
807+ ):
777808assert type (header )== str # noqa: E721
778809assert type (test_count )== int # noqa: E721
779810assert type (test_list )== list # noqa: E721
@@ -788,7 +819,7 @@ def LOCAL__print_test_list(header: str, test_count: int, test_list: list[str]):
788819logging .info ("" )
789820
790821def LOCAL__print_test_list2 (
791- header :str ,test_count :int ,test_list :list [ str , int ]
822+ header :str ,test_count :int ,test_list :typing . List [ T_TUPLE__str_int ]
792823 ):
793824assert type (header )== str # noqa: E721
794825assert type (test_count )== int # noqa: E721
@@ -880,13 +911,9 @@ def pytest_configure(config: pytest.Config) -> None:
880911log_name = TestStartupData .GetCurrentTestWorkerSignature ()
881912log_name += ".log"
882913
883- if TestConfigPropNames .TEST_CFG__LOG_DIR in os .environ :
884- log_path_v = os .environ [TestConfigPropNames .TEST_CFG__LOG_DIR ]
885- log_path = pathlib .Path (log_path_v )
886- else :
887- log_path = config .rootpath .joinpath ("logs" )
914+ log_dir = TestStartupData .GetRootLogDir ()
888915
889- log_path .mkdir (exist_ok = True )
916+ pathlib . Path ( log_dir ) .mkdir (exist_ok = True )
890917
891918logging_plugin :_pytest .logging .LoggingPlugin = config .pluginmanager .get_plugin (
892919"logging-plugin"
@@ -895,7 +922,7 @@ def pytest_configure(config: pytest.Config) -> None:
895922assert logging_plugin is not None
896923assert isinstance (logging_plugin ,_pytest .logging .LoggingPlugin )
897924
898- logging_plugin .set_log_path (str ( log_path / log_name ))
925+ logging_plugin .set_log_path (os . path . join ( log_dir , log_name ))
899926
900927
901928# /////////////////////////////////////////////////////////////////////////////