python - 在测试执行期间防止记录文件 IO

标签 python logging mocking pytest monkeypatching

我想测试一个在初始化时记录日志并将日志保存到本地文件的类。因此,我正在模拟日志记录逻辑,以避免在测试时出现文件 IO。这是代表我如何构建测试的伪代码

class TestClass:
    def test_1(self, monkeypatch):
        monkeypatch.setattr('dotted.path.to.logger', lambda *args: '')
        assert True

    def test_2(self, monkeypatch):
        monkeypatch.setattr('dotted.path.to.logger', lambda *args: '')
        assert True

    def test_3(self, monkeypatch):
        monkeypatch.setattr('dotted.path.to.logger', lambda *args: '')
        assert True

请注意 monkeypatch.setattr() 是如何复制粘贴到所有方法中的。考虑到:

  • 我们事先知道所有调用方法都需要以相同的方式进行猴子修补,并且
  • 人们可能会忘记对新方法进行 monkeypatch,

我认为 monkey-patching 应该在类级别进行抽象。我们如何在类级别抽象 monkeypatching?我希望解决方案类似于以下内容:

import pytest
class TestClass:
    pytest.monkeypatch.setattr('dotted.path.to.logger', lambda *args: '')

    def test_1(self):
        assert True

    def test_2(self):
        assert True

    def test_3(self):
        assert True

这是配置记录器的地方。

def initialise_logger(session_dir: str):
    """If missing, initialise folder "log" to store .log files. Verbosity:
    CRITICAL, ERROR, WARNING, INFO, DEBUG, NOTSET."""
    os.makedirs(session_dir, exist_ok=True)
    logging.basicConfig(filename=os.path.join(session_dir, 'session.log'),
                        filemode='a',
                        level=logging.INFO,
                        datefmt='%Y-%m-%d %H:%M:%S',
                        format='|'.join(['(%(threadName)s)',
                                         '%(asctime)s.%(msecs)03d',
                                         '%(levelname)s',
                                         '%(filename)s:%(lineno)d',
                                         '%(message)s']))

    # Adopt NYSE time zone (aka EST aka UTC -0500 aka US/Eastern). Source:
    # https://stackoverflow.com/questions/32402502/how-to-change-the-time-zone-in-python-logging
    logging.Formatter.converter = lambda *args: get_now().timetuple()

    # Set verbosity in console. Verbosity above logging level is ignored.
    console = logging.StreamHandler()
    console.setLevel(logging.ERROR)
    console.setFormatter(logging.Formatter('|'.join(['(%(threadName)s)',
                                                     '%(asctime)s',
                                                     '%(levelname)s',
                                                     '%(filename)s:%(lineno)d',
                                                     '%(message)s'])))
    logger = logging.getLogger()
    logger.addHandler(console)


class TwsApp:
    def __init__(self):
        initialise_logger(<directory>)

最佳答案

更简洁的实现:

# conftest.py
import pytest

@pytest.fixture(autouse=True)
def dont_configure_logging(monkeypatch):
    monkeypatch.setattr('twsapp.client.initialise_logger', lambda x: None)

您不需要用 fixture 标记单个测试,也不需要注入(inject)它,无论如何都会应用。

注入(inject)caplog fixture 如果你需要断言记录的记录。请注意,您无需配置记录器即可进行日志记录断言 - caplog fixture 将注入(inject)它正确工作所需的必要处理程序。如果您想自定义用于测试的日志记录格式,请在 pytest.ini 中执行此操作或在 [tool:pytest] 下节setup.cfg .

关于python - 在测试执行期间防止记录文件 IO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48641406/

相关文章:

c# - 支持模拟以委托(delegate)为参数的方法的模拟框架

python - 如何准确识别 O(nlogn)?

python - 制作带条件的高效Python生成器

logging - 我在哪里可以找到持续测试的项目存储库?

python - 使用 TimedRotatingHandler 时如何将 python flask werkzeug 日志重定向到日志文件?

asp.net-mvc - 如何模拟asp.net mvc中的缓存对象?

mocking - 有没有办法在 Spock 中进行模拟参数捕获

python - 如何解决导入错误: cannot import name 'Box' from 'bokeh.models' ?

python - df.iloc[1].ColumnName 是否返回整行,而不是一个特定值?

c++ - Electron :ui和后端进程在Windows上访问相同的日志文件