web-dev-qa-db-ja.com

NoneTypeオブジェクトで単体テストのassertRaises()を適切に使用する方法は?

私は簡単なテストケースを行いました:

def setUp(self):

  self.testListNone = None

def testListSlicing(self):

  self.assertRaises(TypeError, self.testListNone[:1])

そして、テストに合格することを期待していますが、例外が発生しています:

Traceback (most recent call last):

    self.assertRaises(TypeError, self.testListNone[:1])

TypeError: 'NoneType' object is unsubscriptable

TypeError例外が発生するので、assertRaisesがパスすると思いましたか?

149
Andriusa

Python2.7以降を使用している場合、 assertRaises の機能を使用してコンテキストマネージャーとして使用し、次の操作を実行できます。

with self.assertRaises(TypeError):
    self.testListNone[:1]

Python2.6をこれまでに与えられたものとは別の方法で使用している場合、 nittest2 を使用して、python2.6のunittest新機能のバックポートであり、上記のコードを使用して動作させることができます。

N.B:私はunittestの新機能(SkipTest、テスト発見...)の大ファンなので、できる限りunittest2を使用するつもりです。 python2.6 <でunittestに付属しているものよりもはるかに多いため、同じことを行うことをお勧めします。

228
mouad

問題は、メソッドを呼び出す前にTypeErrorの引数を評価する必要があるため、assertRaisesが「前に」発生することですassertRaisesが呼び出されることです。次のようなlambda式を渡す必要があります。

self.assertRaises(TypeError, lambda: self.testListNone[:1])
120
Bas Bossink

assertRaisesを使用する通常の方法は、関数を呼び出すことです。

self.assertRaises(TypeError, test_function, args)

関数呼び出しtest_function(args)がTypeErrorを発生させることをテストします。

self.testListNone[:1]の問題は、assertRaisesメソッドが呼び出される前に、Pythonがすぐに式を評価することです。 test_functionargsself.assertRaisesに別個の引数として渡される理由は、assertRaisestry...exceptブロック内からtest_function(args)を呼び出し、assertRaisesが例外をキャッチできるようにするためです。

self.testListNone = Noneを定義し、呼び出す関数が必要なので、次のように operator.itemgetter を使用できます。

import operator
self.assertRaises(TypeError, operator.itemgetter, (self.testListNone,slice(None,1)))

以来

operator.itemgetter(self.testListNone,slice(None,1))

self.testListNone[:1]を長々と言う方法ですが、関数(operator.itemgetter)を引数から分離します。

78
unutbu

完全なスニペットは次のようになります。 @mouadの答えを拡張して、エラーのメッセージ(または一般的にはstrargs表現)でアサートすることは有用かもしれません。

from unittest import TestCase


class TestNoneTypeError(TestCase):

  def setUp(self): 
    self.testListNone = None

  def testListSlicing(self):
    with self.assertRaises(TypeError) as ctx:
        self.testListNone[:1]
    self.assertEqual("'NoneType' object is not subscriptable", str(ctx.exception))
5
saaj