Path: csiph.com!fu-berlin.de!uni-berlin.de!not-for-mail From: Facundo Batista Newsgroups: comp.lang.python.announce Subject: Released logassert 5 Date: Thu, 6 Aug 2020 14:16:02 -0300 Lines: 94 Approved: python-announce-list@python.org Message-ID: <159673423206.2895.python-announce-list@python.org> Reply-To: python-list@python.org Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" X-Trace: news.uni-berlin.de /vb1GQ8za3TMPeDNpsnJrgakmh+NKm5ZfImfS1fi/35Q== Authentication-Results: mail.python.org; dkim=pass reason="2048-bit key; unprotected key" header.d=gmail.com header.i=@gmail.com header.b=RGntqljO; dkim-adsp=pass; dkim-atps=neutral X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'url-ip:140.82.118.3/32': 0.03; 'url-ip:140.82.118/24': 0.03; 'url-ip:140.82/16': 0.03; '(for': 0.04; 'indicate': 0.05; 'string': 0.05; 'twitter:': 0.05; 'def': 0.07; 'mechanism': 0.07; 'pytest': 0.07; "python's": 0.07; 'regex': 0.07; 'ticket': 0.07; 'install': 0.09; 'brings': 0.09; 'debug': 0.09; 'example:': 0.09; 'logged': 0.09; 'much,': 0.09; 'received:mail-io1-xd2e.google.com': 0.09; 'renewed': 0.09; 'url- ip:151.101.0.223/32': 0.09; 'url-ip:151.101.128.223/32': 0.09; 'url-ip:151.101.192.223/32': 0.09; 'url-ip:151.101.64.223/32': 0.09; 'wrap': 0.09; 'url-ip:140/8': 0.12; 'problem': 0.12; 'help,': 0.14; 'log': 0.14; 'import': 0.15; 'python': 0.15; '"bad': 0.16; '(it': 0.16; 'all:': 0.16; 'blog:': 0.16; 'declare': 0.16; 'desire': 0.16; 'facundo': 0.16; 'from:addr:facundobatista': 0.16; 'from:name:facundo batista': 0.16; 'github:': 0.16; 'level,': 0.16; 'logs': 0.16; 'pyar:': 0.16; 'semantics': 0.16; 'structures,': 0.16; 'subject:Released': 0.16; 'url- ip:104.18.38.86/32': 0.16; 'url-ip:104.18.38/24': 0.16; 'url- ip:104.18.39.86/32': 0.16; 'url-ip:104.18.39/24': 0.16; 'url- ip:172.67.204.199/32': 0.16; 'url-ip:190.2.29.172/32': 0.16; 'url- ip:190.2.29/24': 0.16; 'url-ip:190.2/16': 0.16; 'url-ip:190/8': 0.16; 'url:plog': 0.16; 'url:project': 0.16; 'url:pypi': 0.16; 'url:taniquetil': 0.16; 'url:github': 0.16; 'skip:@ 10': 0.18; 'that.': 0.18; 'calls': 0.20; "doesn't": 0.23; 'final': 0.25; "i'm": 0.29; 'release': 0.31; 'inside': 0.31; 'message- id:@mail.gmail.com': 0.32; 'include': 0.32; 'received:google.com': 0.33; 'example,': 0.34; 'from:addr:gmail.com': 0.35; 'test': 0.35; 'way': 0.35; '"the': 0.35; 'level.': 0.35; 'usual': 0.35; "it's": 0.36; 'means': 0.37; 'just': 0.37; 'two': 0.38; 'specific': 0.38; 'thanks': 0.39; 'sure': 0.39; 'so,': 0.40; 'text': 0.40; 'want': 0.40; 'advance': 0.61; 'our': 0.62; 'url-ip:172.67/16': 0.62; 'above,': 0.63; 'your': 0.64; 'time.': 0.65; 'matter': 0.66; 'that,': 0.67; 'exactly': 0.69; 'changing': 0.69; 'logging': 0.69; 'interested': 0.70; 'url-ip:104.18/16': 0.72; 'life': 0.74; 'backwards': 0.84; 'lines,': 0.84; 'searched': 0.84; 'to:addr :python-announce': 0.98 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=9ZnZhA9PhEK6csx2Brn2kgz0Sl+tdwKdCmO5Bwam9Ks=; b=RGntqljOi9CLwuuU9yXYouQ6xWvK1CmkkcvxjLxHEhlAQ96b7aAU6bwnqEswBnr8UY Y94kyPUqt4QvEjV/qqHaKkW6vtcVKH99Yt8X6bStltAIFuuO5zH2FkpmFZcNJTLINEDO xzjlH5rjxSWc5/G7bac3DtzUrYCK08rnCg7h41LtK3BqkHcpKL039yd35VGmYQ4jE08R tMbFuNfyfd0/a1ukFeQ8IJO6rqX9UnclVKX4flpfgvRAZcKDvzG+nimNyDj//thOFU9B hJOy8nxJr63cwJ2PValvwFxiwYQpodymywXudHaDLVLe50pSkuN96QT9fEpK8BggPWe9 0zfw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=9ZnZhA9PhEK6csx2Brn2kgz0Sl+tdwKdCmO5Bwam9Ks=; b=k8VuiCRK1AVqblZ9vJe+AV0OeLEa2F06I8CZwc3+DIZuDVvM8VFnrIYdMeb6sbxMP1 4xUN2gLWgP83NVetiwp4Cx8Pfi8v2oSxw+HOBfpeJCIulKlkuqx7QOeT25b0NqHQ02OP 6M4R/U7q+FxzTEBI3IO8T8apfj71tVtmJ6qLeu3Raw78WcmPuNNtWRtiOnScmmfsy8Zy fJzNZxj+OYercC8RH8atwrQH858GMuQiUdXrik/LJdWUzgFhnsPGqF+2x/Iu+ssTR8bY sGCrdCIn3vWQtqAFAO48xOcSHs3SJNloGxdPNFGyHNFI84RKbpDjzPFF3kMTEPrvcI5l 2lAA== X-Gm-Message-State: AOAM531W79E4eHwSIPpDzbHaRimGH5dn5Ccvs6dFTWXAvUxOAlRUMGZ4 pZjT2DTOPxClNJWVMXT+VPzgdQQyGp9Q35FRcSfAqLnyyfA= X-Google-Smtp-Source: ABdhPJxDBiGkJOAZA4bj/+xNKTw2ieQaMZ/UgD5tJiKmH5FI5ZnCimPlzWPlIKIenu/uI1KmCpQzMDZ4rKBU88/nK4U= X-Received: by 2002:a6b:5d05:: with SMTP id r5mr11087172iob.14.1596734173636; Thu, 06 Aug 2020 10:16:13 -0700 (PDT) X-MailFrom: facundobatista@gmail.com X-Mailman-Rule-Hits: emergency X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved Message-ID-Hash: SOMPNXDE4C433CQOLZQK3LRLNZJ72MVV X-Message-ID-Hash: SOMPNXDE4C433CQOLZQK3LRLNZJ72MVV X-Mailman-Approved-At: Thu, 06 Aug 2020 13:16:55 -0400 X-Mailman-Version: 3.3.2b1 Precedence: list List-Id: Announcement-only list for the Python programming language Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Xref: csiph.com comp.lang.python.announce:3450 I'm happy to bring you a new release of logassert, a simple logging assertion mechanism for Python unittests. Because we all know that we must test the logging calls in our programs, right? With `logassert` this is very easy. This new release brings the functionality of logassert as a pytest fixture, with totally renewed semantics (for "classic unittest" structures, logassert is not changing much, to be backwards compatibile). So, for pytest all you need to do is to declare `logs` in your test arguments (it works just like any other fixture), and then just check (using `assert`, as usual with *pytest*) if a specific line is in the logs for a specific level. See this example, with several log lines, and a specific assertion: logger.info("Starting system") places = ['/tmp/', '~/temp'] logger.debug("Checking for config XYZ in all these places %s", places) logger.warning("bad config XYZ") assert "bad config XYZ" in logs.debug See how the test failure message is super helpful: assert for regex 'bad config XYZ' check in DEBUG, failed; logged lines: INFO 'Starting system' DEBUG "Checking for config XYZ in all these places ['/tmp/', '~/temp']" WARNING 'bad config XYZ' You can install logassert from PyPI: https://pypi.org/project/logassert/ The project is in Github: https://github.com/facundobatista/logassert Interested on more detail about how this work? As I said above, you include the `logs` fixture and just assert. Example: def test_bleh(logs) (...) assert "The meaning of life is 42" in logs.debug Actually, the line you write is a regular expression, so you can totally do (in case you're not exactly sure which the meaning of life is): assert "The meaning of life is \d+" in logs.debug The indicated string is searched to be inside the log lines, it doesn't need to be exact whole line. If you want that, just indicate it as with any regular expression: assert "^The meaning of life is \d+$" in logs.debug In a similar way you can also express the desire to check if it's at the beginning or at the end of the log lines. **NOTE**: the message checked is the final one, after the logging system replaced all the indicated parameters in the indicated string. If you want to verify that a text was logged, no matter at which level, just do: assert "The meaning of life is 42" in logs.any_level To verify that some text was NOT logged, just juse the Python's syntax! For example: assert "A problem happened" not in logs.error If you don't like regexes just import `Exact` from `logassert` and wrap the string with that. For example, in this case the `..` means exactly two dots, no regex semantics at all: assert Exact("The meaning of life is ..") in logs.any_level If you need help, or have any question, or found any issue, please open a ticket [here](https://github.com/facundobatista/logassert/issues/new). Thanks in advance for your time. -- . Facundo Blog: http://www.taniquetil.com.ar/plog/ PyAr: http://www.python.org.ar/ Twitter: @facundobatista