GithubHelp home page GithubHelp logo

etianen / logot Goto Github PK

View Code? Open in Web Editor NEW
91.0 3.0 1.0 620 KB

Test whether your code is logging correctly ๐Ÿชต

Home Page: https://logot.readthedocs.io

License: MIT License

Python 100.00%
testing logging python pytest-plugin

logot's People

Contributors

dependabot[bot] avatar etianen avatar will-ockmore avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

will-ockmore

logot's Issues

Allow matching on `exc_info`

This would allow asserting that an exception had been logged. Supporting bool | BaseException for the match would be ideal.

  • False - No exception
  • True - Any exceptiom
  • BaseException - Equality
  • None - Anything

A logged.exception() helper would complete the feature.

`logot` only works with the default `loguru` logger?

Thanks for your work.

Is it possible to configure loguru or does logot only work with a pre-configured default logger?

# test_logger.py
import sys
from typing import Callable

import pytest
from logot import Logot, logged
from logot.loguru import LoguruCapturer
from loguru import logger
from rich.logging import RichHandler


@pytest.fixture(scope="session")
def logot_capturer() -> Callable[[], LoguruCapturer]:
    return LoguruCapturer


def test_capture(logot: Logot):
    """
    Works
    """
    # Log an error message with the default logger
    logger.info("foo bar")
    logot.assert_logged(logged.info("foo bar"))


def test_capture_setup_logger(logot: Logot):
    """
    Does not work
    """
    # Remove all handlers added so far, including the default one.
    logger.remove()
    # Console handler
    logger.add(sink=sys.stderr, level="DEBUG", format="{message}")

    # Log an error message
    logger.info("foo bar")
    logot.assert_logged(logged.info("foo bar"))


def test_capture_setup_logger_rich(logot: Logot):
    """
    Does not work
    """
    # Remove all handlers added so far, including the default one.
    logger.remove()
    # Console handler with rich formatting
    logger.add(
        sink=RichHandler(
            log_time_format="[%X]",
            rich_tracebacks=True,
            tracebacks_show_locals=True,
        ),
        level="DEBUG",
        format="{message}",
    )

    # Log an error message
    logger.info("foo bar")
    logot.assert_logged(logged.info("foo bar"))

Errors:

$ test_capture_setup_logger 
AssertionError: Not logged:
[INFO] foo bar

Captured stderr call:
foo bar

$ test_capture_setup_logger_rich
AssertionError: Not logged:
[INFO] foo bar

Captured stderr call:
[01:02:03] INFO     foo bar                                    test_logger.py:42

Loguru docs:

You should remove() it first if you plan to add() another handler logging messages to the console, otherwise you may end up with duplicated logs.

Support doctest

I try to use doctest only in my code (with occasional unittest.DoctestRunner) and it's always a hassle to capture log output, because doctest clones the logger instances transparently (or something).

Support `loguru`-style message matching

Originally intended as be part of #28, this has been moved to a separate issue following discussion with loguru devs in Delgan/loguru#1072. ๐Ÿ‘

Proposed API

Support .format()-style placeholders like this:

from logot.contrib.loguru import logged

logot.wait_for(logged.info("Hello {}"))

Support matching structured data like this (requires #25):

logot.wait_for(
    logged.bind(foo="bar").info("Hello {}")
)

Implementation

Parsing of the format-style placeholders should be nice and easy using string.Formatter.parse(). Probably easier than the normal %-style placeholder parsing!

Only import `asyncio` if actually used

It's a big heavy framework we don't always need to import. Since we're only importing 3rd-party libs when actually used, it would be ideal to treat heavyweight stdlib modules the same.

Since asyncio is the default async waiter, probably a lazy import is best to keep the default async waiter zero-config.

Overload the `*` operator for `Logged`

This can be used to create repetitions of log patterns.

  • Use this in the why test logging example like this:

    from logot import Logot, logged
    
    def test_poll_daemon(logot: Logot) -> None:
        app.start_poll()
        logot.wait_for(
            (logged.info("Poll started")) >> logged.info("Poll finished")) * 3
        )
  • Link to the log pattern matching docs from this example.

  • Implement with _from_compose to correctly flatten _OrderedAllLogged.

Support `loguru` log capture

Supporting a basic loguru integration would be very easy by providing a context manager via a helper func using their LogHandler integration.

Alternatively, a Logot subclass called Logurot would be cheese and fun. That would allow the pytest plugin to provide a logurot fixture too (if loguru is installed).

Support ELLIPSIS marker

With using doctest you can use ... to mean regex-like .* catchall.
When converting to logot I stumbled upon AssertionError: Not logged: until realizing I had ... inside the expected output.

Only import `logging` if actually used

Although less heavyweight than asyncio (see #81), logging is still quite chunky and part of proving our support for any logging framework (see #28) is not giving special preference to logging.

Support `trio`

We can support trio by allowing the async waiter implementation to be customized in the Logot constructor.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.