doctestの実行方法について

前回のエントリでdoctestの実行方法についてコメントで教えていただいたので新たに書き直しました。

まず昨日のエントリで私が書いていたコードは

def main(initial=u"あ", inputsource=multi_input_reader()):
    u"""
    正常パターン
    >>> main(inputsource=[[u"アフロ", u"ローマ字", u"ジントニック"], [u"クラス", u"スルメ"]])
    最初のもじは「あ」です
    アフロ
    ローマ字
    ジントニック
    --次は4語目です。--
    クラス
    スルメ
    --次は6語目です。--
    終了です
    """
    usedwords = {}

    print (u"最初のもじは「" + initial + u"」です")

    for wordsU in inputsource:
        try:
            for (furigana, word) in ParallelAsk.get_result(wordsU):
                if word in usedwords:  # 使用済みでないか確認
                    raise shiritori.UniquenessError(word, usedwords[word])

                furigana.exam(initial, word)  # 冒頭、末尾文字確認
                initial = furigana.creatIL()
                print word
                usedwords[word] = len(usedwords) + 1

            print u"--次は" + str(len(usedwords) + 1) + u"語目です。--"

        except shiritori.CrtShiritoriError, e:
            print e
            break
        except shiritori.ShiritoriRuleError, e:
            print e
            print u"--次は" + str(len(usedwords) + 1) + u"語目です。--"
            continue

    print u"終了です"

if __name__ == "__main__":
    import doctest
    doctest.testmod()

というdoctestを書いているのと同一ファイル内で実行まで行う書き方でしたが、これだとテストを行うために実行部分を書き換えないといけませんでした。

#テスト時はこのように書いて・・・
if __name__ == "__main__":
    import doctest
    doctest.testmod()

#実行時にはこう書かないといけない
if __name__ == "__main__":
    main()

他のファイルからimportして使うことが前提のモジュールならそれで良いのですが、今回のようにそれ自体を実行するファイルである場合はこれは不便です。

そこで教えていただいた方法はdoctestの単体テストAPIというもので簡単にいうとdoctestをunittestの1つとして実行できるようにするものです。
これを利用して外部のテスト用ファイルから各クラスのテストと共にmainのdoctestを実行するように書いたのが以下です。

# coding: utf-8

import unittest
import doctest
import multithread_shiritori
import shiritori


class TestSequence(unittest.TestCase):

    def testHFD(self):
        """辞書テスト"""
        testdict = multithread_shiritori.PrlSupportHFD()
        # 正しいxmlが戻る場合
        self.assertEqual(testdict[u"Linux"], u"りなっくす")
        # はてなキーワードに登録がない場合
        self.assertIsNone(testdict[u"あああ"])
        # xmlにエラーが発生する場合
        self.assertIs(testdict[u"伯爵"], False)

    def testPA(self):
        """子スレッド生成テスト"""
        words = [u"あああ", u"Linux", u"伯爵"]

        for (furigana, word) in multithread_shiritori.ParallelAsk.get_result(words, 10):
            self.assertEqual(furigana, shiritori.Furigana(word))


def load_tests(loader, tests, ignore):
    tests.addTests(doctest.DocTestSuite(multithread_shiritori))
    return tests

if __name__ == "__main__":
    unittest.main()

これでmultithread_shiritoriモジュール内のすべてのdoctestが実行されます。