例外を鼻でテストしています。次に例を示します。
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
例外が発生した場合はアサートが実行されますが、例外が発生しなかった場合は実行されません。
上記のコメント付きの行に何か例外を発生させない場合、鼻が失敗を報告するために何か私ができることはありますか?
noseは、(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]
これはあなたが探していた適切な方法であると私は思うでしょう。なぜならそれはあなたが期待する、または望む例外を特定できるからです。したがって、実際にエラーを引き起こして、適切な例外が発生することを確認します。そして、noseに結果を評価させます。 (単体テストにはできるだけ少ないロジックを入れてください!)
assert_raises
のassert_raises_regexp
およびnose.tools
を使用することを強くお勧めします。これらは、unittest.TestCase
の assertRaises
および assertRaisesRegexp
の動作を複製します。これらにより、実際にはunittest.TestCase
クラスを使用しないテストスイートでunittest.TestCase
によって提供されるのと同じ機能を使用できます。
@raises
は、あまりにも鈍い楽器であることがわかりました。ここに問題を示すコードがあります:
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
はパスしますが、foo
が予期した例外を発生させたためではなく、foo
が使用するデータを設定するコードが同じ例外で失敗したためです。 test4
は、assert_raises
を使用してテストを記述し、テスト対象を実際にテストする方法を示しています。最初の行の問題により、Noseはエラーを報告します。次に、テストを書き直して、その行をテストして、テストの意味を最終的にテストできるようにします。
@raises
では、例外に関連付けられたメッセージをテストできません。 ValueError
をレイズする場合、1つの例を挙げると、通常は情報メッセージでレイズしたいと思います。次に例を示します。
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
を使用する@raises
はパスしますが、間違った理由でパスします。 test6
は、より細かいテストを実行して、発生したValueError
が目的のものではなかったことを明らかにします。
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
は、例外が発生した場合は実行されません。また、try
ブロックの実行が完了した後、実行によってexcept
ブロックに再び入ることはないため、問題が発生することはありません。
↓
(statements)
↓ exception
(try) ↚──────────→ (except)
↓ │
(statements) ←───────────┘
↓
まだここにない理由はわかりませんが、もう1つの方法があります。
import unittest
class TestCase(unittest.TestCase):
def testKeyError(self):
d = dict()
with self.assertRaises(KeyError):
d[1]
使用する assert_raises
:
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)
テストでtry and catchを使用することは悪い習慣のようです(ほとんどの場合)。
それは基本的に単なるラッパーなので、鼻に特定のドキュメントはありません nittest.TestCase.assertRaises (ref。 鼻のassert_raisesの使い方? )
鼻が何であるかはわかりませんが、except句の後に「else」を使用してみましたか?つまり.
else:
assert False