@@ -661,6 +661,73 @@ def test_log_file(request):
661
661
assert "This log message won't be shown" not in contents
662
662
663
663
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
+
664
731
def test_log_file_cli_level (pytester : Pytester ) -> None :
665
732
# Default log file level
666
733
pytester .makepyfile (
@@ -741,6 +808,47 @@ def test_log_file(request):
741
808
assert "This log message won't be shown" not in contents
742
809
743
810
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
+
744
852
def test_log_file_ini_level (pytester : Pytester ) -> None :
745
853
log_file = str (pytester .path .joinpath ("pytest.log" ))
746
854
@@ -1060,6 +1168,66 @@ def test_second():
1060
1168
assert "message from test 2" in content
1061
1169
1062
1170
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
+
1063
1231
def test_colored_captured_log (pytester : Pytester ) -> None :
1064
1232
"""Test that the level names of captured log messages of a failing test
1065
1233
are colored."""
0 commit comments