从配置文件读取configparser的单元测试python代码
我是python单元测试新手。我学习并做了示例单元测试,其中方法接受输入并返回输出 但是对于下面提到的代码,我有一些问题从配置文件读取configparser的单元测试python代码,python,unit-testing,pytest,Python,Unit Testing,Pytest,我是python单元测试新手。我学习并做了示例单元测试,其中方法接受输入并返回输出 但是对于下面提到的代码,我有一些问题 如何在unittest中模拟init方法的configparser?路径/config/program.cfg位于生产服务器上,不在dev目录中。program.cfg文件存在于代码目录中的其他位置。有没有办法在unittest中处理这个问题 如何发送或跳过unittest中的硬编码路径,例如/var/log/info_server.log 如果可能的话,您能告诉我如何使用p
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")
当然,我们可以模拟很多事情,但是对被测试的类进行简单的重新分解,添加config和log,将使工作变得更加轻松
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\u obj.connect\u redis()log\u mock.logger.info.assert\u调用了('Started redis instance')
未工作
不要一次问多个问题;有人知道三个问题的答案的可能性比知道一个问题的答案的可能性小。如果打开
/config/program.cfg
,您可以模拟内置的open
函数,该函数将返回带有配置文件内容的StringIO
,或者在打开/var/log/info\u server.log
进行写入时写入StringIO
。谢谢。这真的让生活轻松多了。但我现在面临的问题是在start\u Redis方法中调用self.logger.info(“Started Redis实例”)的次数。我尝试将补丁('scripts.server.server.logging')作为log\u mock:self.server\u obj.connect\u redis()log\u mock.logger.info.assert\u调用了('Started redis instance'),但它在connect\u redis中查看logging.info而不计算self.logging.info如何实现?假设您正在测试的脚本或模块是server.py
,如果您导入日志记录
,使用补丁('scripts.sever.logging.getLogger.info')作为模拟信息
,那么您可以使用('xxx')调用self.server.obj.logger.info.assert\u来快速回复。对脚本名为server.py,它有导入日志记录,我尝试了上面的建议,但得到以下错误。AttributeError:没有“info”属性,因此我添加了“getLogger.level..”并尝试使用修补程序('scripts.server.logging.getLogger.level.info')作为模拟_info:self.server_obj.logger.info.assert_调用了_('Started Redis instance'),但获取模块发现错误:没有名为'scripts.server.logging';'“scripts.server”不是一个包,我缺少什么吗?我只是想告诉您,我使用的是Python3.6。5@Amit,如果您的IDE中有一个自动完成功能,那么就更容易弄清楚要模拟什么。在这种情况下,我更新了答案,是伪代码让您知道如何模拟
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)>>
with mock.patch.object(logging.RootLogger, 'info') as mock_info:
server_obj = Server(cfg='sth', log='sth')
mock_info.assert_called_with('xxx')