Python nose单元测试已经生成了太多客户端

时间:2013-07-31 15:49:34

标签: python-3.x sqlalchemy pyramid psycopg2 nose

我使用的是python 3.3,pyramid,sqlalchemy,psygopg2。我使用测试postgres db进行单元测试。我有101个单元测试设置为鼻子运行。在测试101我得到:

  

nose.proxy.OperationalError :( OperationalError)致命:抱歉,已有太多客户

从追溯中可以看出,异常是在

中引发的
  

....... / venv / lib / python3.3 / site-packages / SQLAlchemy-0.8.2-py3.3.egg / sqlalchemy / pool.py&#34;,第368行,在__connect < / p>

   connection = self.__pool._creator()

也许每次测试后tearDown()都没有运行?一次不是Postgresql 100的连接池限制吗?

这是我的BaseTest课程:

class BaseTest(object):
    def setup(self):
        self.request = testing.DummyRequest()
        self.config = testing.setUp(request=self.request)
        self.config.scan('../models')
        sqlalchemy_url = 'postgresql://<user>:<pass>@localhost:5432/<db>'
        engine = create_engine(sqlalchemy_url)
        DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
        DBSession.configure(bind=engine)
        Base.metadata.bind = engine
        Base.metadata.create_all(engine)
        self.dbsession = DBSession

    def tearDown(self):
        testing.teardown()

我的测试类继承自BaseTest:

class TestUser(BaseTest):
    def __init__(self, dbsession = None):
        if dbsession:
            self.dbsession = dbsession

    def test_create_user(self):
        ......
        ......

其中一个测试类测试多对多关系,因此在该测试类中,我首先创建满足外键关系所需的记录:

from tests.test_user import TestUser
from tests.test_app import TestApp
class TestAppUser(BaseTest):
    def __init__(self, dbsession = None):
        if dbsession:
            self.dbsession = dbsession

    def create_app_user(self):
        test_app = TestApp(self.dbsession)
        test_user = TestUser(self.dbsession)
        test_app.request = testing.DummyRequest()
        test_user.request = testing.DummyRequest()
        app = test_app.create_app()
        user = test_user.create_user()
        ......

我将dbsession传递给TestApp和TestUser类......我认为这是问题的根源,但我不确定。

非常感谢任何帮助。感谢。

1 个答案:

答案 0 :(得分:1)

Pyramid与SQLAlchemy无关。 Pyramid的API中没有任何地方可以以Pyramid真正关心的方式链接任何SQLAlchemy配置。因此,金字塔的testing.tearDown()对连接没有任何作用。怎么可能呢?它不知道它们存在。

您正在使用带有单元测试的作用域会话,这实际上没有多大意义,因为您的单元测试可能没有线程化。所以现在你正在创建threadlocal会话而不是清理它们。它们不是垃圾收集因为它们是线程本地的。您也没有手动关闭这些连接,因此连接池认为它们仍在使用中。

您的测试中是否需要ZopeTransactionExtension?您是在测试中使用transaction包还是pyramid_tm?在测试中,如果你不知道什么是什么,那么它就不应该存在。您是通过create_all()方法致电setUp()了吗?因为我会对数据库进行内省并在每个请求上创建表格,这将会很慢。哎哟。

class BaseTest(object):
    def setUp(self):
        self.request = testing.DummyRequest()
        self.config = testing.setUp(request=self.request)
        self.config.scan('../models')
        sqlalchemy_url = 'postgresql://<user>:<pass>@localhost:5432/<db>'
        self.engine = create_engine(sqlalchemy_url)
        Base.metadata.create_all(bind=self.engine)
        self.sessionmaker = sessionmaker(bind=self.engine)
        self.sessions = []

    def makeSession(self, autoclose=True):
        session = self.sessionmaker()
        if autoclose:
            self.sessions.append(session)

    def tearDown(self):
        for session in self.sessions:
            session.close()
        self.engine.dispose()
        testing.teardown()