Assert that str matches regex in pytest

Once in a while every Pythonista faces a need to test that some string value matches a regex pattern. When it comes to it we have no option but to use re module directly.

import re

def test_something_very_useful():
    value = get_some_string()
    assert re.match("\d+", value)

While it works perfectly fine in case of a lone string, it's not always convenient to do the same when a string is a part of more complex data structure (e.g. dict) because you need to extract the string, check it and only then get back to check rest attributes.

import re

def test_something_even_more_useful():
    mapping = get_some_structure()

    # inconvenient and boring! :(
    assert "value" in mapping
    value = mapping.pop("value")
    assert re.match("\d+", value)

    # rest assertion
    assert mapping = {
        "foo": 1,
        "bar": 2,
    }

Fortunately, it's pretty easy to write a convenient helper that would check a string against some pattern when comparing complex data structures.

def test_something_even_more_useful():
    mapping = get_some_structure()
    assert mapping = {
        "foo": 1,
        "bar": 2,
        "value": pytest_regex("\d+"),
    }

Looks better, huh? :) The trick can be achieved by implementing a class wrapper that implements both __eq__ and __repr__ dunder methods. The first method is used to implement matching while the other – to return the value that will be shown in error message in case of errors.

import re

class pytest_regex:
    """Assert that a given string meets some expectations."""

    def __init__(self, pattern, flags=0):
        self._regex = re.compile(pattern, flags)

    def __eq__(self, actual):
        return bool(self._regex.match(actual))

    def __repr__(self):
        return self._regex.pattern

Well, actually, it's not by any means tied to pytest and could be used even in non-test production code, though I found this rather queer.