Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何确保使用nosetest调用tearDown(在测试中出现未捕获异常的情况下)?_Python_Unit Testing_Sqlalchemy - Fatal编程技术网

Python 如何确保使用nosetest调用tearDown(在测试中出现未捕获异常的情况下)?

Python 如何确保使用nosetest调用tearDown(在测试中出现未捕获异常的情况下)?,python,unit-testing,sqlalchemy,Python,Unit Testing,Sqlalchemy,我有一个带有设置和拆卸方法的测试用例: TESTCONF = SafeConfigParser(...) ENGINE = create_engine(TESTCONF.get('database', 'dsn')) class TestBase(TestCase): def setUp(self): self.config = TESTCONF self.connection = ENGINE.connect() self.trans

我有一个带有
设置
拆卸
方法的测试用例:

TESTCONF = SafeConfigParser(...)
ENGINE = create_engine(TESTCONF.get('database', 'dsn'))

class TestBase(TestCase):

    def setUp(self):
        self.config = TESTCONF
        self.connection = ENGINE.connect()
        self.trans = self.connection.begin()
        self.session = Session(bind=self.connection)

    def tearDown(self):
        print "post teardown 0", ENGINE.pool.status()
        self.trans.rollback()
        print "post teardown 1", ENGINE.pool.status()
        self.session.close()
        print "post teardown 2", ENGINE.pool.status()
        self.connection.close()
        print "post teardown 3", ENGINE.pool.status(), "\n"
所有与DB相关的测试用例都继承自此类。似乎并不总是调用
tearDown
。我很难定位错误。在某一点上,测试运行程序挂起

self.connection = ENGINE.connect()
我假设并不总是调用
close
方法来释放池中的连接

你知道要找什么吗

更新:我如何添加了一些打印语句(在上面的示例代码中也添加了它们),我最初的想法是正确的。某些连接未正确关闭,也未返回池。测试中的所有“错误”(而不是“失败”)都会发生这种情况。下面的代码块显示了我使用上述
tearDown
方法得到的输出(为了简洁起见,提前切断)。如您所见,有错误的行(那些以
Epre
而不是
.pre
开头的行)不调用任何
拆卸
行。甚至没有显示
post-tearDown 0
消息

我现在已经将错误追溯到使用
self.assertRaisesRegEx
而不是
self.assertRaisesRegExp
,因此异常是在单元测试中引发的,而不是在测试代码中

pre setup Pool size: 5  Connections in pool: 0 Current Overflow: -5 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
'TestCommonBase' object has no attribute 'assertRaisesRegex'
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
'TestCommonBase' object has no attribute 'assertRaisesRegex'
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0 

.SSpre setup Pool size: 5  Connections in pool: 1 Current Overflow: -4 Current Checked out connections: 0
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
ESpre setup Pool size: 5  Connections in pool: 0 Current Overflow: -4 Current Checked out connections: 1
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -3 Current Checked out connections: 2
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: -3 Current Checked out connections: 2
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -2 Current Checked out connections: 3
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: -2 Current Checked out connections: 3
post connect Pool size: 5  Connections in pool: 0 Current Overflow: -1 Current Checked out connections: 4
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: -1 Current Checked out connections: 4
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 0 Current Checked out connections: 5
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 0 Current Checked out connections: 5
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 1 Current Checked out connections: 6
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 1 Current Checked out connections: 6
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 2 Current Checked out connections: 7
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 2 Current Checked out connections: 7
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 3 Current Checked out connections: 8
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 3 Current Checked out connections: 8
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 4 Current Checked out connections: 9
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 4 Current Checked out connections: 9
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 5 Current Checked out connections: 10
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 5 Current Checked out connections: 10
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 6 Current Checked out connections: 11
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 6 Current Checked out connections: 11
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 7 Current Checked out connections: 12
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 7 Current Checked out connections: 12
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 8 Current Checked out connections: 13
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 8 Current Checked out connections: 13
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 9 Current Checked out connections: 14
Epre setup Pool size: 5  Connections in pool: 0 Current Overflow: 9 Current Checked out connections: 14
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: 10 Current Checked out connections: 14 

.pre setup Pool size: 5  Connections in pool: 1 Current Overflow: 10 Current Checked out connections: 14
post connect Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
Epost teardown 0 Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 1 Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 2 Pool size: 5  Connections in pool: 0 Current Overflow: 10 Current Checked out connections: 15
post teardown 3 Pool size: 5  Connections in pool: 1 Current Overflow: 10 Current Checked out connections: 14 
其他详情: 为了回答这个问题,我写了一个很小的可复制的例子。不幸的是,一个人没有表现出这种行为:

class MyTest(TestCase):
    """
    Example test case meant to demonstrate that ``tearDown`` is not called.

    It turns out, in this case, ``tearDown`` *is* called as expected!
    """

    def setUp(self):
        print "setup"

    def tearDown(self):
        print "tearDown"

    def test_failing(self):
        print int('yes')


if __name__ == '__main__':
    main()
那么,是什么使这个示例与我的实际代码不同呢?为什么在这个简单的示例中调用了
tearDown
,而在我的生产代码中没有调用


我将继续调查…

如果您怀疑没有调用
tearDown
,那么我可以建议您在测试中使用上下文管理器进行资源分配。
with
语句保证如果
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()方法返回时没有错误,那么将始终调用
\uuuuuuuuuuuuuuuuuuuuuuuuu

下面是您修改为使用上下文管理器进行连接分配的示例:

TESTCONF = SafeConfigParser(...)
ENGINE = create_engine(TESTCONF.get('database', 'dsn'))

class DBConnection(object):
    def __init__(self, engine):
        self.engine = engine

    def __enter__(self):
        self.connection = engine.connect()
        self.trans = self.connection.begin()
        self.session = Session(bind=self.connection)
        # return value can be accessed using `as` directive
        return self.connection, self.trans, self.session

    def __exit__(self, exc_type, exc_val, traceback):
        self.trans.rollback()
        self.session.close()
        self.connection.close()


class TestBase(unittest.TestCase):

    def setUp(self):
        self.config = TESTCONF

    def run(self, result=None):
        with DBConnection(ENGINE) as db_conn:
            self.connection, self.trans, self.session = db_conn
            super(MyTest, self).run(result)
如果DBConnection类看起来太庞大,也可以使用contextlib:

from contextlib import contextmanager

@contextmanager
def DBConnection(engine):
    connection = engine.connect()
    trans = connection.begin()
    session = Session(bind=connection)
    yield connection, trans, session
    trans.close()
    session.close()
    connection.close()

看来你在这里做了很多假设。到底是什么让你认为拆卸没有被调用?如果你把一个print语句放在“tearDown”方法中,或者其他一些很容易被识别为已运行的语句(比如写入文件),你会看到该语句吗?@MarkHildreth对不起,我不得不匆忙地写下这个问题(赶火车)。我试过打印一份声明。我没有看到输出。一旦我回到办公室,我会尝试写一个文件。Nosetests拦截stdout,因此在这种情况下,打印可能不是一种可靠的调试技术。@MarkHildreth我现在有更多的时间进行调查,并为问题添加了更多细节。我仍然很困惑为什么会发生这种情况。我将尝试写一个独立的例子来重现这种行为。但“简单”的演示代码似乎不足以触发错误:(这是一个有趣的想法。我会尝试一下。但最让我担心的是,
tearDown
无论如何都应该被调用。使用上下文管理器似乎是多余的。但值得一试。仅供参考:我还没有尝试过你的解决方案,但同时为有关我的发现的问题添加了更多细节。嗯,在我现在正在使用你的解决方案,无所事事,一事无成。几天后我会接受。我也在给其他人一个插话的机会。你好,我是过去的:)使用
@contextmanager
的解决方案是干净的,但它也将无法正确关闭会话,除非在
yield
语句周围添加
try/finally
块。并关闭该
finally
块中的对象!