views:

1593

answers:

3

I've not used Unit Tests before other than a quick introduction in a Uni course. I'm currently writing an application though and would like to teach myself TDD in the process. The problem is, I've no idea what to test or really how.

I'm writing a Django application, and so far have only created the models (and customised the admin application). This is how I've written the skeletons of my tests so far:

class ModelTests(TestCase):
fixtures = ['initial_data.json',]

def setUp(self):
    pass

def testSSA(self):
    ssa = SSA.objects.create(name="sdfsdf", cost_center=1111, street_num=8,
            street_name="dfsdfsf Street", suburb="sdfsdfsdf",
            post_code=3333)


def testResident(self):
    pass

def testSSA_Client(self):
    pass

I planned to write a function to test each model within the ModelTests class. Is this a good way of writing tests? Also, what exactly should I be testing for? That creating a model with all of the fields completed works? That a half complete model fails? That any special cases are tested (like a null and is_required=False)? I've trust in the ORM, which as far as I'm aware is heavily tested, so I shouldn't need to test all of the methods should I?

What do I need to test for a web application written in Django/Python? Some examples would be nice.

+5  A: 

I'm not exactly sure of the specifics of what you're trying to test here, I'd need more code snippets for this, but I can give you some general advice.

First, read the unit testing chapter of "Dive into Python" (it's free online! http://diveintopython.org/), it's a great explanation of unit testing in general, what you need to do, and why.

Second, with regards to TDD, it is a valuable practice, but be careful about growing too dependent on it as I've found it can lead to over-specifying software and further on to having software that can not be re-developed and adapted to new tasks. This is just my experience, mind. Also, providing you don't use it dogmatically TDD is valuable.

Third, it strikes me that the best piece of advice for your specific situation is to strive to test your logic, but not the logic of frameworks that you depend on. That means that often testing half-complete models fail etc. etc. may not be appropriate, since that is not your logic, but django's, and so should already be tested. More valuable would be to test a few expected cases, instantiations that you expect, exceptions that you expect etc. to make sure your model specification is sound, and then move on to the more substantial logic of your application.

Daniel Nadasi
+1 for the summary of how actually to get started with unit testing in Python and for sharing your own experience with TDD.
Peter Mortensen
+2  A: 

Presumably you've already read Testing Django Applications.

Start testing the normal use cases of your application, creating a new user, adding a blog entry, etc. Just your typical CRUD operations first, then move out to the edge cases. Basically your building confidence in your application that anything you later change will not break how I expect the application to behave.

Simulate GET/POST requests on your URLs and observe the responses (headers, status codes and content). Did your application render the correct view? Using the correct template? In the sections where your application throws exceptions, attempt to trigger them (e.g. view/edit a non-existent record to raise ObjectDoesNotExist).

It's usually worth putting in a tracking system (e.g. Trac), so you can add a new test for every logged defect.

Jeff Bauer
+15  A: 

Is a function to test each model within the ModelTests class a good way of writing tests?

No.

What exactly should I be testing for?

  • That creating a model with all of the fields completed works?

  • That a half complete model fails?

  • That any special cases are tested (like a null and is_required=False)?

  • I've trust in the ORM, which as far as I'm aware is heavily tested, so I shouldn't need to test all of the methods should I?

Not much of that.

You might test validation rules, but that isn't meaningful until you've defined some Form objects. Then you have something to test -- does the form enforce all the rules. You'll need at least one TestCase class for each form. A function will be a scenario -- different combinations of inputs that are allowed or not allowed.

For each Model class, you'll need at least one TestCase class definition. TestCases are cheap, define lots of them.

Your model embodies your "business entity" definitions. Your models will have methods that implement business rules. Your methods will do things like summarize, filter, calculate, aggregate, reduce, all kinds of things. You'll have functions for each of these features of a model class.

You're not testing Django. You're testing how your business rules actually work in Django.

Later, when you have more stuff in your application (forms, views, urls, etc.) you'll want to use the Django unittest client to exercise each method for each url. Again, one TestCase per

S.Lott
+1 Excellent summary.
muhuk
Once I wrote the skeletons out, and defined two tests for one model, I'd realised I was wasting my time. There was nothing to test I wasn't sure about. I've not defined custom methods yet though. Very good answer I appreciate it.
Josh Smeaton
@Josh Smeaton: NOT wasting time. Those simplistic skeleton tests are helpful in the long run. In the future, you'll do some refactoring that seems trivial and one of those lame tests will break, indicating that you missed something. "Sure" isn't always good enough. You need "proof".
S.Lott