Search code examples
djangotestingtdd

how to write django test meant to fail?


I have a model called Thing with an attribute called name, and I want name to be a char field that's only 3 characters long.

How do I write a test for that?

class TestCase1(TestCase):
    def test1(self):
        thing = Thing(name='1234')

that test should fail. How do I properly write the test so that the test passes when that object fails?


Solution

  • If you're expecting Thing(name='1234') to raise an exception, there are two ways to deal with this.

    One is to use Django's assertRaises (actually from unittest/unittest2):

    def mytest(self):
        self.assertRaises(FooException, Thing, name='1234')
    

    This fails unless Thing(name='1234') raises a FooException error. Another way is to catch the expected exception and raise one if it doesn't happen, like this:

    def mytest(self):
        try:
            thing = Thing(name='1234')
            self.fail("your message here")
        except FooException:
            pass
    

    Obviously, replace the FooException with the one you expect to get from creating the object with too long a string. ValidationError?

    A third option (as of Python 2.7) is to use assertRaises as a context manager, which makes for cleaner, more readable code:

    def mytest(self):
        with self.assertRaises(FooException):
            thing = Thing(name='1234')
    

    Sadly, this doesn't allow for custom test failure messages, so document your tests well. See https://hg.python.org/cpython/file/2.7/Lib/unittest/case.py#l97 for more details.