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

问题:Python unittest中的setUp()和setUpClass()有什么区别?

setUp()setUpClass()Python unittest框架之间有什么区别?为什么设置会以一种方法而不是另一种方法处理?

我想了解什么设置的一部分在完成setUp()setUpClass()功能,以及与tearDown()tearDownClass()

What is the difference between setUp() and setUpClass() in the Python unittest framework? Why would setup be handled in one method over the other?

I want to understand what part of setup is done in the setUp() and setUpClass() functions, as well as with tearDown() and tearDownClass().


回答 0

当您的类中有多个测试方法时,差异就会显现出来。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之前和之后出现test1 test2,而setUpClasstearDownClass只出现一次,在整个测试案例的开始和结束。

The difference manifests itself when you have more than one test method in your class. setUpClass and tearDownClass are run once for the whole class; setUp and tearDown are run before and after each test method.

For example:

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")

When you run this test, it prints:

setUpClass
setUp
test1
tearDown
.setUp
test2
tearDown
.tearDownClass

(The dots (.) are unittest‘s default output when a test passes.) Observe that setUp and tearDown appear before and after test1 and test2, whereas setUpClass and tearDownClass appear only once, at the beginning and end of the whole test case.


回答 1

setUp()setUpClass()Python unittest框架之间有什么区别?

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

unittest 文档中

setUpClass()

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

@classmethod
def setUpClass(cls):
    ...

和:

setUp()

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

为什么设置会以一种方法而不是另一种方法处理?

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

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

What is the difference between setUp() and setUpClass() in the Python unittest framework?

The main difference (as noted in the answer by Benjamin Hodgson) is that setUpClass is called only once and that is before all the tests, while setUp is called immediately before each and every test. (NB: The same applies to the equivalent methods in other xUnit test frameworks, not just Python’s unittest.)

From the unittest documentation:

setUpClass()

A class method called before tests in an individual class are run. setUpClass is called with the class as the only argument and must be decorated as a classmethod():

@classmethod
def setUpClass(cls):
    ...

and:

setUp()

Method called to prepare the test fixture. This is called immediately before calling the test method; other than AssertionError or SkipTest, any exception raised by this method will be considered an error rather than a test failure. The default implementation does nothing.

Why would setup be handled in one method over the other?

This part of the question has not been answered yet. As per my comment in response to the answer by Gearon, the setUp method is meant for elements of the fixture that are common to all tests (to avoid duplicating that code in each test). I find this is often useful as removing duplication (usually) improves readability and reduces the maintenance burden.

The setUpClass method is for expensive elements that you would rather only have to do once, such as opening a database connection, opening a temporary file on the filesystem, loading a shared library for testing, etc. Doing such things before each test would slow down the test suite too much, so we just do it once before all the tests. This is a slight degradation in the independence of the tests but a necessary optimization in some situations. Arguably, one should not be doing such things in unit tests as it is usually possible to mock the database / filesystem / library / whatever without using the real thing. As such, I find that setUpClass is rarely needed. However, it is useful when testing the above examples (or similar) becomes necessary.