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%.
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.
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.
You can then use p. matcher(str). matches() . See the Pattern class for more details.
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With