Skip to main content

Testing With Python: The Django Way Part 1


One thing I really slacked on while developing AWiKi (it's on internal network hence can't show you) was testing. Maybe that's not the right way to put it. It's not like I didn't test. In fact, I did a lot of testing. A lot of painstaking manual testing. For every change. So, in a way it was really the opposite of slacking. It was working a whole lot harder than I really needed to. It was also dumb. 
Being conversant in conventional Automation methods I quickly tried my hands on automating a few scenarios using QTP and Selenium. But this soon led me to a more severe problem: I was surrounded with uncountable number of scenarios I needed to automate and soon it was eating more time than I was devoting in the development.
Soon I realized What I did slack on, was figuring out how Django's unit testing framework worked. Well, no more! In fact, it's really easy to set up. Writing tests can also be somewhat painstaking when it comes to ensuring you've covered every possible input, but at least that pain is an investment that repays itself every time you make a change to the program and you can know right away if you've broken something that used to work. 
As usual the Django documentation is excellent. Highly recommend for learning everything about testing with Django. What I hope to do here is give a brief overview of what you need to do some basic testing. Partly as a reminder for myself on future projects, and hopefully to help out anyone in the same position I was before I started.

Getting Started 

If your Django app is relatively new, the startapp command already created a tests.py file when you ran it to set up your app. This file includes some helpful examples, like so:

"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".

Replace these with more appropriate tests for your application.
"""

from django.test import TestCase

class SimpleTest(TestCase):
    def test_basic_addition(self):
        """
        Tests that 1 + 1 always equals 2.
        """
        self.failUnlessEqual(1 + 1, 2)

__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.

>>> 1 + 1 == 2
True
"""} 

If you don't already have a tests.py file, the important things to note are that you have to import the TestCase class from django.test and create a new class which subclasses it. Each method defined in this class will correspond to one test, usually the test of a corresponding function in your views.py file. To test a particular function from views.py, define a method with the name test_functionname.

Test data 

Now, I'm guessing your application probably manipulates some sort of data. As a matter of fact mine does a lot. The Django test runner is kind enough to setup and destroy a complete test database for the purposes of running your tests. There's two important consequences to this. First, the database user specified in your settings.py file has to have the necessary permissions to create and destroy databases. So, make sure that's the case. Second, if you already have a test database set up on your development machine (or wherever), with data you've inserted during your manual tests, the test runner won't have access to any of it.
To get some data for your tests, you can try exporting the data already in your test database with Django's dumpdata command. The test runner can then load it as a fixture. Honestly, I just couldn't get this to work. Some googling about the errors I was getting seemed to indicate that I wasn't the only one having problems with it. The update to natural keys announced for Django 1.2 seemed like it would help, but I've still been unsuccessful, so far. In any event, I plan on keeping an eye on future developments to see if there's any improvements in this area.
In the meantime, I went ahead and did it the hard way. I created a separate file called testsetup.py. I imported all the models for my project and defined a function also called testsetup. All this function does is create a few instances for each model with all their various possible configurations. By defining a method called setUp in the new class I created in tests.py and calling this function there, all of the necessary data will be added to the test database before the tests are run.


class ViewTest(TestCase):

    def setUp(self):
        testsetup()


And now we will delve into the requests. But that's for another day (Part 2)

Comments

Popular posts from this blog

FirefoxOS, A keyboard and prediction: Story of my first contribution

Returning to my cubical holding a hot cup of coffee and with a head loaded with frustration and panic over a system codebase that I managed to break with no sufficient time to fix it before the next morning.  This was at IBM, New York where I was interning and working on the TJ Watson project. I returned back to my desk, turned on my dual monitors, started reading some blogs and engaging on Mozilla IRC (a new found and pretty short lived hobby). Just a few days before that, FirefoxOS was launched in India in the form of an Intex phone with a $35 price tag. It was making waves all around, because of its hefty price and poor performance . The OS struggle was showing up in the super low cost hardware. I was personally furious about some of the shortcomings, primarily the keyboard which at that time didn’t support prediction in any language other than English and also did not learn new words. Coincidentally, I came upon Dietrich Ayala in the FirefoxOS IRC channel, who...

April Fool and Google Part 2: A Round Up of ALL of Google’s April Fools Jokes

Ok....this post I think will contain all of the pranks I could find  for today. After my last post here http://rkrants.blogspot.com/2012/04/april-fool-and-google-my-favorite.html Last Time I reported Only a handful of the pranks.. Understandable, as it was only the morning. After that I stumbled upon more of them Which I am gonna round up here. Now staring with the list. The very first one is obviously our favourite Google Maps Quest The above is their official video. In a post in Google Plus they say about it as follows  Today  + Google Maps  announced Google Maps 8-bit for NES. With #8bitmaps , you can do everything you'd normally do in Maps—search for famous landmarks and sites around the world, get directions and even use Street View. Just in time for April Fool's Day, Google has introduced Google Maps Quest, a retro 8-bit version of its mapping tool that is... totally awesome. In a characteristically whimsical video, availabl...

Curious case of Cisco AnyConnect and WSL2

One thing Covid has taught me is the importance of VPN. Also one other thing COVID has taught me while I work from home  is that your Windows Machine can be brilliant  as long as you have WSL2 configured in it. So imagine my dismay when I realized I cannot access my University resources while being inside the University provided VPN client. Both of the institutions I have affiliation with, requires me to use VPN software which messes up WSL2 configuration (which of course I realized at 1:30 AM). Don't get me wrong, I have faced this multiple times last two years (when I was stuck in India), and mostly I have been lazy and bypassed the actual problem by side-stepping with my not-so-noble  alternatives, which mostly include one of the following: Connect to a physical machine exposed to the internet and do an ssh tunnel from there (not so reliable since this is my actual box sitting at lab desk, also not secure enough) Create a poor man's socks proxy in that same box to have...