特定ディレクトリ以下のdoctest -サブディレクトリ対応版-

30分プログラム、その211。前回の特定ディレクトリ以下のdoctest(id:mzp:20071230)をサブディレクトリに対応させてみた。
os.walkディレクトリを辿りつつ、fnmatch.filterで欲しいやつだけ取り出す戦略で。
始めはos.listdirとos.path.isdirを組合せて自分で再帰しようかと思ったけど、カレントディレクトリのパスを自分で管理するのが面倒だったので、os.walkを使うことにした。os.walkならタプルのひとつめに常にカレントディレクトリが入ってるので。

使い方

$ python runner.py
....
----------------------------------------------------------------------
Ran 4 tests in 0.015s

OK

ソースコード

#! /usr/bin/python
# -*- mode:python; coding:utf-8 -*-
#
# runner.py -
#
# Copyright(C) 2007 by mzp
# Author: MIZUNO Hiroki / mzpppp at gmail dot com
# http://howdyworld.org
#
# Timestamp: 2007/12/30 21:16:21
#
# This program is free software; you can redistribute it and/or
# modify it under MIT Lincence.
#
import glob
import doctest
import unittest
import re

import os
import sys
import fnmatch

def find(pat="*",base="."):
    l = []
    for (base,_,files) in os.walk(base):
        # filter filenames which matched with pat
        matched  = fnmatch.filter(files,pat)

        # expand filename to path
        expanded = map(lambda x:base+'/'+x,matched)
        
        # add path to l
        l.extend(expanded)
    return l

def module_name(filename):
    """
    >>> module_name('hoge.py')
    'hoge'

    >>> module_name('foo/bar.py')
    'foo.bar'
    """
    return re.sub(re.compile(r"^\./|\.py$"),
                  '',
                  filename).replace('/','.')


def run():
    suite = unittest.TestSuite()
    for file in find('*.py'):
        mod = __import__(module_name(file))
        try:
            suite.addTest(doctest.DocTestSuite(mod))
        except ValueError,e:
            print e
    runner = unittest.TextTestRunner(verbosity=True)
    runner.run(suite)

if __name__ == '__main__':
    run()