I have a Django model with a "title" CharField(unique=True)
. I have a unit test that asserts that creating a second instance with the same title throws an IntegrityError
. (I'm using pytest and pytest-django.)
I have something like:
class Foo(models.Model):
title = models.CharField(unique=True)
def test_title_is_unique(db):
Foo.objects.create(title='foo')
with pytest.raises(IntegrityError):
Foo.objects.create(title='foo')
This works fine, except the above code doesn't include cleanup code. pytest-django doesn't clean up the database for you, so you need to register cleanup handlers when you create or save a model instance. Something like this:
def test_title_is_unique(request, db):
foo = Foo.objects.create(title='foo')
request.addfinalizer(foo.delete)
with pytest.raises(IntegrityError):
Foo.objects.create(title='foo')
Okay, that's fine. But what if the second .create()
call erroneously succeeds? I still want to clean up that instance, but only if it (erroneously) gets created.
Here is what I settled on:
def test_title_is_unique(request, db):
foo = Foo.objects.create(title='foo')
request.addfinalizer(foo.delete)
try:
with pytest.raises(IntegrityError):
new_foo = Foo.objects.create(title='foo')
finally:
if 'new_foo' in locals():
request.addfinalizer(new_foo.delete)
This doesn't feel particularly elegant or Pythonic, not to mention there are a bunch of lines of code that really shouldn't be running.
How do I guarantee that the second model instance is cleaned up if created, but with fewer hoops to jump through, and/or using fewer lines of code?