Python unittest中setUp()和setUpClass()有什么区别?

时间:2014-05-15 01:04:26

标签: python unit-testing python-unittest

Python setUp()框架中setUpClass()unittest之间有什么区别?为什么设置应该用一种方法处理另一种方法?

我想了解setUp()setUpClass()函数以及tearDown()tearDownClass()中的设置部分是什么。

3 个答案:

答案 0 :(得分:107)

当您的班级中有多个测试方法时,差异就会显现出来。 setUpClasstearDownClass为整个班级运行一次; setUptearDown在每种测试方法之前和之后运行。

例如:

class Example(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("setUpClass")

    def setUp(self):
        print("setUp")

    def test1(self):
        print("test1")

    def test2(self):
        print("test2")

    def tearDown(self):
        print("tearDown")

    @classmethod
    def tearDownClass(cls):
        print("tearDownClass")

运行此测试时,会打印:

setUpClass
setUp
test1
tearDown
.setUp
test2
tearDown
.tearDownClass

(测试通过时,点(.)是unittest的默认输出。)观察setUptearDown出现在{之前和之后{ {1}} test1,而test2setUpClass只出现一次,在整个测试用例的开头和结尾。

答案 1 :(得分:6)

在Python setUp()框架中setUpClass()unittest有什么区别?

主要区别(如本杰明·霍奇森(Benjamin Hodgson)的回答中所述)是,setUpClass仅在所有测试之前被调用一次,而setUp在每个测试之前被调用。 (注意:这同样适用于其他xUnit测试框架中的等效方法,而不仅仅是Python的unittest。)

来自unittest documentation

  

setUpClass()

     

在运行单个类中的测试之前调用的类方法。使用类作为唯一参数调用setUpClass,并且必须将其装饰为classmethod():

@classmethod
def setUpClass(cls):
    ...

和:

  

setUp()

     

调用该方法准备测试夹具。在调用测试方法之前立即调用该方法。除了AssertionError或SkipTest之外,此方法引发的任何异常都将被视为错误而不是测试失败。默认实现不执行任何操作。

为什么在一种方法中要比另一种方法处理设置?

这部分问题尚未回答。根据我对Gearon回答的评论,setUp方法适用于所有测试通用的灯具元素(以避免在每个测试中重复该代码)。我发现这样做通常很有用,因为删除重复项通常可以提高可读性并减轻维护负担。

setUpClass方法用于只需要执行一次的昂贵元素,例如打开数据库连接,打开文件系统上的临时文件,加载用于测试的共享库等。每次测试之前的事情会使测试套件减慢太多,因此我们在所有测试之前只做一次。测试的独立性略有下降,但在某些情况下是必要的优化。可以说,在单元测试中不应该这样做,因为通常可以在不使用真实内容的情况下模拟数据库/文件系统/库/任何东西。因此,我发现几乎不需要setUpClass。但是,当需要测试上述示例(或类似示例)时,这很有用。

答案 2 :(得分:0)

阅读问题和接受的答案后,我认为可以做一些补充。

问:为什么设置要用一种方法而不是另一种方法?
答:这是因为测试方法可能需要初步的测试,而初步测试因测试方法而异。

例如,以https://www.tutorialspoint.com/unittest_framework/unittest_framework_api.htm中的以下代码为示例:

import unittest

class simpleTest2(unittest.TestCase):
   def setUp(self):
      self.a = 10
      self.b = 20
      name = self.shortDescription()
      if name == "add":
         self.a = 10
         self.b = 20
         print name, self.a, self.b
      if name == "sub":
         self.a = 50
         self.b = 60
         print name, self.a, self.b
   def tearDown(self):
      print '\nend of test',self.shortDescription()

   def testadd(self):
      """add"""
      result = self.a+self.b
      self.assertTrue(result == 30)
   def testsub(self):
      """sub"""
      result = self.a-self.b
      self.assertTrue(result == -10)

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

方法testaddtestsub需要不同的输入,我们可以分别在setUp方法中设置输入的值。