user3750195
user3750195

Reputation: 71

py.test logging for tests that pass

I have been over and over the documentation, but I can not fine out how I get py.test to write to the log for tests that pass. For example if I run "py.test --resultlog=mylog.txt myPytest.py" mylog.txt only has one line for each test that passed. I want to add other things to each test recorded in my log file, regardless whether thy passed or failed. For example I need to know the time they ran, some of the output data etc. How do I get py.test to include data about the test (passed and failed) in the py.test log file?

Upvotes: 7

Views: 7998

Answers (5)

Wolf7176
Wolf7176

Reputation: 317

It seems by default the cli log level is INFO We can run this. to see the logs.

pytest </path/test_blah.py> -rP --log-cli-level=INFO

And possibly this to save it to the file.

pytest </path/test_blah.py> -rP --resultlog=mylog.txt --log-cli-level=INFO

import pytest
import logging

@pytest.fixture
def configure_logging():
    logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
    yield  # Code to be executed after logging configuration
    # Cleanup if needed (e.g., reset logging)
    logging.shutdown()

# !pytest % -rP --log-cli-level=INFO
def test_logging_logs_show_in_pytest_console_error(configure_logging, caplog):
    logging.error("ERROR: Hello Py test")
    # assert "Hello Py test" in caplog.text  # Verify the message is capturedimport logging

def test_logging_logs_show_in_pytest_console_info(configure_logging, caplog):
    logging.info("INFO: Hello Py test")
    # assert "Hello Py test" in caplog.text  # Verify the message is capturedimport logging

Upvotes: 0

Dylan Hogg
Dylan Hogg

Reputation: 3398

See All Test Output: pytest -rP

The correct way to display the log output of passing tests is outlined in this answer:

pytest -rP

See All Test Output Always: Live Logs

There is also a way to configure Live Logs which I haven't used, but it appears a way to always see the log output of all running tests. The default value for Live Logs is False.

To enable them, edit your configuration file such as pyproject.toml:

[pytest]
log_cli = True

See All Output of Failing Tests: pytest -s

pytest also supports the -s argument to prevent capturing logging calls for failing tests, however.

pytest -s

From the documentation:

-s, –capture=no Normally stdout and stderr are captured and only shown for failing tests. The -s option can be used to disable capturing, showing stdcalls for print statements, logging calls, etc.

Braindead: Make Your Tests Fail

You can make your test fail with an intentional bug to see the output with -s, but this often doesn't show any output. Often works in a pinch when you can't remember pytest -rP :)

Sometimes though, logs triggered by -s this way just won't display, such as in the following instance (for humor):

logger.debug(f"len(new_df) == {len(new_df)}")
logger.error(f"len(new_df) == {len(new_df)}")
logging.debug(f"len(new_df) == {len(new_df)}")
logging.error(f"len(new_df) == {len(new_df)}")
print(f"len(new_df) == {len(new_df)}")
print(f"len(new_df) == {len(new_df)}", sys.stderr)
sys.stderr.write(f"len(new_df) == {len(new_df)}")
sys.stderr.flush()

assert False

No test output went to console :D

Upvotes: 11

sagar
sagar

Reputation: 377

This hook is an experimental and it is called whenever the assertion passes. From documentation-

Use this hook to do some processing after a passing assertion. The original assertion information is available in the orig string and the pytest introspected assertion information is available in the expl string.

This hook must be explicitly enabled by the enable_assertion_pass_hook ini-file option:

[pytest]
enable_assertion_pass_hook=true

You need to clean the .pyc files in your project directory and interpreter libraries when enabling this option, as assertions will require to be re-written.

import logging
log = logging.getLogger(__name__)
def pytest_assertion_pass(item, lineno, orig, expl):
   """
      Prints the log(log file) every time the assert passes
   """
   log.info(str(item) + ' | lineno: ' + str(lineno) + ' | ' + orig + ' | PASS')

Upvotes: 0

shipperizer
shipperizer

Reputation: 1669

you could use py-cov combine with pytest

py.test --cov $(MOD_NAME) --cov-config .coveragerc --cov-report xml --junit-xml=results.xml

and here you will get all the info you need as we are used to push the coverage.xml file to sonarqube and get all the data available.

If you do really need customized data/logs coming from your tests functions just pass -s so pytest will stop catching the output and it will print it on the console (and you can stream it to a file maybe, not that nice)

Upvotes: 0

flub
flub

Reputation: 6357

You can have a look if the junitxml output provides any more information. But I suspect that if you want the actual time rather then duration etc you will have to write your own plugin. The documentation gives you the relevant hooks: http://pytest.org/latest/plugins.html?highlight=hooks#reporting-hooks

Upvotes: 1

Related Questions