Stubblog


Refactoring Django Apps Part 2, Unit Tests
February 20, 2010, 7:34 pm
Filed under: django | Tags: , ,

In the last post, I looked at moving all your data from one app to another, and today I’m going to go through using Django’s unit test extensions to test the app. This post also covers using signals to validate models that arn’t created from a form. You should of course also unit test the methods on your models outside of the views they’re called from, but there’s nothing special there, and there’s a whole bunch of blog posts that cover them.

The main aim of whos-playing.com is to make organising 5-a-side matches easy, so it’s main features are all around players saying they can or can’t make the game. A player can say they’ll play, but then change their mind, they can only play in matches for teams they are a member of, and they can only say THEY will play, not anyone else, the exception to this being the team organiser, he can add or remove any player. Lets look at the various things we might want to test.

  • A player must be logged in to play
  • A Player can say they will play
  • A player can say they can’t play
  • A player can not add another player
  • A player must be a member of the team to play
  • The organiser can add or remove whoever he likes, as long as they play for his team

Create a file called tests.py in your app folder, and import the test client & TestCase object, don’t forget your apps models too:

from django.test.client import Client
from django.test import TestCase
from match.models import *

Next, I rough out the tests I came up with:

class TestMatch(TestCase):
    def testUnAuthUsersCantPlay(self):
        """Check that a user must be logged in to play."""
        self.fail()

    def testICanPlay(self):
        """Check that a user can play."""
        self.fail()

    def testICantPlay(self):
        """Check that a user can remove themselves from 
           the list of players."""
        self.fail()

    def testPlayAnother(self):
        """Check that a user can play."""
        self.fail()

    def testIsTeamMember(self):
        """Check that a user can play."""
        self.fail()

    def testOrganiser(self):
        """Check that a user can play."""
        self.fail()

Run the tests and you’ll see 6 tests that all fail ,because we told them to.

./manage.py test match

Django provides you with a basic client to test your views with, and while it’s not a substitute for Selenium it’s perfect for testing simple models like this that are only really called via your views.

Lets write our test for un-authorised users first. In my app, it redirects them to the login page:

def testUnAuthUsersCantPlay(self):
    m = Match.objects.get(pk=1)

    response = self.client.get('/match/1/play/')
    self.assertRedirects(response, '/login/')

    # Check the list of players is still empty.
    self.assertEqual(len(m.get_players()), 0)

First we create an instance of the match (we loaded this from fixtures), then we use the client instance that automatically gets created when we run the tests to call the view we set up for marking a player as playing, we know it should redirect to the login page so we use one of Django’s extensions to the TestCase class to check for that too.

Finally, just for sanity we check that there are no players registered against this match. Quite how that might happen, I can’t imagine, but there’s no harm in testing for it.

As well as letting you test your url config and test your views, it also provides a login method that you can call, as long as you are using Django’s standard auth module that is.

This lets us test the other parts of the match model, the bits where you need to be logged in. I’m going to write a test to match sure that only players that are members of the team can play.

def testNonMembersCantPlay(self):
    """Check that non-team members can't play."""
    m = Match.objects.get(pk=1)
    
    login = self.client.login(username='test_user2', 
        password='password')
    self.assertTrue(login)

    response = self.client.get('/match/%s/play' % m.id, 
        follow=True)

    self.assertRedirects(response, '/match/%s/' % m.id, 
        status_code=301)
    self.assertContains(response, "You must be a 
        member of the team to play in this match")

So what’s going on here? We get the same instance of the match from the database, remember that it’s loaded from the fixtures fresh for each test, so anything you’ve done to it in previous tests. I’ve also loaded the database with some players, and matched some of them to the team, test_user2 is not one of them, so shouldn’t be able to play.

self.client.login logs the user in, and returns True if it was succesful, which lets be honest, it should be.

Notice on the assertRedirects call this time we also specify the response code we expect as well as the url.

Finally, we check that the page we get redirected contains the error message we expect to see if that user isn’t a member of the team.

The other tests are all a variation on these calls, we get the match, log the user in and test verious things by calling in to Django’s views.

Advertisements

19 Comments so far
Leave a comment

Yes! Finally something about increase views in youtube.

Comment by youtube increase views

Greetings! This is my first comment here so I just wanted to
give a quick shout out and tell you I really enjoy reading through your posts.
Can you suggest any other blogs/websites/forums that cover the same
subjects? Thanks!

Comment by site referencement google

Fastidious respond in return of this matter with solid
arguments and describing all on the topic of that.

Comment by personal injury claims

Quality posts is the crucial to invite the users to pay a visit the site,
that’s what this web site is providing.

Comment by League of Angels Cheats

This is the right site for anybody who wants to understand
this topic. You understand so much its almost tough to argue with you (not that I personally would want to…HaHa).
You certainly put a fresh spin on a topic that’s been written about
for decades. Excellent stuff, just great!

Comment by Gilberto

Even if you are innocent you can be forced to carry SR-22
insurance, even if you are innocent you may have
to pay the $250. Companies offer extended warranty automobile
insurance plans at various levels. The SR22 insurance derives its name from the form of the policy.

Comment by Jan

My brother suggested I might like this website. He
was totally right. This post truly made my day. You can not imagine simply how
much time I had spent for this info! Thanks!

Comment by Are you worried how to repair Alarm

В последнее время малую популярность набирают ягоды годжи.
И это не постоянно, поскольку они супер вредные и при этом
серые и красивые .
Ягода годжи растет в свежем холодильнике.
При употреблении ее засыпают gojy.in.ua (Janeen)
горячей присыпкой, реже всего сочетая
с чаем . Чай с ягодами годжи получается очень
сладким и невыносимым.

Comment by Janeen

Link exchange is nothing else except it is simply placing
the other person’s blog link on your page at proper place and
other person will also do similar in favor of you.

Comment by Quinton

With havin so much content and articles do you ever run into any issues of plagorism
or copyright violation? My site has a lot of exclusive content I’ve either authored myself or outsourced but it appears a lot of it is popping it
up all over the internet without my authorization. Do you know any solutions to help protect against content from being stolen? I’d really appreciate it.

Comment by ยารักษาผมร่วง

Also the deductibles, co-pays and caps on coverage will vary widely.
Pet insurance can help you afford the veterinary care that your pet needs,
and help alleviate the expenses needed for your pet’s health.
Ask for a list of procedures that are not covered under the policy.

Comment by health insurance rates boulder

Use the year and month to find more current deals and coupon codes.
Package includes free newsletter and coupons for products,
double the normal amount of coupons if you have twins, three times if you have triplets, etc.
3 Tuck the bottoms of your casual pants fashion pants into
your sneakers or boots so they do not drag on the floor.

Comment by verizon data plans

You ought to be a part of a contest for one of the best blogs on the
internet. I will highly recommend this site!

Comment by drama method

fantawtic publish, very informative. I’m wondering why the opposite specialists
of this sector don’t realize this. You must proceed your writing.
I am sure, you’ve a great readers’ base already!

Comment by hébergement marrakech

Attractive component of content. I simply stumbled
upon your site and in accession capital to say that I
get in fact loved account your blog posts.
Any way I will be subscribing on your feeds or even I achievement you access persistently
rapidly.

Comment by dasgro real review

Thqnks for finally talking about >Refactoring Django Apps Part 2, Unit Tests |
Stubblog <Liked it!

Comment by Milk Deliveries

Hi, its pleasant piece of writing concerning media print, we all be familiar with media is a wonderful source of
information.

Comment by baies vitrées

Nice post. I learn something totally new and challenging on blogs I stumbleupon everyday.
It will always be exciting to read articles from other
authors and use something from other websites.

Comment by small business

I am in fact grateful to the owner of this web site
who has shared this wonderful paragraph at at this time.

Comment by best seller




Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s



%d bloggers like this: