2008-09-24 48 views

回答

379

使用TestCase.assertRaises(或TestCase.failUnlessRaises)从单元测试模块,例如:

import mymod 

class MyTestCase(unittest.TestCase): 
    def test1(self): 
     self.assertRaises(SomeCoolException, mymod.myfunc) 
+1

是有办法做到这相反?就像它只有在函数抛出异常时才会失败? – BUInvent 2017-07-26 19:44:59

+4

@BUInvent,是的,有:https://stackoverflow.com/a/4319870/3405140 – moertel 2017-07-27 16:23:47

+0

请注意,要将参数传递给`myfunc`,您需要将它们作为参数添加到assertRaises调用中。见Daryl Spitzer的回答。 – cbron 2018-02-21 16:43:15

24

您的代码应遵循此模式(这是一个单元测试模块的风格测试):

def test_afunction_throws_exception(self): 
    try: 
     afunction() 
    except ExpectedException: 
     pass 
    except Exception as e: 
     self.fail('Unexpected exception raised:', e) 
    else: 
     self.fail('ExpectedException not raised') 

关于Python < 2.7此构造对于检查预期异常中的特定值很有用。单元测试功能assertRaises仅检查是否引发异常。

+2

和方法self.fail只带一个参数 – mdob 2012-10-14 21:54:33

+3

这对于测试函数是否引发异常似乎过于复杂。由于除了那个异常之外的任何异常都会错误地测试,并且不会抛出异常将会使测试失败,似乎唯一的区别是,如果你通过`assertRaises`得到一个不同的异常,你将得到一个ERROR而不是一个FAIL。 – unflores 2015-01-21 12:52:28

160

在我以前的答案的代码可以简化为:

def test_afunction_throws_exception(self): 
    self.assertRaises(ExpectedException, afunction) 

如果机能缺失接受参数,只需将它们传递到assertRaises这样的:

def test_afunction_throws_exception(self): 
    self.assertRaises(ExpectedException, afunction, arg1, arg2) 
+0

如何处理控制台中存在的异常的追踪?也就是说,在其他方面通过的测试中有一个追溯。 – MadPhysicist 2017-03-15 14:13:13

+0

@MadPhysicist我看不到你在说什么。我刚刚在Python 2.6和3.5上进行了测试 - 没有将Tracebacks打印到控制台。也许你正在打印或记录代码中的回溯? – 2017-04-04 17:43:55

7

我用文档测试 [1 ]几乎无处不在,因为我喜欢我同时记录和测试我的功能的事实。

看一看这段代码:

def throw_up(something, gowrong=False): 
    """ 
    >>> throw_up('Fish n Chips') 
    Traceback (most recent call last): 
    ... 
    Exception: Fish n Chips 

    >>> throw_up('Fish n Chips', gowrong=True) 
    'I feel fine!' 
    """ 
    if gowrong: 
     return "I feel fine!" 
    raise Exception(something) 

if __name__ == '__main__': 
    import doctest 
    doctest.testmod() 

如果你把这个例子中的模块中,并通过命令行测试案例进行评估,并检查运行它。

[1] Python documentation: 23.2 doctest -- Test interactive Python examples

4

我刚刚发现Mock library提供assertRaisesWithMessage()方法(在它的子类unittest.TestCase生成),这将不仅检查了预期的异常升高,而且它是与预期的消息提出:

from testcase import TestCase 

import mymod 

class MyTestCase(TestCase): 
    def test1(self): 
     self.assertRaisesWithMessage(SomeCoolException, 
            'expected message', 
            mymod.myfunc) 
255

因为Python 2.7,你可以使用上下文管理器来获得抛出的实际Exception对象的保持:

import unittest 

def broken_function(): 
    raise Exception('This is broken') 

class MyTestCase(unittest.TestCase): 
    def test(self): 
     with self.assertRaises(Exception) as context: 
      broken_function() 

     self.assertTrue('This is broken' in context.exception) 

if __name__ == '__main__': 
    unittest.main() 

http://docs.python.org/dev/library/unittest.html#unittest.TestCase.assertRaises


的Python 3.5,你必须包装在strcontext.exception,否则你会得到一个TypeError

self.assertTrue('This is broken' in str(context.exception)) 
0

您可以使用assertRaises从单元测试模块

import unittest 

class TestClass(): 
    def raises_exception(self): 
    raise Exception("test") 

class MyTestCase(unittest.TestCase): 
    def test_if_method_raises_correct_exception(self): 
    test_class = TestClass() 
    # note that you dont use() when passing the method to assertRaises 
    self.assertRaises(Exception, test_class.raises_exception) 
7

来自:http://www.lengrand.fr/2011/12/pythonunittest-assertraises-raises-error/

首先,这里是文件dum_function中相应的(仍然是dum:p)函数。潘岳:

def square_value(a): 
    """ 
    Returns the square value of a. 
    """ 
    try: 
     out = a*a 
    except TypeError: 
     raise TypeError("Input should be a string:") 

    return out 

这里是要进行的测试(仅适用于本次测试插入):

import dum_function as df # import function module 
import unittest 
class Test(unittest.TestCase): 
    """ 
     The class inherits from unittest 
     """ 
    def setUp(self): 
     """ 
     This method is called before each test 
     """ 
     self.false_int = "A" 

    def tearDown(self): 
     """ 
     This method is called after each test 
     """ 
     pass 
     #--- 
     ## TESTS 
    def test_square_value(self): 
     # assertRaises(excClass, callableObj) prototype 
     self.assertRaises(TypeError, df.square_value(self.false_int)) 

    if __name__ == "__main__": 
     unittest.main() 

现在我们可以测试我们的功能!以下是试图运行测试时发生的情况:

====================================================================== 
ERROR: test_square_value (__main__.Test) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "test_dum_function.py", line 22, in test_square_value 
    self.assertRaises(TypeError, df.square_value(self.false_int)) 
    File "/home/jlengrand/Desktop/function.py", line 8, in square_value 
    raise TypeError("Input should be a string:") 
TypeError: Input should be a string: 

---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

FAILED (errors=1) 

TypeError被触发,并生成测试失败。问题是这正是我们想要的行为:s。

为了避免这种错误,只需在测试呼叫使用lambda运行函数:

self.assertRaises(TypeError, lambda: df.square_value(self.false_int)) 

最终输出:

---------------------------------------------------------------------- 
Ran 1 test in 0.000s 

OK 

完美!

...对我来说也是完美的!

Thansk很多朱利安·朗格朗兰伯特先生

2

你可以建立自己的contextmanager检查是否异常升高。

import contextlib 

@contextlib.contextmanager 
def raises(exception): 
    try: 
     yield 
    except exception as e: 
     assert True 
    else: 
     assert False 

然后你就可以使用raises这样的:

with raises(Exception): 
    print "Hola" # Calls assert False 

with raises(Exception): 
    raise Exception # Calls assert True 

如果使用的是pytest,这件事情已经落实。你可以做pytest.raises(Exception)

例子:

def test_div_zero(): 
    with pytest.raises(ZeroDivisionError): 
     1/0 

而结果:

[email protected]$ py.test 
================= test session starts ================= 
platform linux2 -- Python 2.6.6 -- py-1.4.20 -- pytest-2.5.2 -- /usr/bin/python 
collected 1 items 

tests/test_div_zero.py:6: test_div_zero PASSED 
73

你如何测试一个Python函数抛出一个异常?

如何编写一个测试,只有在函数不会将 预期的异常抛出时才会失败?

答案很简单:

使用self.assertRaises方法作为上下文管理器:

def test_1_cannot_add_int_and_str(self): 
     with self.assertRaises(TypeError): 
      1 + '1' 

示范

的最佳实践方法是很容易在Python外壳来证明。

unittest

在Python 2。7或3:

import unittest 

在Python 2.6,你可以安装2.7的unittest库的反向移植,叫​​,只是别名为unittest

import unittest2 as unittest 

示例测试

现在,将Python的类型安全性粘贴到您的Python shell中:

class MyTestCase(unittest.TestCase): 
    def test_1_cannot_add_int_and_str(self): 
     with self.assertRaises(TypeError): 
      1 + '1' 
    def test_2_cannot_add_int_and_str(self): 
     import operator 
     self.assertRaises(TypeError, operator.add, 1, '1') 

测试人员使用assertRaises作为上下文管理器,可确保在记录时正确捕获并清除错误。

我们也可以写它没有上下文管理器,见测试二。第一个参数是您期望提出的错误类型,第二个参数,您正在测试的函数,剩余的参数和关键字参数将被传递给该函数。

我认为它更简单,更易读,更易于使用上下文管理器。

运行测试

运行测试:

unittest.main(exit=False) 

在Python 2.6,你可能会need the following

unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase)) 

而且终端应该输出如下:

.. 
---------------------------------------------------------------------- 
Ran 2 tests in 0.007s 

OK 
<unittest2.runner.TextTestResult run=2 errors=0 failures=0> 

我们可以看到,正如我们预期的那样,试图在TypeError中添加1'1'


更详细的输出,试试这个:

unittest.TextTestRunner(verbosity=2).run(unittest.TestLoader().loadTestsFromTestCase(MyTestCase))