具有从配置文件中读取 configparser 的单元测试 python 代码 [英] unit test python code that has configparser reading from config file
问题描述
我是 Python 单元测试的新手.我学习并做了示例单元测试,其中方法接受输入并返回输出.
但是对于下面提到的代码,我有一些问题.
- 我如何在单元测试中模拟 init 方法的 configparser?路径/config/program.cfg 在生产服务器上,不在 dev 目录中.program.cfg 文件存在于代码目录的其他位置.有没有办法在单元测试中处理它?
- 我如何在单元测试中发送或跳过诸如硬编码路径之类的内容,例如/var/log/info_server.log
如果可能,请告诉我您将如何使用 pytest 模块为以下代码编写单元测试?这将有助于理解流程,我可以用其余的代码来做到这一点.
def __init__(self):self.setup_logger()# 读取配置参数config = configparser.ConfigParser()config.read("/config/program.cfg")self.host_ip = config.get('default','HostIP')self.redis_ip = config.get('default','RedisIP')self.redis_port = config.get('default','RedisPort')self.info_port = config.get('default','InfoPort')self.sqlite_db_file = config.get('default','SQLiteDbFile')self.connect_redis()def setup_logger(self):#初始化记录器self.logger = logging.getLogger(__name__)self.logger.setLevel(logging.INFO)# 创建文件处理程序handler = logging.FileHandler('/var/log/info_server.log')handler.setLevel(logging.INFO)# 创建日志格式formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')handler.setFormatter(格式化程序)# 将处理程序添加到记录器self.logger.addHandler(处理程序)def connect_redis(self):# 启动一个Redis实例self.logger.info("启动Redis实例")self.ad_info = redis.StrictRedis(host=self.redis_ip, port=self.redis_port, db=0)如果 self.ad_info 是 None:self.logger.error("无法启动Redis实例")别的:self.logger.info("启动Redis实例")
当然,我们可以模拟很多东西,但是一个简单的重构被测试的类,添加配置和日志,会让生活变得更容易.
def __init__(self, cfg='/config/program.cfg', log='/var/log/info_server.log'):
在不存在 /config/program.cfg
的开发服务器中,您可以
TheClass(cfg='~/dev.cfg', log='/tmp/dev.log')
<块引用>
self.server_obj.connect_redis() log_mock.logger.info.assert_Called_with('Started Redis instance')
不工作
导入日志logging.getLogger# <函数 getLogger 在 0x7f3d2ed427b8>记录器 = logging.getLogger()类型(记录器)# <class 'logging.RootLogger'>记录器信息# <绑定方法Logger.info of <RootLogger root (WARNING)>>
补丁应该是这样的:
使用 mock.patch.object(logging.RootLogger, 'info') 作为 mock_info:server_obj = Server(cfg='sth', log='sth')mock_info.assert_Called_with('xxx')
I'm new to python unit test. I learned and did sample unit test where method accepts input and returns output.
But for code as mentioned below, I've some questions.
- How I mock configparser of init method in unittest? Path /config/program.cfg is on production server and not exists in dev directory. program.cfg file exists at other location in code directory. Is there a way to handle that in unittest?
- How I send or skip something like hardcoded path in unittest e.g. /var/log/info_server.log
If possible, can you please tell me how would you write unittest for below code using pytest module? This will be helpful to understand the flow and I can do that with rest of code.
def __init__(self): self.setup_logger() # Read config parameters config = configparser.ConfigParser() config.read("/config/program.cfg") self.host_ip = config.get('default','HostIP') self.redis_ip = config.get('default','RedisIP') self.redis_port = config.get('default','RedisPort') self.info_port = config.get('default','InfoPort') self.sqlite_db_file = config.get('default','SQLiteDbFile') self.connect_redis() def setup_logger(self): #Initialize logger self.logger = logging.getLogger(__name__) self.logger.setLevel(logging.INFO) # Create a file handler handler = logging.FileHandler('/var/log/info_server.log') handler.setLevel(logging.INFO) # Create a logging format formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) # Add the handlers to the logger self.logger.addHandler(handler) def connect_redis(self): # Start up a Redis instance self.logger.info("Start Redis instance") self.ad_info = redis.StrictRedis(host=self.redis_ip, port=self.redis_port, db=0) if self.ad_info is None: self.logger.error("Failed to start Redis instance") else: self.logger.info("Started Redis instance")
Sure, we could mock many things, but a simple re-factoring the class being tested, adding config and log, will make life much easier.
def __init__(self, cfg='/config/program.cfg', log='/var/log/info_server.log'):
In development server where /config/program.cfg
is not present, you could just
TheClass(cfg='~/dev.cfg', log='/tmp/dev.log')
self.server_obj.connect_redis() log_mock.logger.info.assert_called_with('Started Redis instance')
not working
import logging
logging.getLogger
# <function getLogger at 0x7f3d2ed427b8>
logger = logging.getLogger()
type(logger)
# <class 'logging.RootLogger'>
logger.info
# <bound method Logger.info of <RootLogger root (WARNING)>>
The patch should be sth like this:
with mock.patch.object(logging.RootLogger, 'info') as mock_info:
server_obj = Server(cfg='sth', log='sth')
mock_info.assert_called_with('xxx')
这篇关于具有从配置文件中读取 configparser 的单元测试 python 代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!