1

I'm working on a project that creates a different log file each time it runs. I have some unit tests that test my code but in the process also cause the log files to get created. My application code looks like this:

module.py

import logging
from uuid import uuid4

class TestRun:

    def __init__(self):
        self.test_run_id = str(uuid4())
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)
        handler = logging.FileHandler('{}.log'.format(self.test_run_id))
        self.logger.addHandler(handler)

    def prep_test_run(self):
        self.logger.info('Starting prep')

if __name__ == '__main__':
    tr = TestRun()
    tr.prep_test_run()

My test code is something like this:

import unittest
from module import TestRun

class TestModule(unittest.TestCase):
    def test_function(self):
        tr = TestRun()
        tr.prep_test_run()

Every time I run the unit tests files get created. Is there a way to disable this while running the unit tests. I've tried to set the log level in def setUp(self) but it didn't work.

2
  • I'm not sure what exactly the test is testing, but you can either: cleanup the files after they are written or pass a flag into one or both method of your class like test=1 and in those cases, you create if statements to skip the steps in the code which make the log files you don't want. Commented Sep 1, 2017 at 21:41
  • Note that like setUp, Unit Tests support a tearDown() method to handle things exactly like this. Commented Sep 1, 2017 at 21:42

3 Answers 3

2

Here's a context manager that will disable a specific logger for a portion of code:

from contextlib import contextmanager

@contextmanager
def disable_logger(name):
    """Temporarily disable a specific logger."""
    logger = logging.getLogger(name)
    old_value = logger.disabled
    logger.disabled = True
    try:
        yield
    finally:
        logger.disabled = old_value

You can then use it like so:

class MyTest(unittest.TestCase):

   def test_do_something(self):
      with disable_logger('mypackage.mymodule'):
          mymodule.do_something()
Sign up to request clarification or add additional context in comments.

Comments

0

I see two paths for handling this: either remove the handler, or never create it in the first place.

For the first, remove the handlers from the logger in test_function:

def test_function(self):
    tr = TestRun()
    tr.logger.handlers = []

This is very brute force (it removes all of the log handlers, so use it carefully), but it should solve the problem.

The second way would be to control whether you produce the logs in the first place by adding a keyword argument to TestRun.__init__, something like:

class TestRun:
    def __init__(self, file_logs = True):
        self.test_run_id = str(uuid4())
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.INFO)
        if file_logs:
            handler = logging.FileHandler('{}.log'.format(self.test_run_id))
            self.logger.addHandler(handler)

Then, when you make a instance in your tests, do tr = TestRun(file_logs = False).

On the other hand, as pointed out in comments, it might be best to simply create the logs as normal, then delete them once the test is done.

1 Comment

I chose this as the best answer because if I need to I can still get the logger object without it being written to a file.
0

This should do the trick:

logging.getLogger(__name__).disabled = True

Add this line right after your imports.

1 Comment

Won't that get the wrong logger instance? __name__ will be different in the test code than where TestRun is defined.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.