Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: assert if string matches a format

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.

like image 820
kaveh Avatar asked Aug 30 '17 19:08

kaveh


People also ask

How do you know if a string matches a pattern?

To check if a String matches a Pattern one should perform the following steps: Compile a String regular expression to a Pattern, using compile(String regex) API method of Pattern. Use matcher(CharSequence input) API method of Pattern to create a Matcher that will match the given String input against this pattern.

How do I check if a string is in one format?

You can then use p. matcher(str). matches() . See the Pattern class for more details.

Is regex a match in Python?

match() function of re in Python will search the regular expression pattern and return the first occurrence. The Python RegEx Match method checks for a match only at the beginning of the string. So, if a match is found in the first line, it returns the match object.


1 Answers

You are looking for assertRegex():

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

See also assertNotRegex.

like image 168
mrts Avatar answered Sep 29 '22 02:09

mrts