Wednesday, September 30, 2009

Django unit testing with docstrings

Here's how I was able to get docstring tests to work in Django. Directory structure:
project/
  |  
  +-- app/
  |    |
  |    +-- __init__.py
  |    |
  |    +-- tests.py
  |    |
  |    +-- mymodule.py
  |    |
  |    etc.
  |
  +-- urls.py
  |
  +-- __init__.py
  |
  etc.

The docstring tests are in mymodule.py. The file tests.py (note: plural) contains:
import doctest
import mymodule

doctest.testmod(mymodule)
Then, if you are in the directory project, you can run the unit tests with
python ./manage.py test app

Original Approach

My first cut was to put this in tests.py:
import unittest
import doctest
import mymodule

suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite(mymodule))
runner = unittest.TextTestRunner()
runner.run(suite)
While that ran, it also raised the following exceptions, which I didn't bother to figure out.
Traceback (most recent call last):

  File "./manage.py", line 11, in 
    execute_manager(settings)

  File "/usr/lib/python2.5/site-packages/
      django/core/management/__init__.py",
      line 348, in execute_manager utility.execute()

  File "/usr/lib/python2.5/site-packages/
      django/core/management/__init__.py",
      line 293, in execute
      self.fetch_command(subcommand).run_from_argv(self.argv)

  File "/usr/lib/python2.5/site-packages/
      django/core/management/base.py", 
      line 192, in run_from_argv
      self.execute(*args, **options.__dict__)

  File "/usr/lib/python2.5/site-packages/
      django/core/management/base.py", 
      line 219, in execute
      output = self.handle(*args, **options)

  File "/usr/lib/python2.5/site-packages/
      django/core/management/commands/test.py", 
      line 23, in handle failures = 
      test_runner(test_labels, verbosity=verbosity, 
      interactive=interactive)

  File "/usr/lib/python2.5/site-packages/
      django/test/simple.py", 
      line 179, in run_tests
      suite.addTest(build_suite(app))

  File "/usr/lib/python2.5/site-packages/
      django/test/simple.py",
      line 63, in build_suite
      suite.addTest(test_module.suite())

  File "/usr/lib/python2.5/unittest.py",
      line 437, in __call__
      return self.run(*args, **kwds)

References

  1. Introduction to Python/Django testing: Basic Doctests Gave me some hints.
  2. Breaking out the Django Tests Suggested where to poke around in the Django code.

Tuesday, September 15, 2009

Strange bedfellows: ctags and actionscript

I've been hacking a lot in ActionScript and Flex recently. I'm a vi user and went looking for how I could use ctags with ActionScript source.

Lo and behold, Google says there are about 858,800 results for a "actionscript ctags" search. (Bing says 45,800, which seems more reasonable but still really high.)

I associate ctags and vi with old school *nix hackers, and ActionScript with graphic designers that morph into Flash code monkeys. My picture of actionscript hackers ain't right, which gives me a good feeling about using ActionScript.

Anyway, it's pretty easy. Mixing some Makefile goo with some regular expressions, I get:


CTAGSLANGS=--langdef=as \
--langmap=as:.as \
--regex-as='/^(a-z0-9_]+)\([^\)]*\)[ \t]*/\1/f,function/i' \
--regex-as='/class[ \t]+([^ \t]+)[ \t]*$$/\1/c,class/i'

ctags::
        find . -name "*.as" | ctags -e - $(CTAGLANGS)
Notes:
  • the regular expressions are Posix extended (roughly egrep);
  • the "kind" (e.g., f,function) options can be seen by running
    ctags --list-kinds | less
    at the command line;
  • the i flag says case-insensitive;
  • the $$ (to match the end of a line) is required because we are inside a Makefile
  • these regex are specific to how I format my code.
More on that last point: I like using the vi's bracket-bracket key sequence to move from function to function within a source file, and to make this work, my ActionScript functions look like this:
public function
getfoo()
: void
{
}
The function regex may catch more than I want, but the alternative is to write some C code and recompile ctags (so I can use the previous line as context), so I'll run with this for a while.

References

  1. How to Add Support for a New Language to Exuberant Ctags
  2. ctags(1)
  3. Makefile goo, more complex regex's