Python: assert if string matches a format

10,786

Solution 1

You are looking for assertRegex():

class SomeTestCases(TestCase):
    def test_something(self):
        response = self.client.post(...)
        self.assertRegex(response.data, r'^your regex here$')

Solution 2

Seems like regex would be the easiest solution here

import re
msg = 'Geometry type "point" is not supported'
assert re.match(r'^Geometry type ".+" is not supported$', msg)
Share:
10,786
kaveh
Author by

kaveh

Updated on June 11, 2022

Comments

  • kaveh
    kaveh about 2 years

    I have some unit tests for my Django API using Django Rest Framework APIClient. Different endpoints of the API return custom error messages, some with formatted strings like: 'Geometry type "{}" is not supported'.

    I'm asserting the status code from the client responses and error message keys, but there are cases that I'd like to figure what error message is returned to make sure nothing else has caused that error.

    So I'd like to validate the returned error message against the original unformatted string too. For example if I receive an error message like 'Geometry type "Point" is not supported', I'd like to check if it matches the original unformatted message, i.e. 'Geometry type "{}" is not supported'.

    The solutions I've thought of so far:

    • First: replacing the brackets in the original string with a regex pattern and see if it matches the response.

    • Second: (the cool idea, but might fail in some cases) using difflib.SequenceMatcher and test if the similarity ratio is bigger than, for example, 90%.

    UPDATE

    Here's an example:

    There's a dict of error messages from which each error picks the relevant message, adds the format arguments if needed, and raises its error:

    ERROR_MESSAGES = {
        'ERROR_1': 'Error message 1: {}. Do something about it',
        'ERROR_2': 'Something went wrong',
        'ERROR_3': 'Check you args: {}. Here is an example: {}'
    }
    

    Now an error happens in my DRF serializer during processing a request and it raises an error:

    try:
        some_validation()
    except SomeError as e:
        raise serializers.ValidationError({'field1': [ERROR_MESSAGES['ERROR_N1'], ERROR_MESSAGES['ERROR_N2']], 'field2': ['ERROR_N3']})
    

    Now in a specific test, I'd like to make sure a certain error message is there:

    class SomeTestCases(TestCase):
        def test_something(self):
            response = self.client.post(...)
            self.assertThisMessageIsInResponse(response.data, ERROR_MESSAGES['ERROR_K'])
    

    response.data can be just a string or a dict or list of errors; i.e. whatever that can go in ValidationError.

    Pointing to the error message location within response.data for each test case is no problem. The concern of this question is dealing with comparison between formatted and unformatted strings.

    So far the easiest approach has been regex. I'm mostly curios about if there's a built-in assertion for this and what other solutions can be used.