##
10 デバッグ

`doctest` では、doctest 例題をデバッグするメカニズムをいくつか 提供しています:

- doctest を実行可能な Python プログラムに変換し、 Python デバッガ `pdb` で実行できるようにするための関数がいくつかあります。
- `DocTestRunner` のサブクラス`DebugRunner` クラスが あります。このクラスは、最初に失敗した例題に対して例外を送出します。 例外には例題に関する情報が入っています。この情報は例題の検視デバッグ に利用できます。
- `DocTestSuite()` の生成する`unittest` テストケース は、`debug()` メソッドをサポートしています。`debug()` は ``unittest`.TestCase` で定義されています。
- ``pdb`.set_trace()` を doctest 例題の中で呼び 出しておけば、その行が実行されたときに Python デバッガが組み込まれます。 デバッガを組み込んだあとは、変数の現在の値などを調べられます。 たとえば、以下のようなモジュールレベルの docstring の入ったファイル a.py があるとします:

      """
      >>> def f(x):
      ...     g(x*2)
      >>> def g(x):
      ...     print x+3
      ...     import pdb; pdb.set_trace()
      >>> f(3)
      9
      """

  対話セッションは以下のようになるでしょう:

      >>> import a, doctest
      >>> doctest.testmod(a)
      --Return--
      > <doctest a[1]>(3)g()->None
      -> import pdb; pdb.set_trace()
      (Pdb) list
        1     def g(x):
        2         print x+3
        3  ->     import pdb; pdb.set_trace()
      [EOF]
      (Pdb) print x
      6
      (Pdb) step
      --Return--
      > <doctest a[0]>(2)f()->None
      -> g(x*2)
      (Pdb) list
        1     def f(x):
        2  ->     g(x*2)
      [EOF]
      (Pdb) print x
      3
      (Pdb) step
      --Return--
      > <doctest a[2]>(1)?()->None
      -> f(3)
      (Pdb) cont
      (0, 3)
      >>>

  バージョン 2.4 で 変更 された仕様: ``pdb`.set_trace()` を doctest の 中で有効に使えるようになりました

以下は、doctest を Python コードに変換して、できたコードをデバッガ下で 実行できるようにするための関数です:

`script_from_examples`( | s)

  例題の入ったテキストをスクリプトに変換します。

  引数s は doctest 例題の入った文字列です。この文字列は Python スクリプトに変換され、その中では s の doctest 例題が 通常のコードに、それ以外は Python のコメント文になります。 生成したスクリプトを文字列で返します。例えば、

          import doctest
          print doctest.script_from_examples(r"""
              Set x and y to 1 and 2.
              >>> x, y = 1, 2

              Print their sum:
              >>> print x+y
              3
          """)

  は、

          # Set x and y to 1 and 2.
          x, y = 1, 2
          #
          # Print their sum:
          print x+y
          # Expected:
          ## 3

  になります。

  この関数は他の関数 (下記参照) から使われていまるが、対話セッションを Python スクリプトに変換したいような場合にも便利でしょう。

  バージョン 2.4 で 新たに追加 された仕様です。

`testsource`( | module, name)

  あるオブジェクトの doctest をスクリプトに変換します。

  引数module はモジュールオブジェクトか、対象の doctest を持つ オブジェクトの入ったモジュールのドット表記名です。 引数name は対象の doctest を持つオブジェクトの (モジュール内の) 名前です。対象オブジェクトの docstring を上の `script_from_examples()` で説明した方法で Python スクリプトに 変換してできた文字列を返しますます。例えば、a.py モジュールの トップレベルに関数 `f()` がある場合、以下のコード

      import a, doctest
      print doctest.testsource(a, "a.f")

  を実行すると、`f()` の docstring から doctest をコードに 変換し、それ以外をコメントにしたスクリプトを出力します。

  バージョン 2.3 で 新たに追加 された仕様です。

`debug`( | module, name[, pm])

  オブジェクトの持つ doctest をデバッグします。

  module および name 引数は上の `testsource()` と同じです。指定したオブジェクトの docstring から合成された Python スクリプトは一時ファイルに書き出され、その後 Python デバッガ `pdb` の制御下で実行されます。

  ローカルおよびグローバルの実行コンテキストには、 `module.__dict__` の浅いコピーが使われます。

  オプション引数pm は、検死デバッグを行うかどうかを指定します。 pm が真の場合、スクリプトファイルは直接実行され、 スクリプトが送出した例外が処理されないまま終了した場合にのみデバッガ が立ち入ります。その場合、``pdb`.post_mortem()` によって 検死デバッグを起動し、処理されなかった例外から得られたトレースバック オブジェクトを渡します。pm を指定しないか値を偽にした場合、 ``pdb`.run()` に適切な `execfile()` 呼び出しを 渡して、最初からデバッガの下でスクリプトを実行します。

  バージョン 2.3 で 新たに追加 された仕様です。

  バージョン 2.4 で 変更 された仕様: 引数pm を追加しました

`debug_src`( | src[, pm][, globs])

  文字列中の doctest をデバッグします。

  上の`debug()` に似ていますが、doctest の入った文字列は src 引数で直接指定します。

  オプション引数 pm は上の `debug()` と同じ意味です。

  オプション引数globs には、ローカルおよびグローバルな 実行コンテキストの両方に使われる辞書を指定します。globs を 指定しない場合や`None` にした場合、空の辞書を使います。 辞書を指定した場合、実際の実行コンテキストには浅いコピーが使われます。

  バージョン 2.4 で 新たに追加 された仕様です。

`DebugRunner` クラス自体や`DebugRunner` クラスが送出 する特殊な例外は、テストフレームワークの作者にとって非常に興味のある ところで The `DebugRunner` class, and the special exceptions it may raise, are of most interest to testing framework authors, and will only be sketched here.

詳しくはソースコード、とりわけ`DebugRunner` の docstring (それ自体 doctest ですよ!) を参照してください。

クラス `DebugRunner`( | [checker][, verbose][, optionflags])

  テストの失敗に遭遇するとすぐに例外を送出するようになっている `DocTestRunner` のサブクラスです。予期しない例外が生じると、 `UnexpectedException` 例外を送出します。この例外には、 テスト、例題、もともと送出された例外が入っています。 予想出力と実際出力が一致しないために失敗した場合には、 `DocTestFailure` 例外を送出します。この例外には、 テスト、例題、実際の出力が入っています。

  コンストラクタのパラメタやメソッドについては、5.2.9 節の `DocTestRunner` のドキュメントを参照してください。

`DebugRunner` インスタンスの送出する例外には以下の二つがあります:

例外 `DocTestFailure`( | test, example, got)

  doctest 例題の実際の出力が予想出力と一致しなかったことを示すために `DocTestRunner` が送出する例外です。 コンストラクタの引数は、インスタンスの同名のメンバ変数を 初期化するために使われます。

`DocTestFailure` では以下のメンバ変数を定義しています:

`test`
  例題が失敗した時に実行されていた`DocTest` オブジェクトです。

`example`
  失敗した `Example` オブジェクトです。

`got`
  例題の実際の出力です。

例外 `UnexpectedException`( | test, example, exc_info)

  doctest 例題が予期しない例外を送出したことを示すために `DocTestRunner` が送出する例外です。 コンストラクタの引数は、インスタンスの同名のメンバ変数を 初期化するために使われます。

`UnexpectedException` では以下のメンバ変数を定義しています:

`test`
  例題が失敗した時に実行されていた`DocTest` オブジェクトです。

`example`
  失敗した `Example` オブジェクトです。

`exc_info`
  予期しない例外についての情報の入ったタプルで、`sys.exc_info()` が返すのと同じものです。