Unittest teardown()del所有属性

Mik*_*lla 6 python unit-testing

我有使用setup和teardown方法的单元测试,如下所示:

def setUp(self):
   self.foo = "bar"
   self.bar = "foo"

def tearDown(self):
   del self.foo
   del self.bar
Run Code Online (Sandbox Code Playgroud)

有没有更简洁的方法来调用__del__我实例化的每个对象setUp?如果我不这样做,那么setUp在每次测试后,打开的(通过实例化那些对象)的MySQL数据库的连接似乎都保持打开状态.

理想情况下,我当然会找出潜在的问题(为什么在测试完成并且测试用例被丢弃时,这些数据库连接没有被关闭).在此期间,是否有一种更清洁的方式来处理del所有这些对象?

使用MySQLdb库创建数据库连接,还有一个析构函数来关闭连接:

class Foo(object):

    def __init__(self,some_credentials):
        self.db_connection = MySQLdb.connect(some_credentials)

    def __del__(self):
        self.db_connection.close()
Run Code Online (Sandbox Code Playgroud)

Kar*_*ara 8

这里的根本问题是每个python单元测试在每个测试用例运行后都不会丢弃测试实例.实例保存在内存中,因此分配给self的任何对象也会保留在内存中,直到整个套件完成.

您可以使用以下代码重现此问题.每次运行的附加测试都会增加内存使用量.如果self.large_list设置为None,teardown那么内存使用量保持一致.

import resource
import unittest
import uuid


class TestSelfGarbageCollection(unittest.TestCase):

    def setUp(self):
        # Create an object that will use lots of memory
        self.large_list = []
        for _ in range(300000):
            self.large_list.append(uuid.uuid4())

    def tearDown(self):
        # Without the following line a copy of large_list will be kept in
        # memory for each test that runs, uncomment the line to allow the
        # large_list to be garbage collected.
        # self.large_list = None
        mb_memory = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss / 1000
        print("Memory usage: %s MB" % mb_memory)

    def test_memory1(self):
        pass

    def test_memory2(self):
        pass

    def test_memory3(self):
        pass

    def test_memory4(self):
        pass

    def test_memory5(self):
        pass
Run Code Online (Sandbox Code Playgroud)

运行:

py.test test_large_memory.py -s -v
Run Code Online (Sandbox Code Playgroud)

最简单的解决方案是显式清除分配给的任何大对象self或需要清理的任何对象(例如数据库连接)tearDown.

参考文献:
Python漏洞TestCase
问题11798:测试用例不是运行后收集的垃圾 - Python跟踪器


Mar*_*ers 5

您根本不必删除所有这些属性.

TestCase实例最终将被丢弃tearDown; 每个测试都运行一个新的,干净的,有光泽的,最重要的是空的新实例.实例上的任何属性都将被清除,一旦测试套件运行,引用计数就会丢失,如果实例是对这些值的唯一引用,它们将从内存中消失.

引用unittest.TestCase()文档:

class unittest.TestCase(methodName='runTest')
Run Code Online (Sandbox Code Playgroud)

TestCase该类的实例代表unittest Universe中最小的可测试单元.[...].每个实例TestCase将运行一个测试方法:名为methodName的方法.

强调我的 ; 测试运行器将创建这些实例,传入要运行的测试方法的名称; 如果你有方法test_footest_bar,将创建的实例传递这些名称.

使用它tearDown来清除测试实例之外的东西; 删除临时文件,删除模拟补丁,关闭数据库连接等.TestCase一旦所有测试都运行,实例将最终完成(从内存中删除),因为测试运行器可能希望稍后访问每个测试以提供有关它们的详细信息.全套运行的结束.