Old question, haven't seen my usual answer. I dislike what is offered here because:
assertRaises(SomeError, msg='some error happened')
doesn't let you check the precise exception message or code as stated in other answers
assertRaisesMessage
and assertRaisesRegexp
rely on the human-worded message wich is weak to wording changes. Not great for unit testing.
But Django is as usual setting contradicting standards (yikes) and so here is their ValidationError best practice doc https://docs.djangoproject.com/en/5.0/ref/forms/validation/#raising-validationerror . In it they recommand passing a more stable code="some_error" parameter.
If you can and the exception provides something like an error code (there doesn't seem to be a Python standard for it?), I would suggest this:
with self.assertRaises(SomeError) as error:
trigger_error()
self.assertEqual(error.code, 'deliberate_error')
I'm kinda surprised to not see this answer here already. Am I missing something?