The Artima Developer Community
Sponsored Link

Computing Thoughts
Testing Python CGIs
by Bruce Eckel
July 16, 2006
Summary
I've been doing a lot of web programming lately. Although I've experimented with PHP, I keep migrating back to Python.

Advertisement

I've found PHP useful for some presentation-layer things, especially basics like standard headers and footers. And there are lots of web-specific functions in PHP, and a very large number of modules and applications available.

But as soon as the logic starts to get complex, I find Python to be easier to manage, probably because I've used it for so many years.

The problem with most languages when writing CGIs is testing. You usually have to move the CGI to a server and run it there in order to see what's going on, adding extra code to feed error information back to you. If you're trying to do rapid experimentation, this slows you down significantly.

Python does have a nice module for producing nicely-formatted and colored error output on a web page, which helps considerably. You just say:


import cgitb; cgitb.enable()
Also, you can run a Python CGI on the command line to detect syntax errors. But there isn't a built-in approach to feed test variables into a CGI, as if they were coming from a web page with a form on it.

To capture form variables from a page, Python has the cgi module. You use it like this:


form = cgi.FieldStorage()
Now form contains the names and values from the submitted page. If you run a cgi containing the above line from the command line, form will still be created, but it will be empty. Assuming there would be a way to populate it by hand for testing, I looked through the code in cgy.py and discovered that I could populate it this way:

for name, value in {
    "name1" : "value1",
    "name2" : "value2",
    "name3" : "value3",
    "name4" : "value4",
    "name5" : "value5",
}.items():
    form.list.append(cgi.MiniFieldStorage(name, value))

Now form contains the same information as if it were populated by submitting a form through the web.

You'll typically only want to load test data when you're experimenting on your local machine. Also, there are other configurations which will differ between your local machine and the server. For example, cgitb.enable() is very helpful on the server, but on your local machine it pours out all the html formatting, which isn't very helpful. And producing your own error messages on the server is different than on a local machine.

One approach is to have a flag that you change depending on whether you're running on a server or a local machine, but I didn't want to require any extra actions (details count). My approach was to look at the path for a directory that exists on the local machine but not on the server. So, for example, if the cgi lived on the local machine in a path that included "website," you can do this:


runningOnServer = "website" not in os.getcwd()

The "in" operation here is from Python 2.4 and is definitely one of my favorite improvements -- it checks whether a string appears within another string and is far more readable and intuitive than


os.getcwd().find("website") != -1

From then on, you just check runningOnServer when deciding what to do, like this:


if runningOnServer:
    import cgitb; cgitb.enable()

You can also choose the way errors are reported:


def error(msg):
    print "Content-type: text/html"
    print
    print "Error:", msg
    sys.exit()

if not runningOnServer:
    def error(msg):
        print "Error:", msg
        sys.exit()

And of course if it's not running on the server, you can populate the test data.

Have any tricks that you use when testing CGIs?

Talk Back!

Have an opinion? Readers have already posted 3 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Bruce Eckel adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Bruce Eckel (www.BruceEckel.com) provides development assistance in Python with user interfaces in Flex. He is the author of Thinking in Java (Prentice-Hall, 1998, 2nd Edition, 2000, 3rd Edition, 2003, 4th Edition, 2005), the Hands-On Java Seminar CD ROM (available on the Web site), Thinking in C++ (PH 1995; 2nd edition 2000, Volume 2 with Chuck Allison, 2003), C++ Inside & Out (Osborne/McGraw-Hill 1993), among others. He's given hundreds of presentations throughout the world, published over 150 articles in numerous magazines, was a founding member of the ANSI/ISO C++ committee and speaks regularly at conferences.

This weblog entry is Copyright © 2006 Bruce Eckel. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us