778 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			778 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			Python
		
	
	
	
# -*- coding: utf-8 -*-
 | 
						|
import re
 | 
						|
import os
 | 
						|
 | 
						|
import six
 | 
						|
 | 
						|
import pytest
 | 
						|
 | 
						|
 | 
						|
def test_nothing_logged(testdir):
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import sys
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            sys.stdout.write('text going to stdout')
 | 
						|
            sys.stderr.write('text going to stderr')
 | 
						|
            assert False
 | 
						|
        ''')
 | 
						|
    result = testdir.runpytest()
 | 
						|
    assert result.ret == 1
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stdout call -*',
 | 
						|
                                 'text going to stdout'])
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stderr call -*',
 | 
						|
                                 'text going to stderr'])
 | 
						|
    with pytest.raises(pytest.fail.Exception):
 | 
						|
        result.stdout.fnmatch_lines(['*- Captured *log call -*'])
 | 
						|
 | 
						|
 | 
						|
def test_messages_logged(testdir):
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import sys
 | 
						|
        import logging
 | 
						|
 | 
						|
        logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            sys.stdout.write('text going to stdout')
 | 
						|
            sys.stderr.write('text going to stderr')
 | 
						|
            logger.info('text going to logger')
 | 
						|
            assert False
 | 
						|
        ''')
 | 
						|
    result = testdir.runpytest('--log-level=INFO')
 | 
						|
    assert result.ret == 1
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured *log call -*',
 | 
						|
                                 '*text going to logger*'])
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stdout call -*',
 | 
						|
                                 'text going to stdout'])
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stderr call -*',
 | 
						|
                                 'text going to stderr'])
 | 
						|
 | 
						|
 | 
						|
def test_root_logger_affected(testdir):
 | 
						|
    testdir.makepyfile("""
 | 
						|
        import logging
 | 
						|
        logger = logging.getLogger()
 | 
						|
        def test_foo():
 | 
						|
            logger.info('info text ' + 'going to logger')
 | 
						|
            logger.warning('warning text ' + 'going to logger')
 | 
						|
            logger.error('error text ' + 'going to logger')
 | 
						|
 | 
						|
            assert 0
 | 
						|
    """)
 | 
						|
    log_file = testdir.tmpdir.join('pytest.log').strpath
 | 
						|
    result = testdir.runpytest('--log-level=ERROR', '--log-file=pytest.log')
 | 
						|
    assert result.ret == 1
 | 
						|
 | 
						|
    # the capture log calls in the stdout section only contain the
 | 
						|
    # logger.error msg, because --log-level=ERROR
 | 
						|
    result.stdout.fnmatch_lines(['*error text going to logger*'])
 | 
						|
    with pytest.raises(pytest.fail.Exception):
 | 
						|
        result.stdout.fnmatch_lines(['*warning text going to logger*'])
 | 
						|
    with pytest.raises(pytest.fail.Exception):
 | 
						|
        result.stdout.fnmatch_lines(['*info text going to logger*'])
 | 
						|
 | 
						|
    # the log file should contain the warning and the error log messages and
 | 
						|
    # not the info one, because the default level of the root logger is
 | 
						|
    # WARNING.
 | 
						|
    assert os.path.isfile(log_file)
 | 
						|
    with open(log_file) as rfh:
 | 
						|
        contents = rfh.read()
 | 
						|
        assert "info text going to logger" not in contents
 | 
						|
        assert "warning text going to logger" in contents
 | 
						|
        assert "error text going to logger" in contents
 | 
						|
 | 
						|
 | 
						|
def test_log_cli_level_log_level_interaction(testdir):
 | 
						|
    testdir.makepyfile("""
 | 
						|
        import logging
 | 
						|
        logger = logging.getLogger()
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            logger.debug('debug text ' + 'going to logger')
 | 
						|
            logger.info('info text ' + 'going to logger')
 | 
						|
            logger.warning('warning text ' + 'going to logger')
 | 
						|
            logger.error('error text ' + 'going to logger')
 | 
						|
            assert 0
 | 
						|
    """)
 | 
						|
 | 
						|
    result = testdir.runpytest('--log-cli-level=INFO', '--log-level=ERROR')
 | 
						|
    assert result.ret == 1
 | 
						|
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        '*-- live log call --*',
 | 
						|
        '*INFO*info text going to logger',
 | 
						|
        '*WARNING*warning text going to logger',
 | 
						|
        '*ERROR*error text going to logger',
 | 
						|
        '=* 1 failed in *=',
 | 
						|
    ])
 | 
						|
    assert 'DEBUG' not in result.stdout.str()
 | 
						|
 | 
						|
 | 
						|
def test_setup_logging(testdir):
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import logging
 | 
						|
 | 
						|
        logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
        def setup_function(function):
 | 
						|
            logger.info('text going to logger from setup')
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            logger.info('text going to logger from call')
 | 
						|
            assert False
 | 
						|
    ''')
 | 
						|
    result = testdir.runpytest('--log-level=INFO')
 | 
						|
    assert result.ret == 1
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured *log setup -*',
 | 
						|
                                 '*text going to logger from setup*',
 | 
						|
                                 '*- Captured *log call -*',
 | 
						|
                                 '*text going to logger from call*'])
 | 
						|
 | 
						|
 | 
						|
def test_teardown_logging(testdir):
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import logging
 | 
						|
 | 
						|
        logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            logger.info('text going to logger from call')
 | 
						|
 | 
						|
        def teardown_function(function):
 | 
						|
            logger.info('text going to logger from teardown')
 | 
						|
            assert False
 | 
						|
        ''')
 | 
						|
    result = testdir.runpytest('--log-level=INFO')
 | 
						|
    assert result.ret == 1
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured *log call -*',
 | 
						|
                                 '*text going to logger from call*',
 | 
						|
                                 '*- Captured *log teardown -*',
 | 
						|
                                 '*text going to logger from teardown*'])
 | 
						|
 | 
						|
 | 
						|
def test_disable_log_capturing(testdir):
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import sys
 | 
						|
        import logging
 | 
						|
 | 
						|
        logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            sys.stdout.write('text going to stdout')
 | 
						|
            logger.warning('catch me if you can!')
 | 
						|
            sys.stderr.write('text going to stderr')
 | 
						|
            assert False
 | 
						|
        ''')
 | 
						|
    result = testdir.runpytest('--no-print-logs')
 | 
						|
    print(result.stdout)
 | 
						|
    assert result.ret == 1
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stdout call -*',
 | 
						|
                                 'text going to stdout'])
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stderr call -*',
 | 
						|
                                 'text going to stderr'])
 | 
						|
    with pytest.raises(pytest.fail.Exception):
 | 
						|
        result.stdout.fnmatch_lines(['*- Captured *log call -*'])
 | 
						|
 | 
						|
 | 
						|
def test_disable_log_capturing_ini(testdir):
 | 
						|
    testdir.makeini(
 | 
						|
        '''
 | 
						|
        [pytest]
 | 
						|
        log_print=False
 | 
						|
        '''
 | 
						|
    )
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import sys
 | 
						|
        import logging
 | 
						|
 | 
						|
        logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
        def test_foo():
 | 
						|
            sys.stdout.write('text going to stdout')
 | 
						|
            logger.warning('catch me if you can!')
 | 
						|
            sys.stderr.write('text going to stderr')
 | 
						|
            assert False
 | 
						|
        ''')
 | 
						|
    result = testdir.runpytest()
 | 
						|
    print(result.stdout)
 | 
						|
    assert result.ret == 1
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stdout call -*',
 | 
						|
                                 'text going to stdout'])
 | 
						|
    result.stdout.fnmatch_lines(['*- Captured stderr call -*',
 | 
						|
                                 'text going to stderr'])
 | 
						|
    with pytest.raises(pytest.fail.Exception):
 | 
						|
        result.stdout.fnmatch_lines(['*- Captured *log call -*'])
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('enabled', [True, False])
 | 
						|
def test_log_cli_enabled_disabled(testdir, enabled):
 | 
						|
    msg = 'critical message logged by test'
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import logging
 | 
						|
        def test_log_cli():
 | 
						|
            logging.critical("{}")
 | 
						|
    '''.format(msg))
 | 
						|
    if enabled:
 | 
						|
        testdir.makeini('''
 | 
						|
            [pytest]
 | 
						|
            log_cli=true
 | 
						|
        ''')
 | 
						|
    result = testdir.runpytest()
 | 
						|
    if enabled:
 | 
						|
        result.stdout.fnmatch_lines([
 | 
						|
            'test_log_cli_enabled_disabled.py::test_log_cli ',
 | 
						|
            '*-- live log call --*',
 | 
						|
            'test_log_cli_enabled_disabled.py* CRITICAL critical message logged by test',
 | 
						|
            'PASSED*',
 | 
						|
        ])
 | 
						|
    else:
 | 
						|
        assert msg not in result.stdout.str()
 | 
						|
 | 
						|
 | 
						|
def test_log_cli_default_level(testdir):
 | 
						|
    # Default log file level
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_cli(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_cli_handler.level == logging.NOTSET
 | 
						|
            logging.getLogger('catchlog').info("INFO message won't be shown")
 | 
						|
            logging.getLogger('catchlog').warning("WARNING message will be shown")
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest()
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_cli_default_level.py::test_log_cli ',
 | 
						|
        'test_log_cli_default_level.py*WARNING message will be shown*',
 | 
						|
    ])
 | 
						|
    assert "INFO message won't be shown" not in result.stdout.str()
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
 | 
						|
 | 
						|
def test_log_cli_default_level_multiple_tests(testdir, request):
 | 
						|
    """Ensure we reset the first newline added by the live logger between tests"""
 | 
						|
    filename = request.node.name + '.py'
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import logging
 | 
						|
 | 
						|
        def test_log_1():
 | 
						|
            logging.warning("log message from test_log_1")
 | 
						|
 | 
						|
        def test_log_2():
 | 
						|
            logging.warning("log message from test_log_2")
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest()
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        '{}::test_log_1 '.format(filename),
 | 
						|
        '*WARNING*log message from test_log_1*',
 | 
						|
        'PASSED *50%*',
 | 
						|
        '{}::test_log_2 '.format(filename),
 | 
						|
        '*WARNING*log message from test_log_2*',
 | 
						|
        'PASSED *100%*',
 | 
						|
        '=* 2 passed in *=',
 | 
						|
    ])
 | 
						|
 | 
						|
 | 
						|
def test_log_cli_default_level_sections(testdir, request):
 | 
						|
    """Check that with live logging enable we are printing the correct headers during
 | 
						|
    start/setup/call/teardown/finish."""
 | 
						|
    filename = request.node.name + '.py'
 | 
						|
    testdir.makeconftest('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        def pytest_runtest_logstart():
 | 
						|
            logging.warning('>>>>> START >>>>>')
 | 
						|
 | 
						|
        def pytest_runtest_logfinish():
 | 
						|
            logging.warning('<<<<< END <<<<<<<')
 | 
						|
    ''')
 | 
						|
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        @pytest.fixture
 | 
						|
        def fix(request):
 | 
						|
            logging.warning("log message from setup of {}".format(request.node.name))
 | 
						|
            yield
 | 
						|
            logging.warning("log message from teardown of {}".format(request.node.name))
 | 
						|
 | 
						|
        def test_log_1(fix):
 | 
						|
            logging.warning("log message from test_log_1")
 | 
						|
 | 
						|
        def test_log_2(fix):
 | 
						|
            logging.warning("log message from test_log_2")
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest()
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        '{}::test_log_1 '.format(filename),
 | 
						|
        '*-- live log start --*',
 | 
						|
        '*WARNING* >>>>> START >>>>>*',
 | 
						|
        '*-- live log setup --*',
 | 
						|
        '*WARNING*log message from setup of test_log_1*',
 | 
						|
        '*-- live log call --*',
 | 
						|
        '*WARNING*log message from test_log_1*',
 | 
						|
        'PASSED *50%*',
 | 
						|
        '*-- live log teardown --*',
 | 
						|
        '*WARNING*log message from teardown of test_log_1*',
 | 
						|
        '*-- live log finish --*',
 | 
						|
        '*WARNING* <<<<< END <<<<<<<*',
 | 
						|
 | 
						|
        '{}::test_log_2 '.format(filename),
 | 
						|
        '*-- live log start --*',
 | 
						|
        '*WARNING* >>>>> START >>>>>*',
 | 
						|
        '*-- live log setup --*',
 | 
						|
        '*WARNING*log message from setup of test_log_2*',
 | 
						|
        '*-- live log call --*',
 | 
						|
        '*WARNING*log message from test_log_2*',
 | 
						|
        'PASSED *100%*',
 | 
						|
        '*-- live log teardown --*',
 | 
						|
        '*WARNING*log message from teardown of test_log_2*',
 | 
						|
        '*-- live log finish --*',
 | 
						|
        '*WARNING* <<<<< END <<<<<<<*',
 | 
						|
        '=* 2 passed in *=',
 | 
						|
    ])
 | 
						|
 | 
						|
 | 
						|
def test_live_logs_unknown_sections(testdir, request):
 | 
						|
    """Check that with live logging enable we are printing the correct headers during
 | 
						|
    start/setup/call/teardown/finish."""
 | 
						|
    filename = request.node.name + '.py'
 | 
						|
    testdir.makeconftest('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        def pytest_runtest_protocol(item, nextitem):
 | 
						|
            logging.warning('Unknown Section!')
 | 
						|
 | 
						|
        def pytest_runtest_logstart():
 | 
						|
            logging.warning('>>>>> START >>>>>')
 | 
						|
 | 
						|
        def pytest_runtest_logfinish():
 | 
						|
            logging.warning('<<<<< END <<<<<<<')
 | 
						|
    ''')
 | 
						|
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        @pytest.fixture
 | 
						|
        def fix(request):
 | 
						|
            logging.warning("log message from setup of {}".format(request.node.name))
 | 
						|
            yield
 | 
						|
            logging.warning("log message from teardown of {}".format(request.node.name))
 | 
						|
 | 
						|
        def test_log_1(fix):
 | 
						|
            logging.warning("log message from test_log_1")
 | 
						|
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest()
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        '*WARNING*Unknown Section*',
 | 
						|
        '{}::test_log_1 '.format(filename),
 | 
						|
        '*WARNING* >>>>> START >>>>>*',
 | 
						|
        '*-- live log setup --*',
 | 
						|
        '*WARNING*log message from setup of test_log_1*',
 | 
						|
        '*-- live log call --*',
 | 
						|
        '*WARNING*log message from test_log_1*',
 | 
						|
        'PASSED *100%*',
 | 
						|
        '*-- live log teardown --*',
 | 
						|
        '*WARNING*log message from teardown of test_log_1*',
 | 
						|
        '*WARNING* <<<<< END <<<<<<<*',
 | 
						|
        '=* 1 passed in *=',
 | 
						|
    ])
 | 
						|
 | 
						|
 | 
						|
def test_sections_single_new_line_after_test_outcome(testdir, request):
 | 
						|
    """Check that only a single new line is written between log messages during
 | 
						|
    teardown/finish."""
 | 
						|
    filename = request.node.name + '.py'
 | 
						|
    testdir.makeconftest('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        def pytest_runtest_logstart():
 | 
						|
            logging.warning('>>>>> START >>>>>')
 | 
						|
 | 
						|
        def pytest_runtest_logfinish():
 | 
						|
            logging.warning('<<<<< END <<<<<<<')
 | 
						|
            logging.warning('<<<<< END <<<<<<<')
 | 
						|
    ''')
 | 
						|
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        @pytest.fixture
 | 
						|
        def fix(request):
 | 
						|
            logging.warning("log message from setup of {}".format(request.node.name))
 | 
						|
            yield
 | 
						|
            logging.warning("log message from teardown of {}".format(request.node.name))
 | 
						|
            logging.warning("log message from teardown of {}".format(request.node.name))
 | 
						|
 | 
						|
        def test_log_1(fix):
 | 
						|
            logging.warning("log message from test_log_1")
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest()
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        '{}::test_log_1 '.format(filename),
 | 
						|
        '*-- live log start --*',
 | 
						|
        '*WARNING* >>>>> START >>>>>*',
 | 
						|
        '*-- live log setup --*',
 | 
						|
        '*WARNING*log message from setup of test_log_1*',
 | 
						|
        '*-- live log call --*',
 | 
						|
        '*WARNING*log message from test_log_1*',
 | 
						|
        'PASSED *100%*',
 | 
						|
        '*-- live log teardown --*',
 | 
						|
        '*WARNING*log message from teardown of test_log_1*',
 | 
						|
        '*-- live log finish --*',
 | 
						|
        '*WARNING* <<<<< END <<<<<<<*',
 | 
						|
        '*WARNING* <<<<< END <<<<<<<*',
 | 
						|
        '=* 1 passed in *=',
 | 
						|
    ])
 | 
						|
    assert re.search(r'(.+)live log teardown(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)',
 | 
						|
                     result.stdout.str(), re.MULTILINE) is not None
 | 
						|
    assert re.search(r'(.+)live log finish(.+)\n(.+)WARNING(.+)\n(.+)WARNING(.+)',
 | 
						|
                     result.stdout.str(), re.MULTILINE) is not None
 | 
						|
 | 
						|
 | 
						|
def test_log_cli_level(testdir):
 | 
						|
    # Default log file level
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_cli(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_cli_handler.level == logging.INFO
 | 
						|
            logging.getLogger('catchlog').debug("This log message won't be shown")
 | 
						|
            logging.getLogger('catchlog').info("This log message will be shown")
 | 
						|
            print('PASSED')
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest('-s', '--log-cli-level=INFO')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_cli_level.py*This log message will be shown',
 | 
						|
        'PASSED',  # 'PASSED' on its own line because the log message prints a new line
 | 
						|
    ])
 | 
						|
    assert "This log message won't be shown" not in result.stdout.str()
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
 | 
						|
    result = testdir.runpytest('-s', '--log-level=INFO')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_cli_level.py* This log message will be shown',
 | 
						|
        'PASSED',  # 'PASSED' on its own line because the log message prints a new line
 | 
						|
    ])
 | 
						|
    assert "This log message won't be shown" not in result.stdout.str()
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
 | 
						|
 | 
						|
def test_log_cli_ini_level(testdir):
 | 
						|
    testdir.makeini(
 | 
						|
        """
 | 
						|
        [pytest]
 | 
						|
        log_cli=true
 | 
						|
        log_cli_level = INFO
 | 
						|
        """)
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_cli(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_cli_handler.level == logging.INFO
 | 
						|
            logging.getLogger('catchlog').debug("This log message won't be shown")
 | 
						|
            logging.getLogger('catchlog').info("This log message will be shown")
 | 
						|
            print('PASSED')
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest('-s')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_cli_ini_level.py* This log message will be shown',
 | 
						|
        'PASSED',  # 'PASSED' on its own line because the log message prints a new line
 | 
						|
    ])
 | 
						|
    assert "This log message won't be shown" not in result.stdout.str()
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('cli_args', ['',
 | 
						|
                                      '--log-level=WARNING',
 | 
						|
                                      '--log-file-level=WARNING',
 | 
						|
                                      '--log-cli-level=WARNING'])
 | 
						|
def test_log_cli_auto_enable(testdir, request, cli_args):
 | 
						|
    """Check that live logs are enabled if --log-level or --log-cli-level is passed on the CLI.
 | 
						|
    It should not be auto enabled if the same configs are set on the INI file.
 | 
						|
    """
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
 | 
						|
        def test_log_1():
 | 
						|
            logging.info("log message from test_log_1 not to be shown")
 | 
						|
            logging.warning("log message from test_log_1")
 | 
						|
 | 
						|
    ''')
 | 
						|
    testdir.makeini('''
 | 
						|
        [pytest]
 | 
						|
        log_level=INFO
 | 
						|
        log_cli_level=INFO
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest(cli_args)
 | 
						|
    if cli_args == '--log-cli-level=WARNING':
 | 
						|
        result.stdout.fnmatch_lines([
 | 
						|
            '*::test_log_1 ',
 | 
						|
            '*-- live log call --*',
 | 
						|
            '*WARNING*log message from test_log_1*',
 | 
						|
            'PASSED *100%*',
 | 
						|
            '=* 1 passed in *=',
 | 
						|
        ])
 | 
						|
        assert 'INFO' not in result.stdout.str()
 | 
						|
    else:
 | 
						|
        result.stdout.fnmatch_lines([
 | 
						|
            '*test_log_cli_auto_enable*100%*',
 | 
						|
            '=* 1 passed in *=',
 | 
						|
        ])
 | 
						|
        assert 'INFO' not in result.stdout.str()
 | 
						|
        assert 'WARNING' not in result.stdout.str()
 | 
						|
 | 
						|
 | 
						|
def test_log_file_cli(testdir):
 | 
						|
    # Default log file level
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_file(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_file_handler.level == logging.WARNING
 | 
						|
            logging.getLogger('catchlog').info("This log message won't be shown")
 | 
						|
            logging.getLogger('catchlog').warning("This log message will be shown")
 | 
						|
            print('PASSED')
 | 
						|
    ''')
 | 
						|
 | 
						|
    log_file = testdir.tmpdir.join('pytest.log').strpath
 | 
						|
 | 
						|
    result = testdir.runpytest('-s', '--log-file={0}'.format(log_file), '--log-file-level=WARNING')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_file_cli.py PASSED',
 | 
						|
    ])
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
    assert os.path.isfile(log_file)
 | 
						|
    with open(log_file) as rfh:
 | 
						|
        contents = rfh.read()
 | 
						|
        assert "This log message will be shown" in contents
 | 
						|
        assert "This log message won't be shown" not in contents
 | 
						|
 | 
						|
 | 
						|
def test_log_file_cli_level(testdir):
 | 
						|
    # Default log file level
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_file(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_file_handler.level == logging.INFO
 | 
						|
            logging.getLogger('catchlog').debug("This log message won't be shown")
 | 
						|
            logging.getLogger('catchlog').info("This log message will be shown")
 | 
						|
            print('PASSED')
 | 
						|
    ''')
 | 
						|
 | 
						|
    log_file = testdir.tmpdir.join('pytest.log').strpath
 | 
						|
 | 
						|
    result = testdir.runpytest('-s',
 | 
						|
                               '--log-file={0}'.format(log_file),
 | 
						|
                               '--log-file-level=INFO')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_file_cli_level.py PASSED',
 | 
						|
    ])
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
    assert os.path.isfile(log_file)
 | 
						|
    with open(log_file) as rfh:
 | 
						|
        contents = rfh.read()
 | 
						|
        assert "This log message will be shown" in contents
 | 
						|
        assert "This log message won't be shown" not in contents
 | 
						|
 | 
						|
 | 
						|
def test_log_level_not_changed_by_default(testdir):
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import logging
 | 
						|
        def test_log_file():
 | 
						|
            assert logging.getLogger().level == logging.WARNING
 | 
						|
    ''')
 | 
						|
    result = testdir.runpytest('-s')
 | 
						|
    result.stdout.fnmatch_lines('* 1 passed in *')
 | 
						|
 | 
						|
 | 
						|
def test_log_file_ini(testdir):
 | 
						|
    log_file = testdir.tmpdir.join('pytest.log').strpath
 | 
						|
 | 
						|
    testdir.makeini(
 | 
						|
        """
 | 
						|
        [pytest]
 | 
						|
        log_file={0}
 | 
						|
        log_file_level=WARNING
 | 
						|
        """.format(log_file))
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_file(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_file_handler.level == logging.WARNING
 | 
						|
            logging.getLogger('catchlog').info("This log message won't be shown")
 | 
						|
            logging.getLogger('catchlog').warning("This log message will be shown")
 | 
						|
            print('PASSED')
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest('-s')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_file_ini.py PASSED',
 | 
						|
    ])
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
    assert os.path.isfile(log_file)
 | 
						|
    with open(log_file) as rfh:
 | 
						|
        contents = rfh.read()
 | 
						|
        assert "This log message will be shown" in contents
 | 
						|
        assert "This log message won't be shown" not in contents
 | 
						|
 | 
						|
 | 
						|
def test_log_file_ini_level(testdir):
 | 
						|
    log_file = testdir.tmpdir.join('pytest.log').strpath
 | 
						|
 | 
						|
    testdir.makeini(
 | 
						|
        """
 | 
						|
        [pytest]
 | 
						|
        log_file={0}
 | 
						|
        log_file_level = INFO
 | 
						|
        """.format(log_file))
 | 
						|
    testdir.makepyfile('''
 | 
						|
        import pytest
 | 
						|
        import logging
 | 
						|
        def test_log_file(request):
 | 
						|
            plugin = request.config.pluginmanager.getplugin('logging-plugin')
 | 
						|
            assert plugin.log_file_handler.level == logging.INFO
 | 
						|
            logging.getLogger('catchlog').debug("This log message won't be shown")
 | 
						|
            logging.getLogger('catchlog').info("This log message will be shown")
 | 
						|
            print('PASSED')
 | 
						|
    ''')
 | 
						|
 | 
						|
    result = testdir.runpytest('-s')
 | 
						|
 | 
						|
    # fnmatch_lines does an assertion internally
 | 
						|
    result.stdout.fnmatch_lines([
 | 
						|
        'test_log_file_ini_level.py PASSED',
 | 
						|
    ])
 | 
						|
 | 
						|
    # make sure that that we get a '0' exit code for the testsuite
 | 
						|
    assert result.ret == 0
 | 
						|
    assert os.path.isfile(log_file)
 | 
						|
    with open(log_file) as rfh:
 | 
						|
        contents = rfh.read()
 | 
						|
        assert "This log message will be shown" in contents
 | 
						|
        assert "This log message won't be shown" not in contents
 | 
						|
 | 
						|
 | 
						|
@pytest.mark.parametrize('has_capture_manager', [True, False])
 | 
						|
def test_live_logging_suspends_capture(has_capture_manager, request):
 | 
						|
    """Test that capture manager is suspended when we emitting messages for live logging.
 | 
						|
 | 
						|
    This tests the implementation calls instead of behavior because it is difficult/impossible to do it using
 | 
						|
    ``testdir`` facilities because they do their own capturing.
 | 
						|
 | 
						|
    We parametrize the test to also make sure _LiveLoggingStreamHandler works correctly if no capture manager plugin
 | 
						|
    is installed.
 | 
						|
    """
 | 
						|
    import logging
 | 
						|
    from functools import partial
 | 
						|
    from _pytest.capture import CaptureManager
 | 
						|
    from _pytest.logging import _LiveLoggingStreamHandler
 | 
						|
 | 
						|
    class MockCaptureManager:
 | 
						|
        calls = []
 | 
						|
 | 
						|
        def suspend_global_capture(self):
 | 
						|
            self.calls.append('suspend_global_capture')
 | 
						|
 | 
						|
        def resume_global_capture(self):
 | 
						|
            self.calls.append('resume_global_capture')
 | 
						|
 | 
						|
    # sanity check
 | 
						|
    assert CaptureManager.suspend_capture_item
 | 
						|
    assert CaptureManager.resume_global_capture
 | 
						|
 | 
						|
    class DummyTerminal(six.StringIO):
 | 
						|
 | 
						|
        def section(self, *args, **kwargs):
 | 
						|
            pass
 | 
						|
 | 
						|
    out_file = DummyTerminal()
 | 
						|
    capture_manager = MockCaptureManager() if has_capture_manager else None
 | 
						|
    handler = _LiveLoggingStreamHandler(out_file, capture_manager)
 | 
						|
    handler.set_when('call')
 | 
						|
 | 
						|
    logger = logging.getLogger(__name__ + '.test_live_logging_suspends_capture')
 | 
						|
    logger.addHandler(handler)
 | 
						|
    request.addfinalizer(partial(logger.removeHandler, handler))
 | 
						|
 | 
						|
    logger.critical('some message')
 | 
						|
    if has_capture_manager:
 | 
						|
        assert MockCaptureManager.calls == ['suspend_global_capture', 'resume_global_capture']
 | 
						|
    else:
 | 
						|
        assert MockCaptureManager.calls == []
 | 
						|
    assert out_file.getvalue() == '\nsome message\n'
 |