4

私はassert_raisedテスト用のコンテキスト マネージャーを作成しました。これは、予想どおりに例外が発生したことを確認し、そうでない場合はAssertionError. これをテストするための doctest も作成しましたが、doctest が失敗し続け、その理由がよくわかりません。doctest は次のとおりです。

>>> for e in [TypeError, ValueError, KeyError]:
...     with assert_raised(TypeError, ValueError):
...         print('Raising {}...'.format(e.__name__))
...         raise e
Raising TypeError...
Raising ValueError...
Raising KeyError...
Traceback (most recent call last):
    ...
AssertionError: Got 'KeyError', expected 'TypeError, ValueError'

実際に発生する例外は次のとおりです。

Traceback (most recent call last):
  File "<doctest dtlibs.mock.assert_raised[3]>", line 4, in <module>
    raise e
KeyError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python32\lib\doctest.py", line 1253, in __run
    compileflags, 1), test.globs)
  File "<doctest dtlibs.mock.assert_raised[3]>", line 4, in <module>
    raise e
  File "G:\Projects\Programming\dt-tools\dtlibs\dtlibs\mock.py", line 274, in __exit__
    raise self._exception(exc_type.__name__)
AssertionError: Got 'KeyError', expected 'TypeError, ValueError'

実装は重要ではないと思いますが、ここで何か間違ったことをしている場合に備えて (doctest なしで):

class assert_raised:

    def __init__(self, *exceptions):
        self.exceptions = exceptions

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type is None:
            raise self._exception('None')
        elif self.exceptions and exc_type not in self.exceptions:
            raise self._exception(exc_type.__name__)
        return True

    def _exception(self, got):
        if len(self.exceptions) == 0:
            expected = 'an exception'
        else:
            expected = ', '.join(e.__name__ for e in self.exceptions)
        msg = "Got '{}', expected '{}'".format(got, expected)
        return AssertionError(msg)
4

1 に答える 1

4

Doctests には、例外の発生を処理するための特別なコードがあります。そのため、出力が例外であることを認識します。これを認識するためには、予想される出力が単語で始まる必要がありますTraceback。予想される出力はこれで始まらないため、doctest は出力が例外を予想していると認識せず、例外が予想されないため、例外が発生すると失敗します。

これは、次の 3 つの方法で修正できます。

  1. Raising XXXError...出力の一部を取り除きます。[怠惰]

  2. Raising XXXError...doctest が-part [複雑]を無視できるようにする特別な出力フィルタを doctest に実装します。

  3. ドキュメントのテスト以外の目的で doctests を使用するのはやめてください。[正しい]

上記のコードは明らかに、このコンテキスト マネージャーの使用方法のサンプル コードではなく、コンテキスト マネージャーが機能することをテストするコードです。そのようなテストは決してドキュメントテストであってはなりません。Doctest は苦痛で限界があるため、ドキュメントのテストにのみ使用する必要があります。

于 2012-04-10T07:22:50.397 に答える