特定ディレクトリ以下のdoctest

30分プログラム、その210。特定ディレクトリ以下のdoctestをまとめて実行する。サブディレクトリへの対応はまだ。

最初はDocFileSuiteを使うつもりだったけど、これはどうやら違うらしい。これはモジュールのロードはせずに、テストだけをロードするっぽい。参考: http://d.hatena.ne.jp/pythonco/20061015#p2

次にevalでimportしてaddSuiteするようにしようとしたけれど、eval中ではimportは使えないっぽい。

>>> eval('import os')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1
    import os
         ^
SyntaxError: invalid syntax

最終的に__import__を使う形に落ち着きました。

サブディレクトリはos.walkを使えば対応できるかな。globが'**/*.py'のような拡張グロブに対応してればいいのに。Rubyにはあるのにな。

irb> Dir['**/*.py']
=> ["foo.py", "bar.py", "baz/xyzzy.py"]

使い方

# カレントディレクトリにあるモジュールのテストを全部実行する
$ python runner.py

ソースコード

#! /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

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 glob.glob('*.py'):
        mod = __import__(module_name(file))
        suite.addTest(doctest.DocTestSuite(mod))
    runner = unittest.TextTestRunner(verbosity=True)
    runner.run(suite)

if __name__ == '__main__':
    run()