2016-12-26 27 views
1

在Linux上用Python 2.7.12测试。单元测试库如何确定是否运行装饰方法?

我想写一个简单的函数来装饰test_*方法unittest.TestCase。我知道不以test_开头的方法不被视为实际测试,并且在测试运行时不会被直接调用。然后我想知道如果你采取了test_方法并且将一个朴素的装饰器应用到它上面,那么它不会保留名称。我期待我的测试被忽略,并且必须修改我的修饰器以确保该函数的名称以test_开头。无论如何,测试时我都非常非常惊讶。

这里的例子

. 
|-- add.py 
|-- print_args.py 
|-- test_add.py 
`-- test_add_decorated.py 

0 directories, 4 files 

add.py的目录布局,我们正在测试的库。它增加了两件事。

def add(x, y): 
    return x + y 

print_args.py是包含打印功能作为副作用的指定参数和kwargs一个装饰的库。它被写成尽可能天真,并没有试图保留函数的名字。

def print_args(wrapped): 
    def wrapper(*args, **kwargs): 
     print [args, kwargs] 
     return apply(wrapped, args, kwargs) 

    return wrapper 

这里是test_add.py其中进口add.py和测试,4 + 5 = 9TestAdd__repr__方法与此示例没有直接关系,但将在下一个示例中。

import unittest 
import add 


class TestAdd(unittest.TestCase): 
    def __repr__(self): 
     return "I am a unittest.TestCase! Fear me!" 

    def test_add(self): 
     self.assertEqual(add.add(4, 5), 9) 


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

当我们运行test_add.py,我们可以看到一个测试运行,它通过。

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

OK 

现在,我们将装饰到test_add方法test_add_decorated.py

import unittest 
import print_args 
import add 


class TestAdd(unittest.TestCase): 
    def __repr__(self): 
     return "I am a unittest.TestCase! Fear me!" 

    @print_args.print_args 
    def test_add(self): 
     self.assertEqual(add.add(4, 5), 9) 


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

之前,我跑了这一点,我期待看到没有错误,但零测试指示已经用完,因为test_add方法的名称现在应该wrapper

这不是发生了什么事。装饰器工作正常,我们可以看到数组中的args和kwargs,并表明一次测试成功运行。

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

OK 
[(I am a unittest.TestCase! Fear me!,), {}] 

所以,我的问题是...怎么没unittest库弄清楚,它应该运行我的装饰方法?

+0

这是什么Python版本? –

+0

@SimeonVisser 2.7.12 –

回答

3

包装函数的__name__可能是wrapper,但它仍然是TestAdd.test_add。如果您查看TestAdd类的__dict__,则会发现绑定到密钥'test_add'的包装函数,并且如果您想调用该方法,则可以使用名称test_add而不是wrapper

unittest使用方法名称来确定方法是否是测试时,它不会查看__name__。它查看该方法与哪个属性名称相关联,并且装饰器不会影响该名称。

+2

对于上下文,你可以看到它在这里测试类本身调用'dir()':https://hg.python.org/cpython/file/2.7/Lib/unittest/loader。 PY#L140 –