question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

[QUESTION] How to update log file path based on test result

See original GitHub issue

I’ve been playing around with the logging and so far it’s great! But now I am wanting to do a bit more customization to suite our needs.

So basically we have a lot of API tests to get through and we’re logging both PASSED and FAILED assertions to our logs and the HTML report.

This part is fine, except for the small hiccup that any one particular log file could be thousands of lines long.

So I have created a couple of functions to help split these logs on a per-test basis.

This is to get the current test details:

def get_current_test():
    path_to_module_and_test_name = os.environ['PYTEST_CURRENT_TEST'].split(' ')[0]
    list_details = path_to_module_and_test_name.split("::")
    path_to_module = list_details[0]
    test_name_with_data = list_details[1]
    path_details_list = path_to_module.split('/')
    test_module = path_details_list[-1]

    service_name = 'general'

    for x in ast.literal_eval(os.environ['API_SERVICES']):
        if x in path_details_list:
            service_name = x
            break

    if '[' in test_name_with_data:
        test_name = test_name_with_data.split('[')[0]
        test_data = test_name_with_data.replace(test_name, '')
    else:
        test_name = test_name_with_data
        test_data = test_name_with_data

    os.environ['test_module'] = test_module
    os.environ['test_service'] = service_name
    os.environ['test_name'] = test_name
    os.environ['test_data'] = test_data

Then I have a fixture to ‘remove and create’ the logger:

@pytest.fixture(autouse=True)
def update_logger():
    # get test details
    get_current_test()

    # set default status
    test_status = 'UNKNOWN'

    # prevent double logs
    logger.remove()

    # set logging
    logger.add(Path(os.environ.get('reports_dir'),
                    test_status,
                    os.environ['test_service'],
                    f'{os.environ["test_name"]}.log'),
               format=formatter)
    logger.add(sys.stderr, format=formatter)

And so far this works good for us. We end up with a break-down like this:

Reports
└── 18.03.2022
    └── 15.38.54
        ├── Execution_Report.html
        └── general
            └── test_again.log

And so basically, the idea is that we’re able to split log files on a per test basis (or whatever we want really) to keep the logs as short and precise as possible.

BUT, this approach introduces a lot of overhead for having to look through MANY directories and log files to find the logs for failed tests.

So I searched a bit and there’s a way to grab the result of a test, like so:

@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    # execute all other hooks to obtain the report object
    outcome = yield
    rep = outcome.get_result()

    # we only look at actual [PASS/FAIL/SKIP] test calls, not setup/teardown
    if rep.when == "call":
        if rep.passed:
            test_status = 'PASS'
        elif rep.failed:
            test_status = 'FAIL'
        elif rep.skipped:
            test_status = 'SKIP'
        else:
            test_status = 'ERROR'

And from this, I’d like to update the path that the logs would be generated in.

So I’d end up with something like this:

Reports
└── 18.03.2022
    └── 15.38.54
        ├── Execution_Report.html
        ├── FAIL
        │   └── general
        │       └── test_again.log
        └── PASS
            └── general
                └── Execution_Log.log

But the problem is that the path is already set for the log file in the update_logger fixture and I’m wondering if there’s a way of changing that path location in the pytest_runtest_makereport fixture?

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:6 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
Delgancommented, Mar 22, 2022

That looks fine. 😉

Here is a slightly simplified version to explain the principle in broad terms:

from loguru import logger
import pytest
import os
import shutil


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    outcome = yield
    rep = outcome.get_result()

    if rep.when == "call":
        if rep.passed:
            test_status = 'PASS'
        elif rep.failed:
            test_status = 'FAIL'
        elif rep.skipped:
            test_status = 'SKIP'
        else:
            test_status = 'ERROR'

        os.makedirs(test_status, exist_ok=True)
        shutil.move(item.session.config._logfile_path, test_status)

@pytest.fixture(autouse=True)
def update_logger(request):
    logfile_path = "logs/" + request.node.name + ".log"
    request.config._logfile_path = logfile_path
    logger.remove()
    handler_id = logger.add(logfile_path, mode="w")
    yield
    logger.remove(handler_id)

Note I’m using pytest.Config to store the log filepath and move it ad the end of the test (once it has been removed by fixture).

0reactions
Delgancommented, Mar 30, 2022

Great, glad I could help you. 👍

I’m closing this issue then. 😉

Read more comments on GitHub >

github_iconTop Results From Across the Web

pytest implementing a logfile per test method - Stack Overflow
It is based on set_log_path , which is an experimental feature. Pytest 6.1.1 and Python 3.8.4 # conftest.py # Required modules import pytest ......
Read more >
java - Where should tests' log files go?
If I'm checking out a logs on a server at my company I always go straight to the logs folder. In my work...
Read more >
Log4j – Frequently Asked Questions - Apache Logging Services
Frequently Asked Questions · I'm seeing this error “Unable to locate a logging implementation, using SimpleLogger”. · Which JAR files do I need?...
Read more >
Snakefiles and Rules — Snakemake 7.19.1 documentation
The script path is always relative to the Snakefile containing the directive (in contrast to the input and output file paths, which are...
Read more >
Viewing Test Results | TestComplete Documentation
To open a result, double-click it in the Project Explorer or right-click it and select Open from the context menu. To view statistics...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found