2009-06-15 33 views
10

私は単なるPythonプログラミングの初心者であり、unittestモジュールに関するいくつかの質問があります。Pythonコンストラクタでの例外のユニットテスト

私はクラスを持っていますが、__init__メソッドでは、悪い引数を調べるためにいくつかのアサーションを行っています。新しいインスタンスを作成するときに、そのようなAssertionErrorをチェックするunittestを作成したいと思います。

unittestモジュールでは、呼び出し可能呼び出し時に特定の例外をテストすることができます(ただし、assertRaises)が、明らかにそのクラスのメソッドに適用されます。コンストラクタのテストを実行する適切な方法は何ですか?

不正な引数を持つクラスのインスタンスを作成しようとすると、unittestはテストの失敗を報告しますが、最初の例外の直後に停止します。複数のテストを複数回テスト機能は、まったくエレガントではありません。

答えて

1

まず、悪い引数のチェックは、Pythonでは良い考えではありません。 Pythonは、理由のために動的に型付けされています。

引数が適切な引数であると仮定してください。クラスのユーザーの意図を知らないので、良い引数をチェックすることで、より一般的なインスタンスでクラスの使用を制限することができます。

代わりに良いAPIを定義し、ドキュメントストリングとテキストを使用してそれを非常にうまく文書化し、不正な引数のエラーをユーザーに自動的に伝えます。

例:

def sum_two_values(value_a, value_b): 
    return value_a + value_b 

大丈夫、この例は愚かであるが、私は整数として値をチェックして主張している場合、機能は私以外の理由もなく、山車、文字列、リストでは動作しません。チェックして、なぜ最初の場所にチェックインするのですか?それは動作しないタイプで自動的に失敗するので、心配する必要はありません。

+0

後、私は、ctypesのといくつかのCライブラリをロードして...彼らに –

+0

@asen_asenovをコンストラクタから引数を渡すために持っているので、私は、何かが早期に間違っていることを主張したいと思い、私の特定のケースではまあ、:その場合、 、あなたのctypes呼び出しを適切な変換でラップするだけです。 ctypes.c_int(param)。そうすれば、型が互換性があり、互換性のない型に対して自動的にエラーが発生します。 – nosklo

7

assertRaisesで混乱させないでください。それはあまりにも複雑です。

この

class Test_Init(unittest.TestCase): 
    def test_something(self): 
     try: 
      x= Something("This Should Fail") 
      self.fail("Didn't raise AssertionError") 
     except AssertionError, e: 
      self.assertEquals("Expected Message", e.message) 
      self.assertEquals(args, e.args) 

は他の例外は、通常のテスト・エラーになります。

__init__メソッドであまりにも多くの先行エラーチェックを混乱させないでください。誰かが間違ったタイプのオブジェクトを提供すると、コードは通常のイベントの過程で失敗し、通常の手段で通常の例外が発生します。オブジェクトをあらかじめ「プレスクリーン」する必要はありません。ユニットテストモジュールにおいて

+2

「それは複雑すぎる」に拡張できますか?私は 'assertRaises(assertionError、...)'(アサーションが発生しましたが、 'assertRaises'によって捕捉されませんでした)の問題を抱えていました。なぜか... – naught101

+0

もっと迷惑なコードです彼らは 'message'プロパティを持っていないので(少なくともPython 3では)、AssertionErrorsを実際に使っていません。 – naught101

17

、呼び出し可能が呼び出されたときに一方が特定の例外のために(assertRaisesで)テストすることができ、しかし、明らかに、そのクラスのメソッドに適用されます。コンストラクタのテストを実行する適切な方法は何ですか?

コンストラクタは呼び出し可能そのものです:

self.assertRaises(AssertionError, MyClass, arg1, arg2) 

言われていること、私はnosklo年代と引数の型チェックを行うことについてS.Lottの懸念をエコーし​​ます。さらに、関数の引数をチェックするためにアサーションを使用すべきではありません。アサーションは、何か内部的にコードに間違いがない限りトリガされないサニティチェックとして最も役に立ちます。また、assert文はPythonが "最適化された" -Oモードで実行されるときにコンパイルされます。関数が引数の何らかのチェックを行う必要がある場合は、適切な例外が発生します。

+1

-1:アサーションは引数をチェックするのに最適です。非常に短いコード:アサート0 <= n、 "nは負である"。 –

+0

私はそれが意見の問題だと思います。 – Miles

0

S.Lottの答えが間違っています:self.fail()自体は次の行で例外によって引き起こされる例外、発生します

class NetworkConfigTest1(unittest.TestCase): 
    def runTest(self): 
     try: 
      NetworkConfig("192.168.256.0/24") 
      self.fail("Exception expected but not thrown") 
     except Exception, error: 
      printf("Exception caught: %s" % str(error) 
      pass 

出力は「例外は期待が、投げられない」たのが、テストされているコードは書かれていませんでしたが、単体テストは失敗とマークされませんでした。メソッドが例外を発生させるかどうかを確認するために

以上の有効な方法を使用することです:

私の場合は
self.failUnlessRaises([error], [callable], [arguments to callable]) 

、私がテストだクラスがNetworkConfigと呼ばれ、コンストラクタがあれば例外をスローする必要がありますネットワーク記述子が無効です。

class NetworkConfigTest1(unittest.TestCase): 
    def runTest(self): 
     self.failUnlessRaises(Exception, NetworkConfig, "192.168.256.0/24") 

これは適切に機能し、正しいテストを実行します。

2

か分からないのですが、これは役立ちますが、以下のように、私が持っていた問題は、次のとおりです。

self.assertRaises(Exception, MyFunction()) 

問題は、私はちょうどMyFunctionを渡しますが、同様にそれを呼び出して、失敗して例外が生じていなかったです育てられている。 Myfunctionは、引数を期待し、私は何も渡されていない場合、それは失敗にしたい、私はそれを考え出したまでしばらくの間、私をイライラ:予想通り

self.assertRaises(Exception, MyFunction) 

作品。

関連する問題