[英]Unittest for Python logger function
我正在尝试为类似这样的 create_logger(用户定义函数)编写单元测试。
create_logger(path,file_name):
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
fmt="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
fileHandler = logging.FileHandler(
(f"{path}/{file_name}.log"), "w"
)
streamHandler = logging.StreamHandler()
fileHandler.setFormatter(formatter)
streamHandler.setFormatter(formatter)
logger.addHandler(fileHandler)
logger.addHandler(streamHandler)
return logger
我已经为上述方法编写了单元测试,如下所示:
from logger import create_Logger
os.makedirs("unit_test", exist_ok=True)
class TestCreateLogger(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.logger = create_logger("unit_test", "logs")
@classmethod
def tearDownClass(cls):
if os.path.isdir("unit_test"):
shutil.rmtree("unit_test")
else:
raise Exception("The directory does not exist")
del cls.logger
def test_log_level(self):
self.logger.info("First message")
self.logger.debug("Second message")
with open("unit_test/logs.log", "r") as fd:
log_msg = fd.read()
self.assertIn("First message", log_msg)
self.assertNotIn("Second message", log_msg)
def test_log_level_change(self):
self.logger.setLevel("DEBUG")
self.logger.info("First message")
self.logger.debug("Second message")
with open("unit_test/logs.log", "r") as fd:
log_msg = fd.read()
self.assertIn("First message", log_msg)
self.assertIn("Second message", log_msg)
上面的单元测试工作正常,但我不想使用像(mkdir、rmdir 等)这样的文件操作,而是使用模拟、补丁。 由于我的方法采用两个参数(路径和文件名)并将日志消息存储到日志文件并打印到标准输出。 有人可以帮我理解如何用模拟/补丁替换开放操作吗? 目前我正在使用 mkdir 和该目录中的日志文件创建一个目录,并在测试结束时使用 tearDown 删除它们。 如何使用模拟/补丁复制相同的内容?
我建议您在这里测试的不仅仅是您自己的代码; 您正在测试FileHandler
的工作是否符合记录。 您要测试的是create_logger
创建了一个记录器,该记录器记录您打算记录的位置; FileHandler
只是“where”的一种可能定义。
create_logger
中唯一关心path
和file_name
的是FileHandler
。 根本不要创建FileHandler
; 而是将处理程序作为参数传递,并测试您新创建的记录器是否使用它。
def create_logger(handler):
logger = logging.getLogger()
logger.setLevel(logging.INFO)
formatter = logging.Formatter(
fmt="%(asctime)s %(levelname)s %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
streamHandler = logging.StreamHandler()
handler.setFormatter(formatter)
streamHandler.setFormatter(formatter)
logger.addHandler(handler)
logger.addHandler(streamHandler)
return logger
然后您的测试可以使用写入io.StringIO
对象而不是磁盘的StreamHandler
。
from logger import create_Logger
os.makedirs("unit_test", exist_ok=True)
class TestCreateLogger(unittest.TestCase):
def setUp(self):
self.f = io.StringIO()
self.logger = create_logger(StreamHandler(f))
def test_log_level(self):
self.logger.info("First message")
self.logger.debug("Second message")
log_msg = self.f.read()
self.assertIn("First message", log_msg)
self.assertNotIn("Second message", log_msg)
def test_log_level_change(self):
self.logger.setLevel("DEBUG")
self.logger.info("First message")
self.logger.debug("Second message")
log_msg = self.f.read()
self.assertIn("First message", log_msg)
self.assertIn("Second message", log_msg)
在生产中,您将传递一个预制的FileHandler
而不是文件路径组件。
...
foo = create_logger(FileHandler(f"{path}/{file_name}.log", "w"))
如果您担心foo
是否会写入正确的文件,那是整数测试,而不是单元测试,应该写入文件系统。 这样一个要测试的函数可以是create_logger
的包装器,并且是您在生产中直接使用的函数。
def create_file_logger(path, file_name):
return create_logger(FileHandler(f"{path}/{file_name}", "w"))
(不过,该测试会简单得多,因为如果它的单元测试通过,您已经可以假设create_logger
正在工作!)
请记住,记录器可以在运行时配置,因此将您将部署的记录器配置视为需要测试的代码。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.