2015-11-05 61 views
0

我有以下代码:如何assertRaises一个特定的异常

def foo(input): 
    if not input.startswith("prefix"): 
     raise Exception("input should start with prefix!") 
    process(input) 

现在我想单元测试这个功能;当input不是以"prefix"开头时,它实际上可能会抛出异常。这里是我的unittest代码:

def test_foo_invalud_type(self): 
    self.assertRaises(Exception, foo, 999) 

与这个测试代码的问题是:它捕获了异常,但例外的是'int' object has no attribute 'startswith',而不是input should start with prefix!。测试会通过,但这不是一个好的测试。我如何识别两个例外?

回答

4

raise Exception是非常糟糕的形式 - 尝试在引发异常时更具体。使用这样的一般异常使得你很难区分你想要测试的两种不同情况。

在这种情况下,例如,我认为ValueError会内foo是最合适的,因为它是事情的正确类型(一个字符串),但没有正确的价值(不'prefix'在开始)。

def foo(input): 
    if not input.startswith("prefix"): 
     raise ValueError("input should start with prefix!") 
    process(input) 

这让你输入的类型之间进行区分是错的(这引起了一个AttributeError由于不存在的.startswith *):

def test_foo_invalid_type(self): # note fixed typo in 'invalud' 
    self.assertRaises(AttributeError, foo, 999) # and more specific error 

和输入的ValueError明确提出缺少'prefix'前缀):

def test_foo_invalid_value(self): 
    with self.assertRaises(ValueError) as cm: 
     foo('no prefix') 
     self.assertEqual(
      cm.exception.args, 
      ('input should start with prefix!',), 
     ) 

请注意如何使用with上下文管理器形式assertRaises来访问错误本身。这使您还可以检查是否为错误提供了正确的消息。


*您甚至可以考虑处理AttributeErrorfoo,提高一个TypeError代替。这似乎更适合于“该参数是错误的类型”

+0

我认为我误解了这个问题至少两次,但我现在对此感到高兴...... – jonrsharpe

+0

谢谢。我不得不承认我的问题是一个不好的描述。 – Suanmeiguo

1

你正在向函数foo传递一个int,但它看起来像你想要一个str(因为你在参数input上使用startswith)。单元测试应该是:

def test_foo_invalud_type(self): 
    self.assertRaises(Exception, foo, '999') 
0

是提高误差线是:

if not input.startswith("prefix"): 

而不是:

raise Exception("input should start with prefix!") 

因为你传递一个int,而不是字符串:999而不是'999'

请记住int,没有属性startswith。

0

只需执行并引发您自己的异常。

class BadStartException(Exception): 
    pass 

def foo(input): 
    if not input.startswith("prefix"): 
     raise BadStartException("input should start with prefix!") 
    process(input) 

def test_foo_invalud_type(self): 
    self.assertRaises(BadStartException, foo, 999) 

请注意,您的测试现在会失败。我不确定这是你想测试的。

+0

但问题是'foo(999)'不会引发BadStartException异常,它是'AttributeError'! – jonrsharpe

+0

@jonrsharpe这是'foo'的问题,而不是这个答案的问题。不要举'例外'! – o11c