Python unittest与昂贵的设置

时间:2009-01-08 07:00:36

标签: python unit-testing

我的测试文件基本上是:

class Test(unittest.TestCase):
    def testOk():
        pass

if __name__ == "__main__":
    expensiveSetup()
    try:
        unittest.main()
    finally:
        cleanUp()

但是,我确实希望通过Netbeans测试工具进行测试,为此,我需要不依赖于 main 中完成的环境设置的单元测试。查看Caching result of setUp() using Python unittest - 它建议使用Nose。但是,我不认为Netbeans支持这一点。我没有找到任何表明它的信息。另外,我是这里唯一一个编写测试的人,所以我不想为其他2个开发人员引入额外的依赖项,除非他们需要。

如何对我的TestSuite中的所有测试进行一次设置和清理?

这里昂贵的设置是创建一些带有虚拟数据的文件,以及设置和拆除一个简单的xml-rpc服务器。我还有2个测试类,一个在本地测试,另一个在xml-rpc上测试所有方法。

8 个答案:

答案 0 :(得分:25)

如果您使用Python> = 2.7(或unittest2用于Python> = 2.4&< = 2.6),最好的方法是使用

def setUpClass(cls):
    # ...
setUpClass = classmethod(setUpClass)

为属于给定类的所有测试执行一次初始化。

要执行清理,请使用:

@classmethod
def tearDownClass(cls):
    # ...

另请参阅unittest标准库documentation on setUpClass and tearDownClass classmethods

答案 1 :(得分:7)

这就是我的所作所为:

class TestSearch(unittest.TestCase):
    """General Search tests for...."""

    matcher = None
    counter      = 0
    num_of_tests = None

    def setUp(self): # pylint: disable-msg=C0103 
        """Only instantiate the matcher once"""
        if self.matcher is None:
            self.__class__.matcher = Matcher()
            self.__class__.num_of_tests = len(filter(self.isTestMethod, dir(self)))
        self.__class__.counter = self.counter + 1 

    def tearDown(self): # pylint: disable-msg=C0103
        """And kill it when done"""
        if self.counter == self.num_of_tests:
            print 'KILL KILL KILL'
            del self.__class__.matcher

可悲的是(因为我确实希望我的测试是独立且确定的),我做了很多(因为系统测试花费不到5分钟也很重要)。

答案 2 :(得分:4)

首先,S。Lott说。但是!,你不想这样做。有一个原因,setUp和tearDown被包围在每个测试中:它们有助于保持测试的确定性。

否则,如果某些测试将系统置于错误状态,则下一次测试可能会失败。理想情况下,您的每个测试都应该是独立的。

另外,如果你坚持这样做,而不是手工编写self.runTest1(),self.runTest2(),你可能想要进行一些内省以找到要运行的方法。 / p>

答案 3 :(得分:3)

包级初始化不会为你做吗?来自Nose Wiki

  

nose允许将测试分组   测试包。这允许   包级设置;例如,如果   你需要创建一个测试数据库或   您的测试的其他数据夹具   可以在包装设置中创建它   每包一次将其拆除   测试运行,而不是必须创建   每个测试模块将其拆除一次   或测试案例。

     

创建包级别设置和   拆卸方法,定义设置和/或   __init__.py中的拆解功能   一个测试包。设置方法可以   名为setupsetup_packagesetUp,   或setUpPackage;拆解可能会被命名   teardownteardown_packagetearDown   或tearDownPackage。执行测试   在测试包中尽快开始   第一个测试模块是从中加载的   测试包。

答案 4 :(得分:2)

如果运行expensiveSetup(),您可以保存状态。

__expensiveSetup_has_run = False

class ExpensiveSetupMixin(unittest.TestCase):
    def setUp(self):
        global __expensiveSetup_has_run
        super(ExpensiveSetupMixin, self).setUp()
        if __expensiveSetup_has_run is False:
            expensiveSetup()
            __expensiveSetup_has_run = True

或者某种变化。也许ping ping xml-rpc服务器并在没有应答的情况下创建一个新服务器。

但AFAIK的单位测试方式是设置和拆除每单位测试,即使价格昂贵。

答案 5 :(得分:0)

我对Netbeans一无所知,但是我应该提到zope.testrunner,它支持一个漂亮的东西:图层。基本上,您在单独的类中执行testsetup,并将这些类附加到测试中。这些类可以相互继承,形成一个设置层。然后,testrunner将只调用每个设置一次,并将其状态保存在内存中,而不是设置和拆除,它只是将相关的层上下文复制为设置。

这大大加快了测试设置的速度,并在测试Zope产品和Plone时使用,其中testsetup通常需要您启动Plone CMS服务器,创建Plone站点并添加大量内容,这个过程可以采取超过半分钟。对每种测试方法执行此操作显然是不可能的,但对于图层,它只执行一次。这缩短了测试设置保护测试方法彼此,因此意味着测试继续是威慑。

所以我不知道zope.testrunner会为你工作,但值得一试。

答案 6 :(得分:0)

通过定义startTestRun的{​​{1}},stopTestRun,可以做到

。回答https://stackoverflow.com/a/64892396/2679740

答案 7 :(得分:-2)

如果您只有一种测试方法setUp,则可以确保tearDownrunTest执行一次。这种方法可以做任何其他想要的事情。请确保您没有任何名称以test开头的方法。

class MyExpensiveTest( unittest.TestCase ):
    def setUp( self ):
        self.resource = owThatHurts()
    def tearDown( self ):
        self.resource.flush()
        self.resource.finish()
    def runTest( self ):
        self.runTest1()
        self.tunTest2()
    def runTest1( self ):
        self.assertEquals(...)
    def runTest2( self ):
        self.assertEquals(...)

它不会自动确定要运行的内容。如果添加测试方法,则还必须更新runTest。