Search code examples
pythontestingpytestassert

Override Standard Assert Messaging in Pytest Assert


I'm using Pytest to test some SQL queries my team runs programmatically over time.

My SQL queries are lists of JSONs - one JSON corresponds to one row of data.

I've got a function that diffs the JSON key:value pairs so that we can point to exactly which values are different for a given row. Ideally, I'd output a list of these diffs instead of the standard output of an assert statement, which ends up looking clunky and not-very-useful for the end user.


Solution

  • Pytest give us the hook pytest_assertrepr_compare to add a custom explanation about why an assertion failed.

    You can create a class to wrap the JSON string and implement your comparator algorithm overloading the equal operator.

    class JSONComparator:
        def __init__(self, lst):
            self.value = value
    
        def __eq__(self, other):
            # Here your algorithm to compare two JSON strings
            ...
    
            # If they are different, save that information
            # We will need it later
            self.diff = "..."
    
            return True
    
    # Put the hook in conftest.py or import it in order to make pytest aware of the hook.
    def pytest_assertrepr_compare(config, op, left, right):
    
        if isinstance(left, JSONComparator) and op == "==":
            # Return the diff inside an array.
            return [left.diff]
    
    # Create a reference as an alias if you want
    compare = JSONComparator
    

    Usage

    def test_somethig():
        original = '{"cartoon": "bugs"}'
        expected = '{"cartoon": "bugs"}'
    
        assert compare(original) == expected