## 6 例外はどう扱えばよいのですか?

例で生成される出力がトレースバックのみである限り問題ありません: 単にトレースバックを貼り付けてください。44トレースバックには、 頻繁に変更されがちな情報が入っている (例えばファイルパスや行番号など) ものなので、受け入れるべきテスト結果に柔軟性を持たせようと doctest が 苦労している部分の一つです。

簡単な例を示しましょう:

    >>> [1, 2, 3].remove(42)
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: list.remove(x): x not in list
    >>>

この doctest は `ValueError` が送出され、かつ詳細情報に "`list.remove(x): x not in list`" が入っている場合にのみ成功します。

例外が発生したときの予想出力はトレースバックヘッダから始まっていなければ なりません。トレースバックの形式は以下の二通りの行のいずれかでよく、 例題の最初の行と同じインデントでなければりません:

    Traceback (most recent call last):
    Traceback (innermost last):

トレースバックヘッダの後ろにトレースバックスタックを続けてもかまいませんが、 doctest はその内容を無視します。普通はトレースバックスタックを無視するか、 対話セッションからそのままコピーしてきます。

トレースバックスタックの後ろにはもっとも有意義な部分、例外の型と 詳細情報の入った行があります。通常、この行はトレースバックの末尾 にあるのですが、例外が複数行の詳細情報を持っている場合、複数の行 にわたることもあります:

    >>> raise ValueError('multi\n    line\ndetail')
    Traceback (most recent call last):
      File "<stdin>", line 1, in ?
    ValueError: multi
        line
    detail

上の例では、最後の 3 行 (`ValueError` から始まる行) における例外の型と詳細情報だけが比較され、それ以外の部分は無視 されます。

例外を扱うコツは、例題をドキュメントとして読む上で明らかに価値の ある情報でない限り、トレースバックスタックは無視する、ということ です。従って、先ほどの例は以下のように書くべきでしょう:

    >>> raise ValueError('multi\n    line\ndetail')
    Traceback (most recent call last):
        ...
    ValueError: multi
        line
    detail

トレースバックの扱いは非常に特殊なので注意してください。特に、 上の書き直した例題では、"`...`" の扱いが doctest の `ELLIPSIS` オプションによって変わります。この例での省略記号 は何かの省略を表しているかもしれませんし、コンマや数字が 3 個 (または 300 個かもしれませんし、Monty Python のスキットをインデントして 書き写したものかもしれません。

以下の詳細はずっと覚えておく必要はないのですが、一度目を通しておいて ください:

- doctest は予想出力の出所が print 文なのか例外なのかを推測 できません。従って、例えば予想出力が "`ValueError: 42 is prime`" であるような例題は、`ValueError` が実際に送出された 場合と、万が一予想出力と同じ文字列を print した場合の両方で パスしてしまいます。現実的には、通常の出力がトレースバックヘッダ から始まることはないので、さしたる問題にはなりません。

- トレースバックスタック (がある場合) の各行は、例題の最初の行 よりも深くインデントされているか、または 英数文字以外で 始まっていなければなりません。トレースバックヘッダ以後に現れる行の うち、インデントが等しく英数文字で始まる最初の行は例外の詳細情報 が書かれた行とみなされるからです。もちろん、通常のトレースバックでは 全く正しく動作します。

- doctest のオプション`IGNORE_EXCEPTION_DETAIL` を指定 した場合、最も左端のコロン以後の内容が無視されます。

- 対話シェルでは、`SyntaxError` の場合にトレースバック ヘッダを無視することがあります。しかし doctest にとっては、例外を例外で ないものと区別するためにトレースバックヘッダが必要です。 そこで、トレースバックヘッダを省略するような`SyntaxError` をテストする必要があるというごく稀なケースでは、例題に自分で作った トレースバックヘッダを追加する必要があるでしょう。

- `SyntaxError` の場合、 Python は構文エラーの起きた 場所を`^` マーカで表示します:

      >>> 1 1
        File "<stdin>", line 1
          1 1
            ^
      SyntaxError: invalid syntax

  例外の型と詳細情報の前にエラー位置を示す行がくるため、 doctest は この行を調べません。例えば、以下の例では、間違った場所に`^` マーカを入れてもパスしてしまいます:

      >>> 1 1
      Traceback (most recent call last):
        File "<stdin>", line 1
          1 1
          ^
      SyntaxError: invalid syntax

バージョン 2.4 で 変更 された仕様: 複数行からなる例外の詳細情報を扱えるようにし、 doctest オプション`IGNORE_EXCEPTION_DETAIL` を追加しました

#### Footnotes

... 単にトレースバックを貼り付けてください。44
  予想出力結果 と例外の両方を含んだ例はサポートされていません。一方の終わりと 他方の始まりを見分けようとするのはエラーの元になりがちですし、 解りにくいテストになってしまいます。