@@ -661,6 +661,73 @@ def test_log_file(request):
661661 assert "This log message won't be shown" not in contents
662662
663663
664+ def test_log_file_mode_cli (pytester : Pytester ) -> None :
665+ # Default log file level
666+ pytester .makepyfile (
667+ """
668+ import pytest
669+ import logging
670+ def test_log_file(request):
671+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
672+ assert plugin.log_file_handler.level == logging.WARNING
673+ logging.getLogger('catchlog').info("This log message won't be shown")
674+ logging.getLogger('catchlog').warning("This log message will be shown")
675+ print('PASSED')
676+ """
677+ )
678+
679+ log_file = str (pytester .path .joinpath ("pytest.log" ))
680+
681+ with open (log_file , mode = "w" , encoding = "utf-8" ) as wfh :
682+ wfh .write ("A custom header\n " )
683+
684+ result = pytester .runpytest (
685+ "-s" ,
686+ f"--log-file={ log_file } " ,
687+ "--log-file-mode=a" ,
688+ "--log-file-level=WARNING" ,
689+ )
690+
691+ # fnmatch_lines does an assertion internally
692+ result .stdout .fnmatch_lines (["test_log_file_mode_cli.py PASSED" ])
693+
694+ # make sure that we get a '0' exit code for the testsuite
695+ assert result .ret == 0
696+ assert os .path .isfile (log_file )
697+ with open (log_file , encoding = "utf-8" ) as rfh :
698+ contents = rfh .read ()
699+ assert "A custom header" in contents
700+ assert "This log message will be shown" in contents
701+ assert "This log message won't be shown" not in contents
702+
703+
704+ def test_log_file_mode_cli_invalid (pytester : Pytester ) -> None :
705+ # Default log file level
706+ pytester .makepyfile (
707+ """
708+ import pytest
709+ import logging
710+ def test_log_file(request):
711+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
712+ assert plugin.log_file_handler.level == logging.WARNING
713+ logging.getLogger('catchlog').info("This log message won't be shown")
714+ logging.getLogger('catchlog').warning("This log message will be shown")
715+ """
716+ )
717+
718+ log_file = str (pytester .path .joinpath ("pytest.log" ))
719+
720+ result = pytester .runpytest (
721+ "-s" ,
722+ f"--log-file={ log_file } " ,
723+ "--log-file-mode=b" ,
724+ "--log-file-level=WARNING" ,
725+ )
726+
727+ # make sure that we get a '4' exit code for the testsuite
728+ assert result .ret == ExitCode .USAGE_ERROR
729+
730+
664731def test_log_file_cli_level (pytester : Pytester ) -> None :
665732 # Default log file level
666733 pytester .makepyfile (
@@ -741,6 +808,47 @@ def test_log_file(request):
741808 assert "This log message won't be shown" not in contents
742809
743810
811+ def test_log_file_mode_ini (pytester : Pytester ) -> None :
812+ log_file = str (pytester .path .joinpath ("pytest.log" ))
813+
814+ pytester .makeini (
815+ f"""
816+ [pytest]
817+ log_file={ log_file }
818+ log_file_mode=a
819+ log_file_level=WARNING
820+ """
821+ )
822+ pytester .makepyfile (
823+ """
824+ import pytest
825+ import logging
826+ def test_log_file(request):
827+ plugin = request.config.pluginmanager.getplugin('logging-plugin')
828+ assert plugin.log_file_handler.level == logging.WARNING
829+ logging.getLogger('catchlog').info("This log message won't be shown")
830+ logging.getLogger('catchlog').warning("This log message will be shown")
831+ print('PASSED')
832+ """
833+ )
834+
835+ with open (log_file , mode = "w" , encoding = "utf-8" ) as wfh :
836+ wfh .write ("A custom header\n " )
837+
838+ result = pytester .runpytest ("-s" )
839+
840+ # fnmatch_lines does an assertion internally
841+ result .stdout .fnmatch_lines (["test_log_file_mode_ini.py PASSED" ])
842+
843+ assert result .ret == ExitCode .OK
844+ assert os .path .isfile (log_file )
845+ with open (log_file , encoding = "utf-8" ) as rfh :
846+ contents = rfh .read ()
847+ assert "A custom header" in contents
848+ assert "This log message will be shown" in contents
849+ assert "This log message won't be shown" not in contents
850+
851+
744852def test_log_file_ini_level (pytester : Pytester ) -> None :
745853 log_file = str (pytester .path .joinpath ("pytest.log" ))
746854
@@ -1060,6 +1168,66 @@ def test_second():
10601168 assert "message from test 2" in content
10611169
10621170
1171+ def test_log_set_path_with_log_file_mode (pytester : Pytester ) -> None :
1172+ report_dir_base = str (pytester .path )
1173+
1174+ pytester .makeini (
1175+ """
1176+ [pytest]
1177+ log_file_level = DEBUG
1178+ log_cli=true
1179+ log_file_mode=a
1180+ """
1181+ )
1182+ pytester .makeconftest (
1183+ f"""
1184+ import os
1185+ import pytest
1186+ @pytest.hookimpl(wrapper=True, tryfirst=True)
1187+ def pytest_runtest_setup(item):
1188+ config = item.config
1189+ logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
1190+ report_file = os.path.join({ report_dir_base !r} , item._request.node.name)
1191+ logging_plugin.set_log_path(report_file)
1192+ return (yield)
1193+ """
1194+ )
1195+ pytester .makepyfile (
1196+ """
1197+ import logging
1198+ logger = logging.getLogger("testcase-logger")
1199+ def test_first():
1200+ logger.info("message from test 1")
1201+ assert True
1202+
1203+ def test_second():
1204+ logger.debug("message from test 2")
1205+ assert True
1206+ """
1207+ )
1208+
1209+ test_first_log_file = os .path .join (report_dir_base , "test_first" )
1210+ test_second_log_file = os .path .join (report_dir_base , "test_second" )
1211+ with open (test_first_log_file , mode = "w" , encoding = "utf-8" ) as wfh :
1212+ wfh .write ("A custom header for test 1\n " )
1213+
1214+ with open (test_second_log_file , mode = "w" , encoding = "utf-8" ) as wfh :
1215+ wfh .write ("A custom header for test 2\n " )
1216+
1217+ result = pytester .runpytest ()
1218+ assert result .ret == ExitCode .OK
1219+
1220+ with open (test_first_log_file , encoding = "utf-8" ) as rfh :
1221+ content = rfh .read ()
1222+ assert "A custom header for test 1" in content
1223+ assert "message from test 1" in content
1224+
1225+ with open (test_second_log_file , encoding = "utf-8" ) as rfh :
1226+ content = rfh .read ()
1227+ assert "A custom header for test 2" in content
1228+ assert "message from test 2" in content
1229+
1230+
10631231def test_colored_captured_log (pytester : Pytester ) -> None :
10641232 """Test that the level names of captured log messages of a failing test
10651233 are colored."""
0 commit comments