11# /////////////////////////////////////////////////////////////////////////////
22# PyTest Configuration
33
4- import _pytest .outcomes
5-
64import pluggy
75import pytest
8- import _pytest
96import os
107import logging
118import pathlib
129import math
1310import datetime
1411
12+ import _pytest .outcomes
13+ import _pytest .unittest
14+ import _pytest .logging
15+
1516# /////////////////////////////////////////////////////////////////////////////
1617
1718C_ROOT_DIR__RELATIVE = ".."
@@ -91,10 +92,6 @@ def GetCurrentTestWorkerSignature() -> str:
9192return __class__ .sm_CurrentTestWorkerSignature
9293
9394
94- # /////////////////////////////////////////////////////////////////////////////# /////////////////////////////////////////////////////////////////////////////
95- # Fixtures
96-
97-
9895# /////////////////////////////////////////////////////////////////////////////
9996# TEST_PROCESS_STATS
10097
@@ -109,10 +106,12 @@ class TEST_PROCESS_STATS:
109106cSkippedTests :int = 0
110107cNotXFailedTests :int = 0
111108cUnexpectedTests :int = 0
109+ cAchtungTests :int = 0
112110
113111FailedTests = list [str ]()
114112XFailedTests = list [str ]()
115113NotXFailedTests = list [str ]()
114+ AchtungTests = list [str ]()
116115
117116# --------------------------------------------------------------------
118117def incrementTotalTestCount ()-> None :
@@ -163,6 +162,14 @@ def incrementNotXFailedTests(testID: str) -> None:
163162def incrementUnexpectedTests ()-> None :
164163__class__ .cUnexpectedTests += 1
165164
165+ # --------------------------------------------------------------------
166+ def incrementAchtungTestCount (testID :str )-> None :
167+ assert type (testID )== str # noqa: E721
168+ assert type (__class__ .AchtungTests )== list # noqa: E721
169+
170+ __class__ .AchtungTests .append (testID )# raise?
171+ __class__ .cAchtungTests += 1
172+
166173
167174# /////////////////////////////////////////////////////////////////////////////
168175
@@ -198,10 +205,13 @@ def helper__makereport__setup(
198205assert item is not None
199206assert call is not None
200207assert outcome is not None
201- assert type (item )== pytest .Function # noqa: E721
208+ # it may be pytest.Function or _pytest.unittest.TestCaseFunction
209+ assert isinstance (item ,pytest .Function )
202210assert type (call )== pytest .CallInfo # noqa: E721
203211assert type (outcome )== pluggy .Result # noqa: E721
204212
213+ C_LINE1 = "******************************************************"
214+
205215# logging.info("pytest_runtest_makereport - setup")
206216
207217TEST_PROCESS_STATS .incrementTotalTestCount ()
@@ -214,26 +224,42 @@ def helper__makereport__setup(
214224TEST_PROCESS_STATS .incrementNotExecutedTestCount ()
215225return
216226
217- assert rep .outcome == "passed"
218-
219- testNumber = TEST_PROCESS_STATS .incrementExecutedTestCount ()
220-
221227testID = ""
222228
223229if item .cls is not None :
224230testID = item .cls .__module__ + "." + item .cls .__name__ + "::"
225231
226232testID = testID + item .name
227233
228- if testNumber > 1 :
229- logging .info ("" )
234+ if rep .outcome == "passed" :
235+ testNumber = TEST_PROCESS_STATS .incrementExecutedTestCount ()
236+
237+ logging .info (C_LINE1 )
238+ logging .info ("* START TEST {0}" .format (testID ))
239+ logging .info ("*" )
240+ logging .info ("* Path : {0}" .format (item .path ))
241+ logging .info ("* Number: {0}" .format (testNumber ))
242+ logging .info ("*" )
243+ return
244+
245+ assert rep .outcome != "passed"
246+
247+ TEST_PROCESS_STATS .incrementAchtungTestCount (testID )
230248
231- logging .info ("******************************************************" )
232- logging .info ("*START TEST {0}" .format (testID ))
249+ logging .info (C_LINE1 )
250+ logging .info ("*ACHTUNG TEST {0}" .format (testID ))
233251logging .info ("*" )
234252logging .info ("* Path : {0}" .format (item .path ))
235- logging .info ("* Number: {0}" .format (testNumber ))
253+ logging .info ("* Outcome is [{0}]" .format (rep .outcome ))
254+
255+ if rep .outcome == "failed" :
256+ assert call .excinfo is not None
257+ assert call .excinfo .value is not None
258+ logging .info ("*" )
259+ logging .error (call .excinfo .value )
260+
236261logging .info ("*" )
262+ return
237263
238264
239265# ------------------------------------------------------------------------
@@ -243,12 +269,11 @@ def helper__makereport__call(
243269assert item is not None
244270assert call is not None
245271assert outcome is not None
246- assert type (item )== pytest .Function # noqa: E721
272+ # it may be pytest.Function or _pytest.unittest.TestCaseFunction
273+ assert isinstance (item ,pytest .Function )
247274assert type (call )== pytest .CallInfo # noqa: E721
248275assert type (outcome )== pluggy .Result # noqa: E721
249276
250- # logging.info("pytest_runtest_makereport - call")
251-
252277rep = outcome .get_result ()
253278assert rep is not None
254279assert type (rep )== pytest .TestReport # noqa: E721
@@ -341,7 +366,8 @@ def helper__makereport__call(
341366else :
342367TEST_PROCESS_STATS .incrementUnexpectedTests ()
343368exitStatus = "UNEXPECTED [{0}]" .format (rep .outcome )
344- assert False
369+ # [2025-03-28] It may create a useless problem in new environment.
370+ # assert False
345371
346372# --------
347373logging .info ("*" )
@@ -350,6 +376,7 @@ def helper__makereport__call(
350376logging .info ("* EXIT STATUS : {0}" .format (exitStatus ))
351377logging .info ("*" )
352378logging .info ("* STOP TEST {0}" .format (testID ))
379+ logging .info ("*" )
353380
354381
355382# /////////////////////////////////////////////////////////////////////////////
@@ -359,17 +386,14 @@ def helper__makereport__call(
359386def pytest_runtest_makereport (item :pytest .Function ,call :pytest .CallInfo ):
360387assert item is not None
361388assert call is not None
362- assert type (item )== pytest .Function # noqa: E721
389+ # it may be pytest.Function or _pytest.unittest.TestCaseFunction
390+ assert isinstance (item ,pytest .Function )
363391assert type (call )== pytest .CallInfo # noqa: E721
364392
365- # logging.info("[pytest_runtest_makereport][#001][{0}][{1}]".format(item.name, call.when))
366-
367393outcome :pluggy .Result = yield
368394assert outcome is not None
369395assert type (outcome )== pluggy .Result # noqa: E721
370396
371- # logging.info("[pytest_runtest_makereport][#002][{0}][{1}]".format(item.name, call.when))
372-
373397rep :pytest .TestReport = outcome .get_result ()
374398assert rep is not None
375399assert type (rep )== pytest .TestReport # noqa: E721
@@ -440,41 +464,61 @@ def run_after_tests(request: pytest.FixtureRequest):
440464
441465yield
442466
443- logging .info ("--------------------------- [FAILED TESTS]" )
444- logging .info ("" )
445-
446- assert len (TEST_PROCESS_STATS .FailedTests )== TEST_PROCESS_STATS .cFailedTests
447-
448- if len (TEST_PROCESS_STATS .FailedTests )> 0 :
449- helper__print_test_list (TEST_PROCESS_STATS .FailedTests )
450- logging .info ("" )
467+ C_LINE1 = "---------------------------"
451468
452- logging .info ("--------------------------- [XFAILED TESTS]" )
453- logging .info ("" )
469+ def LOCAL__print_line1_with_header (header :str ):
470+ assert type (C_LINE1 )== str # noqa: E721
471+ assert type (header )== str # noqa: E721
472+ assert header != ""
473+ logging .info (C_LINE1 + " [" + header + "]" )
454474
455- assert len (TEST_PROCESS_STATS .XFailedTests )== TEST_PROCESS_STATS .cXFailedTests
475+ def LOCAL__print_test_list (header :str ,test_count :int ,test_list :list [str ]):
476+ assert type (header )== str # noqa: E721
477+ assert type (test_count )== int # noqa: E721
478+ assert type (test_list )== list # noqa: E721
479+ assert header != ""
480+ assert test_count >= 0
481+ assert len (test_list )== test_count
456482
457- if len (TEST_PROCESS_STATS .XFailedTests )> 0 :
458- helper__print_test_list (TEST_PROCESS_STATS .XFailedTests )
483+ LOCAL__print_line1_with_header (header )
459484logging .info ("" )
485+ if len (test_list )> 0 :
486+ helper__print_test_list (test_list )
487+ logging .info ("" )
488+
489+ # fmt: off
490+ LOCAL__print_test_list (
491+ "ACHTUNG TESTS" ,
492+ TEST_PROCESS_STATS .cAchtungTests ,
493+ TEST_PROCESS_STATS .AchtungTests ,
494+ )
460495
461- logging .info ("--------------------------- [NOT XFAILED TESTS]" )
462- logging .info ("" )
496+ LOCAL__print_test_list (
497+ "FAILED TESTS" ,
498+ TEST_PROCESS_STATS .cFailedTests ,
499+ TEST_PROCESS_STATS .FailedTests
500+ )
463501
464- assert (
465- len (TEST_PROCESS_STATS .NotXFailedTests )== TEST_PROCESS_STATS .cNotXFailedTests
502+ LOCAL__print_test_list (
503+ "XFAILED TESTS" ,
504+ TEST_PROCESS_STATS .cXFailedTests ,
505+ TEST_PROCESS_STATS .XFailedTests ,
466506 )
467507
468- if len (TEST_PROCESS_STATS .NotXFailedTests )> 0 :
469- helper__print_test_list (TEST_PROCESS_STATS .NotXFailedTests )
470- logging .info ("" )
508+ LOCAL__print_test_list (
509+ "NOT XFAILED TESTS" ,
510+ TEST_PROCESS_STATS .cNotXFailedTests ,
511+ TEST_PROCESS_STATS .NotXFailedTests ,
512+ )
513+ # fmt: on
471514
472- logging . info ( "--------------------------- [ SUMMARY STATISTICS] " )
515+ LOCAL__print_line1_with_header ( " SUMMARY STATISTICS" )
473516logging .info ("" )
474517logging .info ("[TESTS]" )
475518logging .info (" TOTAL : {0}" .format (TEST_PROCESS_STATS .cTotalTests ))
476519logging .info (" EXECUTED : {0}" .format (TEST_PROCESS_STATS .cExecutedTests ))
477520logging .info (" NOT EXECUTED: {0}" .format (TEST_PROCESS_STATS .cNotExecutedTests ))
521+ logging .info (" ACHTUNG : {0}" .format (TEST_PROCESS_STATS .cAchtungTests ))
478522logging .info ("" )
479523logging .info (" PASSED : {0}" .format (TEST_PROCESS_STATS .cPassedTests ))
480524logging .info (" FAILED : {0}" .format (TEST_PROCESS_STATS .cFailedTests ))
@@ -503,7 +547,13 @@ def pytest_configure(config: pytest.Config) -> None:
503547
504548log_path .mkdir (exist_ok = True )
505549
506- logging_plugin = config .pluginmanager .get_plugin ("logging-plugin" )
550+ logging_plugin :_pytest .logging .LoggingPlugin = config .pluginmanager .get_plugin (
551+ "logging-plugin"
552+ )
553+
554+ assert logging_plugin is not None
555+ assert isinstance (logging_plugin ,_pytest .logging .LoggingPlugin )
556+
507557logging_plugin .set_log_path (str (log_path / log_name ))
508558
509559