chamilad
chamilad

Reputation: 1659

PyTest - Logging in production code

I have a simple module which contains utility methods such as password decryption, folder deletion that are used by other modules in the code. I'm trying to write unit tests for these methods.

This module imports another module called the LogFactory which handles the loggers and logging configuration.

simplemodule.py

from log import LogFactory

log = LogFactory.getlogger(__name__)

def decrypt(pass, key):
   #magic
   log.debug(message)

The problem arises here. The logging configuration is passed as an INI file to the logging module in the LogFactory module. The overall python code is run by a shell script which replaces certain entries in the INI file before running the python module. So in the production everything falls together smoothly.

The problem is when pytest imports the first production code it comes across an error when the values needed by the logger are not replaced by the shell script.

test_simplemodule.py

import simplemodule <----- ERROR, needed values absent from the INI

def test_decryption():
   #test code

I'm writing the tests without the logging entries for now. But I need to eventually include these log entries later.

1) What am I doing wrong in terms of design when it comes to logging in utility methods? I feel the mistake is in the production code since I'm not able to properly write a unit test for it

2) I tried Monkeypatching, but realized that the error comes when importing the production code.

3) What is the standard practice in a situation like this? Drop unit testing and go for some kind of end end automation?

Upvotes: 3

Views: 675

Answers (1)

flub
flub

Reputation: 6357

So firstly this seems to point out that you might want to refactor the logging code to not do things as a side-effect of importing. As you just found out doing anything at import time can come to hurt you.

Once that is sorted you should then be able to easily create an autouse fixture which creates a (dummy) logger instance which would be called during testing. This can be as simply as all logging is a noop, or store it to inspect in test assertions (see pytest-capturelog for fixture inspiration which does this for the stdlib logging).

If you really can't refactor your logging module to behave you could probably get round this by creating the correct INI file in the pytest_configure() hook (and revert it in pytest_unconfigure(), this hook will be called before py.test performs it's test collection so before any imports are attempted.

Upvotes: 2

Related Questions