2011-10-17 6 views
24

私は鼻で例外をテストしています。鼻でどのように例外をテストすればよいですか?

def testDeleteUserUserNotFound(self): 
    "Test exception is raised when trying to delete non-existent users" 
    try: 
     self.client.deleteUser('10000001-0000-0000-1000-100000000000') 
     # make nose fail here 
    except UserNotFoundException: 
     assert True 

アサーションは例外が発生した場合に実行されますが、例外が発生しない場合は実行されません。

上記のコメント行には何も置くことができます。例外が発生していない場合は、障害が報告されますか?

+0

ほとんどのdupのhttp://stackoverflow.com/questions/11767938/how-to-use-noses-assert-raises – Stefano

答えて

39

は(unittestのがないように)例外をテストするためのツールを提供します。 この例を試してみてください(とNose Testing Tools

from nose.tools import * 

l = [] 
d = dict() 

@raises(Exception) 
def test_Exception1(): 
    '''this test should pass''' 
    l.pop() 

@raises(KeyError) 
def test_Exception2(): 
    '''this test should pass''' 
    d[1] 

@raises(KeyError) 
def test_Exception3(): 
    '''this test should fail (IndexError raised but KeyError was expected)''' 
    l.pop() 

def test_Exception4(): 
    '''this test should fail with KeyError''' 
    d[1] 

で他のツールについて読んで私はそれはあなたが期待したりしたい例外について具体的にすることができますので、これはあなたが探していた適切な方法あると思うだろうあなたが実際にエラーを誘発して正しい例外が発生したとしたら、ノーズは結果を評価します(できるだけユニットテストにロジックを入れてください)

+4

ありがとう。物事の見た目でも「assert_raises」があります。 – BartD

+2

noseはunittestからのself.assertRaisesであるassert_raisesも公開しています。これは、フォームで例外をさらに処理する必要がある場合に便利です。 assertRaises(ValueError)with e:

1

私は鼻が何であるかわかりませんが、except節の後ろに 'else'を使ってみましたか?私。

else: 
    assert False 
8
def testDeleteUserUserNotFound(self): 
    "Test exception is raised when trying to delete non-existent users" 
    try: 
     self.client.deleteUser('10000001-0000-0000-1000-100000000000') 
     assert False # <--- 
    except UserNotFoundException: 
     assert True 

try/exceptのセマンティクスは、実行の流れが例外でtryブロックを残し、その例外が発生した場合assert Falseが実行されないことを意味します。また、exceptブロックの実行が終了すると、ブロック実行後に再びtryブロックに再実行されることはありません。

 ↓ 
(statements) 
    ↓ exception 
    (try) ↚──────────→ (except) 
    ↓     │ 
(statements) ←───────────┘ 
    ↓ 
6

私はなぜそれがわからないのですか?まだここには存在しませんが、もうひとつ存在します:

import unittest 

class TestCase(unittest.TestCase): 

    def testKeyError(self): 
     d = dict() 
     with self.assertRaises(KeyError): 
      d[1] 
+1

このメカニズムは、nosetestsを使ったテストに関するものであり、 'unittests.TestCase'のクラスや継承のユーザは必要ありません('あなたが言及するassertRaisesメソッド)。 – PeterJCLaw

2

使用assert_raises:あなたのテストでtryおよびcatchを使用して

from nose.tools import assert_raises 

our_method   = self.client.deleteUser 
arg1    = '10000001-0000-0000-1000-100000000000' 
expected_exception = UserNotFoundException 

assert_raises(expected_exception, our_method, arg1) 

悪い習慣(ほとんどの場合)のように思えます。それは基本的にunittest.TestCase.assertRaises(参考文献How to use nose's assert_raises?)単なるラッパー

4

私は強くassertRaisesunittest.TestCaseからassertRaisesRegexpの動作を複製nose.toolsからassert_raisesassert_raises_regexpを、使用することをお勧めだから

鼻には固有のドキュメントはありません。これにより、実際にunittest.TestCaseクラスを使用しないテストスイートでは、unittest.TestCaseと同じ機能を使用できます。

私は、@raisesが非常に鈍い器械であることがわかりました。 fooは、我々が期待していた例外を調達しているので、しかしfooが使用するデータを設定したコードは、同じ例外で失敗するので

from nose.tools import * 

something = ["aaa", "bbb"] 

def foo(x, source=None): 
    if source is None: 
     source = something 
    return source[x] 

# This is fine 
@raises(IndexError) 
def test1(): 
    foo(3) 

# This is fine. The expected error does not happen because we made 
# a mistake in the test or in the code. The failure indicates we made 
# a mistake. 
@raises(IndexError) 
def test2(): 
    foo(1) 

# This passes for the wrong reasons. 
@raises(IndexError) 
def test3(): 
    source = something[2] # This is the line that raises the exception. 
    foo(10, source) # This is not tested. 

# When we use assert_raises, we can isolate the line where we expect 
# the failure. This causes an error due to the exception raised in 
# the first line of the function. 
def test4(): 
    source = something[2] 
    with assert_raises(IndexError): 
     foo(10, source) 

test3パスではなく:ここでは、問題を示すコードです。test4は、実際にテストすることを意味するものを実際にテストするために、を使用してテストを書き込む方法を示しています。最初の行の問題は、Noseにエラーを報告させ、次にテストを書き直して、その行をテストして、最終的にテストしたことをテストできるようにします。

@raisesは、例外に関連するメッセージのテストを許可しません。私がValueErrorを上げるとき、ちょうど1つの例を取るために、私は通常有益なメッセージでそれを上げたいと思う。ここでは例です:渡します@raises使用

def bar(arg): 
    if arg: # This is incorrect code. 
     raise ValueError("arg should be higher than 3") 

    if arg >= 10: 
     raise ValueError("arg should be less than 10") 

# We don't know which of the possible `raise` statements was reached. 
@raises(ValueError) 
def test5(): 
    bar(10) 

# Yes, we're getting an exception but with the wrong value: bug found! 
def test6(): 
    with assert_raises_regexp(ValueError, "arg should be less than 10"): 
     bar(10) 

test5が、それは間違った理由のために渡します。 test6は、より細かいテストを実行して、ValueErrorが欲しいものではないことがわかりました。

関連する問題